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

 

posted @ 2022-01-20 16:23  支阿怪🔥  阅读(273)  评论(0编辑  收藏  举报