1.包含webgpu的初始化
2.三角形顶点缓冲的创建以及将cpu数据填充到gpu里
3.webgpu里着色器的编写,以及通过代码创建webgpu的着色器程序对象
4.通过顶点和像素阶段的描述创建一个渲染管线
话不多说直接贴代码:
<html> <head> <meta charset="utf-8"> <title>WebGPU Hello Triangle</title> <style> body { font-family: system-ui; color: #f7f7ff; background-color: rgb(38, 38, 38); text-align: center; }canvas { display: block; margin: 0 auto; width: 100%; height: 100%; } </style> <script type="module"> // 获取canvas元素 const canvas = document.getElementById("canvas"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; // 获取WebGPU上下文 const context = canvas.getContext("webgpu"); // 定义顶点数据,三个顶点组成一个三角形 const vertices = new Float32Array([ -0.5, -0.5, 1.0, 0.0, 0.0, 1.0, // 左下角 0.5, -0.5, 0.0, 1.0, 0.0, 1.0, // 右下角 0.0, 0.5, 0.0, 0.0, 1.0, 1.0, // 顶点 ]); // 定义顶点着色器代码,使用WGSL语言 const wgslSource = ` struct Vertex { @builtin(position) Position: vec4<f32>, // 顶点着色器输出的位置 @location(0) color: vec4<f32>, // 顶点着色器输出的颜色 } // 顶点着色器 @vertex fn vsmain( @builtin(vertex_index) VertexIndex: u32, // 顶点着色器内建的顶点索引 @location(0) position: vec2<f32>, // 输入顶点的位置 @location(1) color: vec4<f32> // 输入顶点的颜色 ) -> Vertex { var vertex_out : Vertex; vertex_out.Position = vec4<f32>(position, 0.0, 1.0); vertex_out.color = color; return vertex_out; } // 像素着色器 @fragment fn fsmain(in: Vertex) -> @location(0) vec4<f32> { return in.color; } `; // 初始化WebGPU相关对象 async function initWebGPU() { // 获取适配器对象,表示GPU的物理设备 const adapter = await navigator.gpu.requestAdapter(); // 获取设备对象,表示GPU的会话 const device = await adapter.requestDevice(); // 配置上下文对象,指定设备和像素格式 const format = "bgra8unorm"; context.configure({ device: device, format: format, }); // 创建顶点缓冲区,用于存储顶点数据 const vertexBuffer = device.createBuffer({ size: vertices.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, mappedAtCreation: true, }); new Float32Array(vertexBuffer.getMappedRange()).set(vertices); vertexBuffer.unmap(); // 创建着色器模块,用于编译着色器代码 const shaderModule = device.createShaderModule({ code: wgslSource }); // 定义顶点输入的数据布局,以及顶点着色阶段的其它信息 const vertexSize = 4 * 6; const colorOffset = 4 * 2; const positionAttributeState = { format: "float32x2", offset: 0, shaderLocation: 0, }; const colorAttributeState = { format: "float32x4", offset: colorOffset, shaderLocation: 1, } const vertexBufferState = { arrayStride: vertexSize, stepMode: "vertex", attributes: [positionAttributeState, colorAttributeState], // 顶点输入属性包含一个位置和颜色 };
const vertexStageDescriptor = { buffers: [vertexBufferState], // 顶点着色的顶点缓冲 module: shaderModule, // 顶点着色的shader entryPoint: "vsmain" // 入口函数 };
const fragmentStageDescriptor = { module: shaderModule, entryPoint: "fsmain", targets: [ {format: "bgra8unorm" }, ], }; const renderPipelineDescriptor = { layout: 'auto', vertex: vertexStageDescriptor, fragment: fragmentStageDescriptor, primitive: {topology: "triangle-list" }, }; // 创建渲染管线,用于指定渲染流程和状态 const pipeline = device.createRenderPipeline(renderPipelineDescriptor); return { device, pipeline, vertexBuffer }; // 返回相关对象 } // 渲染函数,用于绘制图形 function render({ device, pipeline, vertexBuffer }) { // 获取颜色纹理,用于存储渲染结果 const textureView = context.getCurrentTexture().createView(); // 创建命令编码器,用于记录渲染命令 const commandEncoder = device.createCommandEncoder(); const colorAttachmentDescriptor = { view: textureView, loadOp: "clear", storeOp: "store", clearColor: [0.5, 0.5, 0.5, 1] }; /* GPURenderPassDescriptor */ const renderPassDescriptor = { colorAttachments: [colorAttachmentDescriptor] }; // 开始一个渲染通道,指定颜色附件和清除颜色 const renderPass = commandEncoder.beginRenderPass(renderPassDescriptor); // 设置渲染管线 renderPass.setPipeline(pipeline); // 设置顶点缓冲区 renderPass.setVertexBuffer(0, vertexBuffer); // 绘制三个顶点,组成一个三角形 renderPass.draw(3, 1, 0, 0); // 结束渲染通道 renderPass.end(); // 结束命令编码器,获取命令缓冲区 const commandBuffer = commandEncoder.finish(); // 将命令缓冲区提交给GPU队列,执行渲染命令 device.queue.submit([commandBuffer]); } // 调用初始化函数,然后调用渲染函数 initWebGPU().then(render); </script> </head> <body> <canvas id="canvas" ></canvas> </body> </html> 效果如下:
标签:const,渲染,0.0,webgpu,简短,device,顶点,三角形,着色器 From: https://www.cnblogs.com/zzatp/p/17783299.html