WebGPU圖形程式設計(3):構建三角形圖元<學習引自徐博士教程>
阿新 • • 發佈:2022-01-20
一、首先修改你的index.html檔案
請注意主要在html頁面修改新增的是需要加選擇項:"triangle-list"和"triangle-strip",如果你不理解這兩個關鍵詞,移步檢視webgpu文件:https://www.orillusion.com/zh/webgpu.html#primitive-state 的第10.3.2節Primitive state檢視原始狀態可以建立哪些圖元。
1 <!DOCTYPE html> 2 <head> 3 <metacharset="utf-8"> 4 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 5 <title>WebGPU Step-by-Step 6</title> 6 <meta name="description" content=""> 7 <meta name="viewport" content="width=device-width, initial-scale=1"> 8 </head> 9 10 <body> 11 <div> 12 <h1> Create Triangle Primitives</h1><br> <!--主標題--> 13 <label><b>Select a primitive type:</Select></b></label> 14 <select id = "id-primitive"> 15 <option value="triangle-list"> triangle-list</option> 16 <option value="triangle-strip"> triangle-strip</option> 17 18 </select> 19 <br><br> 20 <canvas id="canvas-webgpu" width="640" height="480"></canvas><!--使用canvas畫布來繪製webgpu圖形--> 21 </div> 22 <script src="main.bundle.js"></script><!--指令碼呼叫打包的bundle.js--> 23 </body> 24 </html>
二、接下來修改新增shaders檔案程式碼
主要就是修改vertex和fragment新增為9個頂點和9個顏色,滿足triangle頂點要求。
1 export const Shaders = () => { 2 const vertex = ` 3 struct Output { 4 [[builtin(position)]] Position : vec4<f32>; 5 [[location(0)]] vColor : vec4<f32>; 6 }; 7 8 [[stage(vertex)]] 9 fn main([[builtin(vertex_index)]] VertexIndex: u32) -> Output { 10 var pos : array<vec2<f32>, 9> = array<vec2<f32>, 9>( 11 vec2<f32>(-0.63, 0.80), 12 vec2<f32>(-0.65, 0.20), 13 vec2<f32>(-0.20, 0.60), 14 vec2<f32>(-0.37, -0.07), 15 vec2<f32>( 0.05, 0.18), 16 vec2<f32>(-0.13, -0.40), 17 vec2<f32>( 0.30, -0.13), 18 vec2<f32>( 0.13, -0.64), 19 vec2<f32>( 0.70, -0.30) 20 ); 21 22 var color : array<vec3<f32>, 9> = array<vec3<f32>, 9>( 23 vec3<f32>(1.0, 0.0, 0.0), 24 vec3<f32>(0.0, 1.0, 0.0), 25 vec3<f32>(0.0, 0.0, 1.0), 26 vec3<f32>(1.0, 0.0, 0.0), 27 vec3<f32>(0.0, 1.0, 0.0), 28 vec3<f32>(0.0, 0.0, 1.0), 29 vec3<f32>(1.0, 0.0, 0.0), 30 vec3<f32>(0.0, 1.0, 0.0), 31 vec3<f32>(0.0, 0.0, 1.0), 32 ); 33 34 var output: Output; 35 output.Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0); 36 output.vColor = vec4<f32>(color[VertexIndex], 1.0); 37 return output; 38 }` 39 40 const fragment = ` 41 [[stage(fragment)]] 42 fn main([[location(0)]] vColor: vec4<f32>) -> [[location(0)]] vec4<f32> { 43 return vColor; 44 } 45 `; 46 return {vertex, fragment}; 47 }
三、修改新增main.ts檔案
主要是你的primitiveType需要對應"triangle-list"(每三個頂點建立一個三角形)和"triangle-strip"(先建立一個三角形,之後每新增一個頂點就會新增一個三角形)
import $ from 'jquery'; import { CheckWebGPU } from './helper'; import { Shaders } from './sharder'; const CreatePrimitive = async (primitiveType = 'triangle-list') => { const checkgpu = CheckWebGPU(); if(checkgpu.includes('Your current browser does not support WebGPU!')){ console.log(checkgpu); throw('Your current browser does not support WebGPU!'); } let indexFormat = undefined; if(primitiveType === 'triangle-strip'){ indexFormat = 'uint32' } const canvas = document.getElementById('canvas-webgpu') as HTMLCanvasElement; const adapter = await navigator.gpu.requestAdapter() as GPUAdapter; //建立一個adapter(介面卡)去呼叫介面卡 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(); 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: primitiveType as GPUPrimitiveTopology, stripIndexFormat: indexFormat as GPUIndexFormat //按照三角形繪製 } }); const commandEncoder = device.createCommandEncoder(); //建立指令編碼器CommandEncoder 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(9, 1, 0, 0); renderPass.endPass(); device.queue.submit([commandEncoder.finish()]); //結束指令編碼 } CreatePrimitive(); $('#id-primitive').on('change', ()=>{ const primitiveType = $('#id-primitive').val() as string; CreatePrimitive(primitiveType); });
四、打包檔案
npm run prod
五、完成工作,啟用瀏覽器檢視
其實步驟簡單,重要的是理解main檔案和shaders著色器。