WebGPU图形编程(3):构建三角形图元<学习引自徐博士教程>
一、首先修改你的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 <meta charset="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着色器。