WebGPU入门(三):命令编码器、渲染通道及最终绘制

173 阅读2分钟

一、命令编码器与渲染通道

通过获取到的GPU设备对象device的.createCommandEncoder方法创建一个命令编码器,命令编码器能够控制渲染管线渲染输出像素数据

所有的顶点缓冲区、渲染管线、着色器配置都是不会执行的,如果想要在GPU上执行,还需要配置GPU命令编码器对象实现

然后通过命令编码器的.beginRenderPass方法创建渲染通道

渲染通道:渲染通道是一个渲染过程,包括灯光、阴影、高光等过程,并将结果累加到最终呈现的结果上

// 创建GPU命令编码器对象
const commandEncoder = device.createCommandEncoder();
const renderPass = commandEncoder.beginRenderPass({...(参数)});

经过渲染管线各个单元处理的片元数据会存储在显存的颜色缓冲区中,该缓冲区的作用就是存储渲染管线输出的像素数据

canvas画布具备一个默认的颜色缓冲区,可以直接使用。如果需要将WebGPU绘制的图形呈现在canvas画布中,需要将绘制结果输出到canvas画布对应的默认颜色缓冲区中

通过配置colorAttachments给渲染通道指定颜色缓冲区,该属性对应一个对象数组,没个对象中对应一个颜色缓冲区,一般情况下配置一个对象即可(除非需要将片元数据存储至多个颜色缓冲区)

colorAttachments对应的对象中有以下几个关键属性:

  • view:视图,表示生成图像配置
  • storeOp,loadOp:像素数据写入颜色缓冲区
  • clearValue:背景颜色
const renderPass = commandEncoder.beginRenderPass({
  colorAttachments: [{
    // 如果需要将其绑定到canvas上就一样要这么写(也就是绑定canvas和渲染结果)
    view: context.getCurrentTexture().createView(),
    storeOp: 'store',
    loadOp: 'clear',
    clearValue: {r: 0.5, g: 0.5, b: 0.5, a: 1.0}
  }]
});

由于渲染通道可以有多个,需要通过.setPipeline设置需要控制渲染管线

renderPass.setPipeline(pipeline);

完成渲染管线与渲染通道的配置后,需要绑定顶点缓冲区

renderPass.setVertexBuffer(0, vertexBuffer);

image-20230510143535727

二、绘制

通过渲染通道对象renderPass.draw()方法完成绘制

该方法需要传入一个参数,表示绘制多少个点:renderPass.draw(3)

完成绘制后需要执行renderPass对象的.end()方法结束绘制,执行renderPass.end(),系统内部会标记前渲染通道renderPass已经结束

命令编码器对象commandEncoder执行.finish()方法返回一个命令缓冲区对象,同时会把该编码器相关的WebGL API或方法,编码为GPU指令,存入到返回的命令缓冲区对象中

renderPass.draw(3);
renderPass.end();
// 存至命令缓冲区
const commandBuffer = commandEncoder.finish();

最后使用submit方法通过device的命令队列提交命令缓冲区完成绘制

// const commandEncoder = device.createCommandEncoder();
const commandBuffer = commandEncoder.finish();
// 命令编码器缓冲区中命令传入GPU设备对象的命令队列.queue
device.queue.submit([commandBuffer]);

image-20230510143924578