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 6title> 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 Primitivesh1><br> 13 <label><b>Select a primitive type:Select>b>label> 14 <select id = "id-primitive"> 15 <option value="triangle-list"> triangle-listoption> 16 <option value="triangle-strip"> triangle-stripoption> 17 18 select> 19 <br><br> 20 <canvas id="canvas-webgpu" width="640" height="480">canvas> 21 div> 22 <script src="main.bundle.js">script> 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; 5 [[location(0)]] vColor : vec4 ; 6 }; 7 8 [[stage(vertex)]] 9 fn main([[builtin(vertex_index)]] VertexIndex: u32) -> Output { 10 var pos : array , 9> = array , 9>( 11 vec2 (-0.63, 0.80), 12 vec2 (-0.65, 0.20), 13 vec2 (-0.20, 0.60), 14 vec2 (-0.37, -0.07), 15 vec2 ( 0.05, 0.18), 16 vec2 (-0.13, -0.40), 17 vec2 ( 0.30, -0.13), 18 vec2 ( 0.13, -0.64), 19 vec2 ( 0.70, -0.30) 20 ); 21 22 var color : array , 9> = array , 9>( 23 vec3 (1.0, 0.0, 0.0), 24 vec3 (0.0, 1.0, 0.0), 25 vec3 (0.0, 0.0, 1.0), 26 vec3 (1.0, 0.0, 0.0), 27 vec3 (0.0, 1.0, 0.0), 28 vec3 (0.0, 0.0, 1.0), 29 vec3 (1.0, 0.0, 0.0), 30 vec3 (0.0, 1.0, 0.0), 31 vec3 (0.0, 0.0, 1.0), 32 ); 33 34 var output: Output; 35 output.Position = vec4 (pos[VertexIndex], 0.0, 1.0); 36 output.vColor = vec4 (color[VertexIndex], 1.0); 37 return output; 38 }` 39 40 const fragment = ` 41 [[stage(fragment)]] 42 fn main([[location(0)]] vColor: vec4 ) -> [[location(0)]] vec4 { 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着色器。