WebGPU圖形程式設計(2):構建一個單色的三角形<學習引自徐博士教程>
阿新 • • 發佈:2022-01-18
非常興奮,我堅持了下來,開始更新我的第二篇部落格,還是關於WebGPU的,我在學習過程中,對這項技術非常感興趣,即使它非常抽象,難以理解,因為我看到未來Web3D的發展,WebGPU會成為主流技術,學習這項技術的前景會更加光明。
本節來建立單色三角形,並通過輸入color四元陣列數值對三角形顏色進行改變.
一、使用搭建好的開發環境進行所有軟體包的安裝
使用上一章節搭建好的所有配置檔案,先進行一步所有軟體包的安裝(這是徐博士教程裡的步驟),為的是產生node_modules資料夾內的所有配置檔案,但我又在想,我第一節已經把所有配置好的檔案配置好了,並且已經有node_modules檔案夾了,npm install不是多此一舉麼(可能是我對開發環境的搭建還沒有學習深刻)?
npm install
徐博士執行完上述命令列後,才生成node_modules資料夾,我試著下載它的原始碼,他的原始碼裡面沒有包含node_modules資料夾,我執行npm install後成功配置完所有檔案,這裡我猜測是package.json已經寫入了配置檔案及版本號,install可能是自動進行版本號識別安裝;
二、修改index.html內容
需要你對dist資料夾下的index.html<body>內的程式碼內容進行修改
程式碼如下:
<div> <h1>Create Triangle</h1><br> <!--主標題--> <label>Color:</label> <!--表單標題--> <input type="text" id="id-color" value="(1.0,1.0,1.0,1.0)"><!--表單的型別及數值--> <button type="button" id="id-btn">Change Color</button><!--button型別及按鍵名稱--> <br><br> <canvas id="canvas-webgpu" width="640" height="480"></canvas><!--使用canvas畫布來繪製webgpu圖形--> </div>
三、新增管線著色檔案
在src資料夾下,新增sharder.ts檔案,用來寫入WGSL著色器,這裡面的著色器用法和宣告,暫時不需要特別理解,徐博士也是簡單了描述了vertex和fragment兩種著色器,webgpu使用四維向量來渲染三維圖形,之後再詳細學習檢視WGSL使用。
程式碼如下:
export const Shaders = (color:string) => { const vertex = ` [[stage(vertex)]] fn main([[builtin(vertex_index)]] VertexIndex: u32) -> [[builtin(position)]] vec4<f32> { var pos = array<vec2<f32>, 3>( vec2<f32>(0.0, 0.5), vec2<f32>(-0.5, -0.5), vec2<f32>(0.5, -0.5)); return vec4<f32>(pos[VertexIndex], 0.0, 1.0); //webgpu使用四維向量來渲染三維圖形 } `; const fragment = ` [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> { return vec4<f32>${color}; } `; return {vertex, fragment}; } export const Shaders1 = (color:string) => { const vertex = ` var pos = array<vec2<f32>, 3>( vec2<f32>(0.0, 0.5), vec2<f32>(-0.5, -0.5), vec2<f32>(0.5, -0.5)); [[stage(vertex)]] fn main([[builtin(vertex_index)]] VertexIndex: u32) -> [[builtin(position)]] vec4<f32> { return vec4<f32>(pos[VertexIndex], 0.0, 1.0); } `; const fragment = ` [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> { return vec4<f32>${color}; } `; return {vertex, fragment}; } export const ShadersOld = (color:string) => { const vertex = ` const pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>( vec2<f32>(0.0, 0.5), vec2<f32>(-0.5, -0.5), vec2<f32>(0.5, -0.5)); [[builtin(position)]] var<out> Position : vec4<f32>; [[builtin(vertex_idx)]] var<in> VertexIndex : i32; [[stage(vertex)]] fn main() -> void { Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0); return; } `; const fragment = ` [[location(0)]] var<out> outColor : vec4<f32>; [[stage(fragment)]] fn main() -> void { outColor = vec4<f32>${color}; return; } `; return {vertex, fragment}; }
四、使用typescript來編寫webgpu的控制程式碼去控制命令GPU
開啟src資料夾下的main.ts檔案,進行程式碼編寫,同樣這一大段程式碼我也看不懂,但需要知道檔案用處,具體的API使用方法可以參照API文件https://www.orillusion.com/zh/webgpu.html#security;
程式碼如下:
import $ from 'jquery'; import { CheckWebGPU } from './helper'; import { Shaders } from './sharder'; const CreateTriangle = async (color='(1.0,1.0,1.0,1.0)') => { const checkgpu = CheckWebGPU(); if(checkgpu.includes('Your current browser does not support WebGPU!')){ console.log(checkgpu); throw('Your current browser does not support WebGPU!'); } const canvas = document.getElementById('canvas-webgpu') as HTMLCanvasElement; const adapter = await navigator.gpu?.requestAdapter() as GPUAdapter; const device = await adapter?.requestDevice() as GPUDevice; const context = canvas.getContext('webgpu') as unknown as GPUCanvasContext; const format = 'bgra8unorm'; /*const swapChain = context.configureSwapChain({ device: device, format: format, });*/ context.configure({ device: device, format: format, }); const shader = Shaders(color); const pipeline = device.createRenderPipeline({ vertex: { module: device.createShaderModule({ code: shader.vertex }), entryPoint: "main" }, fragment: { module: device.createShaderModule({ code: shader.fragment }), entryPoint: "main", targets: [{ format: format as GPUTextureFormat }] }, primitive:{ topology: "triangle-list", } }); const commandEncoder = device.createCommandEncoder(); const textureView = context.getCurrentTexture().createView(); const renderPass = commandEncoder.beginRenderPass({ colorAttachments: [{ view: textureView, loadValue: { r: 0.5, g: 0.5, b: 0.8, a: 1.0 }, //background color storeOp: 'store' }] }); renderPass.setPipeline(pipeline); renderPass.draw(3, 1, 0, 0); renderPass.endPass(); device.queue.submit([commandEncoder.finish()]); } CreateTriangle(); $('#id-btn').on('click', ()=>{ const color = $('#id-color').val() as string; CreateTriangle(color); });
五、到此我們所有程式碼編寫完成
你可以看到以上步驟,我們對index.html檔案寫頁面展示和呼叫介面、再新建我們的管線程式碼sharder.ts編寫渲染管線、再對mian.ts檔案使用typescript讓webgpuAPI對GPU命令指令;
開啟網頁視窗你可以看到建立成功。
需要注意的一點,也是我過程中犯的錯誤,就是在html中“”內的程式碼內容不可以有空格,否則會生成失敗的!