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着色器。