1. 程式人生 > 其它 >WebGPU圖形程式設計(3):構建三角形圖元<學習引自徐博士教程>

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