返回

玩转WebGPU: 从头开始绘制三角形

前端

  1. WebGPU概述

WebGPU是针对Web应用和游戏开发的下一代图形API,它以更简洁、更低级别的编程方式,为开发者提供了更加精细的控制和更高的性能。在使用WebGPU之前,您需要对它有一些基本的了解。

  • 跨平台支持: WebGPU在主流浏览器中拥有广泛的跨平台支持,包括Chrome、Firefox、Safari等,并且还在持续扩展中。
  • 低级别编程: WebGPU采用低级别的编程方式,这意味着您需要直接操作GPU进行渲染。虽然这需要更深入地了解图形学的基础知识,但它也赋予了您对渲染过程的更大控制权。
  • 高性能: WebGPU使用GPU进行渲染,而不是CPU,因此能够提供更高效的图形处理性能。它还支持多线程并行处理,进一步提升了渲染效率。

2. 三角形绘制步骤

我们现在开始逐步绘制一个三角形。首先,我们需要准备一些必要的信息:

  • 顶点数据: 三角形由三个顶点组成,每个顶点由一个位置和一个颜色值组成。
  • 着色器: 着色器是一种特殊的程序,用于将顶点数据转换为像素数据,并应用各种效果。
  • 渲染管线: 渲染管线是一个将顶点数据转换为像素数据的过程,它包括顶点着色器、片段着色器和光栅化等步骤。
  • 纹理: 纹理是一种用于添加细节和色彩的图像,可以应用到三角形上。

3. WebGPU代码实现

现在,我们可以开始编写WebGPU代码来绘制三角形了。

// 初始化WebGPU设备
const device = navigator.gpu.requestAdapter()
  .then(adapter => adapter.requestDevice());

// 创建缓冲区
const vertexBuffer = device.createBuffer({
  size: 3 * 4 * 2, // 3个顶点,每个顶点包含位置和颜色,每个分量4个字节
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});

// 将顶点数据复制到缓冲区
const vertexData = new Float32Array([
  0.0, 0.5, 1.0, 0.0, 0.0, // 顶点1位置和颜色
  -0.5, -0.5, 0.0, 1.0, 0.0, // 顶点2位置和颜色
  0.5, -0.5, 0.0, 0.0, 1.0, // 顶点3位置和颜色
]);
device.queue.writeBuffer(vertexBuffer, 0, vertexData);

// 创建着色器模块
const vertexShaderSource = `
  @vertex
  fn main(@location(0) pos: vec3<f32>,
          @location(1) color: vec3<f32>) -> @builtin(position) vec4<f32> {
    return vec4<f32>(pos, 1.0);
  }
`;

const fragmentShaderSource = `
  @fragment
  fn main() -> @location(0) vec4<f32> {
    return vec4<f32>(1.0, 0.0, 0.0, 1.0);
  }
`;

const vertexShaderModule = device.createShaderModule({
  code: vertexShaderSource,
});

const fragmentShaderModule = device.createShaderModule({
  code: fragmentShaderSource,
});

// 创建渲染管线
const renderPipeline = device.createRenderPipeline({
  vertex: {
    module: vertexShaderModule,
    entryPoint: "main",
  },
  fragment: {
    module: fragmentShaderModule,
    entryPoint: "main",
    targets: [{
      format: "bgra8unorm",
    }],
  },
  primitive: {
    topology: "triangle-list",
  },
});

// 创建纹理
const texture = device.createTexture({
  size: {
    width: 256,
    height: 256,
  },
  format: "bgra8unorm",
  usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
});

// 创建帧缓冲区
const framebuffer = device.createFramebuffer({
  colorAttachments: [
    {
      view: texture.createView(),
      loadOp: "clear",
      storeOp: "store",
    },
  ],
});

// 绘制三角形
const commandEncoder = device.createCommandEncoder();
const renderPassDescriptor = {
  colorAttachments: [
    {
      view: framebuffer.colorAttachments[0].view,
      clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
      loadOp: "clear",
      storeOp: "store",
    },
  ],
};
const renderPass = commandEncoder.beginRenderPass(renderPassDescriptor);
renderPass.setPipeline(renderPipeline);
renderPass.setVertexBuffer(0, vertexBuffer);
renderPass.draw(3); // 绘制3个顶点
renderPass.end();

// 提交命令
device.queue.submit([commandEncoder.finish()]);

4. 总结

我们成功地绘制了一个三角形,这是一个学习WebGPU的绝佳起点。您可以继续探索WebGPU的更多功能,如纹理、光照、阴影等,从而创建更复杂和逼真的3D图形。