WebGPU图形编程(2):构建一个单色的三角形<学习引自徐博士教程>


非常兴奋,我坚持了下来,开始更新我的第二篇博客,还是关于WebGPU的,我在学习过程中,对这项技术非常感兴趣,即使它非常抽象,难以理解,因为我看到未来Web3D的发展,WebGPU会成为主流技术,学习这项技术的前景会更加光明。

本节来创建单色三角形,并通过输入color四元数组数值对三角形颜色进行改变.

一、使用搭建好的开发环境进行所有软件包的安装

使用上一章节搭建好的所有配置文件,先进行一步所有软件包的安装(这是徐博士教程里的步骤),为的是产生node_modules文件夹内的所有配置文件,但我又在想,我第一节已经把所有配置好的文件配置好了,并且已经有node_modules文件夹了,npm install不是多此一举么(可能是我对开发环境的搭建还没有学习深刻)?

npm install

徐博士执行完上述命令行后,才生成node_modules文件夹,我试着下载它的源代码,他的源码里面没有包含node_modules文件夹,我执行npm install后成功配置完所有文件,这里我猜测是package.json已经写入了配置文件及版本号,install可能是自动进行版本号识别安装;

二、修改index.html内容

需要你对dist文件夹下的index.html内的代码内容进行修改

代码如下:

  <div>
       <h1>Create Triangleh1><br> 
       <label>Color:label> 
       <input type="text" id="id-color" value="(1.0,1.0,1.0,1.0)">
       <button type="button" id="id-btn">Change Colorbutton>
       <br><br>
       <canvas id="canvas-webgpu" width="640" height="480">canvas>
    div>

三、添加管线着色文件

src文件夹下,添加sharder.ts文件,用来写入WGSL着色器,这里面的着色器用法和声明,暂时不需要特别理解,徐博士也是简单了描述了vertex和fragment两种着色器,webgpu使用四维矢量来渲染三维图形,之后再详细学习查看WGSL使用。

代码如下:

export const Shaders = (color:string) => {
    const vertex = `
        [[stage(vertex)]]
        fn main([[builtin(vertex_index)]] VertexIndex: u32) -> [[builtin(position)]] vec4 {
            var pos = array, 3>(
                vec2(0.0, 0.5),
                vec2(-0.5, -0.5),
                vec2(0.5, -0.5));
            return vec4(pos[VertexIndex], 0.0, 1.0);   //webgpu使用四维矢量来渲染三维图形
        }
    `;

    const fragment = `
        [[stage(fragment)]]
        fn main() -> [[location(0)]] vec4 {
            return vec4${color};
        }
    `;
    return {vertex, fragment};
}

export const Shaders1 = (color:string) => {
    const vertex = `
        var pos = array, 3>(
            vec2(0.0, 0.5),
            vec2(-0.5, -0.5),
            vec2(0.5, -0.5));

        [[stage(vertex)]]
        fn main([[builtin(vertex_index)]] VertexIndex: u32) -> [[builtin(position)]] vec4 {
            return vec4(pos[VertexIndex], 0.0, 1.0);
        }
    `;

    const fragment = `
        [[stage(fragment)]]
        fn main() -> [[location(0)]] vec4 {
            return vec4${color};
        }
    `;
    return {vertex, fragment};
}


四、使用typescript来编写webgpu的控制代码去控制命令GPU

打开src文件夹下的main.ts文件,进行代码编写,同样这一大段代码我也看不懂,但需要知道文件用处,具体的API使用方法可以参照API文档https://www.orillusion.com/zh/webgpu.html#security;

代码如下:

import $ from 'jquery';
import { CheckWebGPU } from './helper';
import { Shaders } from './sharder';

const CreateTriangle = async (color='(1.0,1.0,1.0,1.0)') => {
    const checkgpu = CheckWebGPU();
    if(checkgpu.includes('Your current browser does not support WebGPU!')){
        console.log(checkgpu);
        throw('Your current browser does not support WebGPU!');
    }

    const canvas = document.getElementById('canvas-webgpu') as HTMLCanvasElement;        
    const adapter = await navigator.gpu?.requestAdapter() as GPUAdapter;       
    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(color);
    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: "triangle-list",
        }
    });

    const commandEncoder = device.createCommandEncoder();
    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(3, 1, 0, 0);
    renderPass.endPass();

    device.queue.submit([commandEncoder.finish()]);
}

CreateTriangle();
$('#id-btn').on('click', ()=>{
    const color = $('#id-color').val() as string;
    CreateTriangle(color);
});

五、到此我们所有代码编写完成

你可以看到以上步骤,我们对index.html文件写页面展示和调用接口、再新建我们的管线代码sharder.ts编写渲染管线、再对mian.ts文件使用typescript让webgpuAPI对GPU命令指令;

开启网页窗口你可以看到创建成功。

需要注意的一点,也是我过程中犯的错误,就是在html中“”内的代码内容不可以有空格,否则会生成失败的!