WebGPU入门初识

发布于:2025-02-11 ⋅ 阅读:(30) ⋅ 点赞:(0)

什么是 WebGPU?

WebGPU 是一种现代图形 API,旨在取代 WebGL,提供更高性能和更灵活的 GPU 加速能力。它基于 Vulkan、Metal 和 Direct3D 12,为 Web 开发者带来了类似于原生图形 API 的性能和控制力。

与 WebGL 不同,WebGPU 提供了对计算着色器和低级 GPU 操作的直接支持,使开发者能够充分利用 GPU的潜力来处理图形渲染和并行计算任务。


WebGPU 基本概念详解

在 WebGPU 开发中,理解其核心概念至关重要。以下是 WebGPU 的基本概念及相应的实例代码,帮助初学者直观理解。


1. GPU 适配器(GPUAdapter)和设备(GPUDevice)

概念

  • GPUAdapter:表示浏览器访问到的可用 GPU,类似于桥梁,连接 Web 应用与底层硬件。
  • GPUDevice:表示具体的 GPU 设备,用于执行渲染或计算任务。

示例

const adapter = await navigator.gpu.requestAdapter(); // 获取适配器
const device = await adapter.requestDevice();        // 请求设备
console.log("Adapter:", adapter);
console.log("Device:", device);

2. 管线(Pipeline)

概念

  • 渲染管线(Render Pipeline):定义顶点着色器和片元着色器的工作流程。
  • 计算管线(Compute Pipeline):专用于非图形任务的 GPU 计算。

渲染管线示例

const pipeline = device.createRenderPipeline({
  vertex: {
    module: shaderModule,
    entryPoint: "vertex_main",
  },
  fragment: {
    module: shaderModule,
    entryPoint: "fragment_main",
    targets: [{ format: "bgra8unorm" }],
  },
  primitive: {
    topology: "triangle-list", // 图元类型
  },
});
console.log("Pipeline Created:", pipeline);

3. 着色器(Shader)

概念

  • 着色器是运行在 GPU 上的程序,用于处理图形数据。WebGPU 使用 WGSL 编写。
  • 常见的着色器类型:
    • 顶点着色器:处理每个顶点的位置。
    • 片元着色器:计算像素的颜色。

示例

const shaderCode = `
  @vertex
  fn vertex_main(@location(0) position: vec4<f32>) -> @builtin(position) vec4<f32> {
    return position; // 顶点位置传递给片元着色器
  }

  @fragment
  fn fragment_main() -> @location(0) vec4<f32> {
    return vec4(1.0, 0.0, 0.0, 1.0); // 输出红色
  }
`;
const shaderModule = device.createShaderModule({ code: shaderCode });
console.log("Shader Module Created:", shaderModule);

4. 命令编码器(Command Encoder)

概念

  • 用于生成命令缓冲区,将渲染或计算任务发送到 GPU 执行。

示例

const commandEncoder = device.createCommandEncoder();
const passEncoder = commandEncoder.beginRenderPass({
  colorAttachments: [{
    view: context.getCurrentTexture().createView(),
    loadOp: "clear", // 清除屏幕
    clearValue: { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }, // 背景色
    storeOp: "store",
  }],
});

passEncoder.setPipeline(pipeline);
passEncoder.draw(3, 1, 0, 0); // 绘制三角形
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);

5. 缓冲区(Buffer)

概念

  • GPU 缓冲区存储顶点数据、索引数据、常量等。
  • 数据以二进制格式存储,传递给着色器。

示例

const vertices = new Float32Array([
  0.0,  0.5, // 顶点 1
 -0.5, -0.5, // 顶点 2
  0.5, -0.5, // 顶点 3
]);

const vertexBuffer = device.createBuffer({
  size: vertices.byteLength,
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
device.queue.writeBuffer(vertexBuffer, 0, vertices);
console.log("Vertex Buffer Created:", vertexBuffer);

6. 纹理(Texture)

概念

  • 纹理用于存储图像或多维数据,常用于渲染图片或生成复杂效果。

示例

const texture = device.createTexture({
  size: [256, 256, 1],
  format: "rgba8unorm",
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
});
console.log("Texture Created:", texture);

WebGPU 基本示例

以下是一个简单的 WebGPU 应用示例,绘制一个彩色的三角形。

HTML 模板
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebGPU 三角形</title>
</head>
<body>
  <canvas id="gpuCanvas"></canvas>
  <script src="app.js"></script>
</body>
</html>
JavaScript 实现(app.js
(async () => {
  // 初始化 GPU
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();
  const canvas = document.getElementById("gpuCanvas");
  const context = canvas.getContext("webgpu");
  context.configure({
    device: device,
    format: "bgra8unorm",
  });

  // 顶点数据
  const vertices = 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:蓝色
  ]);
  const vertexBuffer = device.createBuffer({
    size: vertices.byteLength,
    usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
  });
  device.queue.writeBuffer(vertexBuffer, 0, vertices);

  // 着色器代码
  const shaderCode = `
    @vertex
    fn vertex_main(@location(0) position: vec2<f32>, @location(1) color: vec3<f32>) -> @builtin(position) vec4<f32> {
      return vec4(position, 0.0, 1.0);
    }

    @fragment
    fn fragment_main(@location(1) color: vec3<f32>) -> @location(0) vec4<f32> {
      return vec4(color, 1.0);
    }
  `;
  const shaderModule = device.createShaderModule({ code: shaderCode });

  // 渲染管线
  const pipeline = device.createRenderPipeline({
    vertex: {
      module: shaderModule,
      entryPoint: "vertex_main",
      buffers: [
        {
          arrayStride: 5 * 4, // 每个顶点占 5 个 float
          attributes: [
            { shaderLocation: 0, offset: 0, format: "float32x2" }, // 位置
            { shaderLocation: 1, offset: 2 * 4, format: "float32x3" }, // 颜色
          ],
        },
      ],
    },
    fragment: {
      module: shaderModule,
      entryPoint: "fragment_main",
      targets: [{ format: "bgra8unorm" }],
    },
    primitive: { topology: "triangle-list" },
  });

  // 渲染
  const commandEncoder = device.createCommandEncoder();
  const passEncoder = commandEncoder.beginRenderPass({
    colorAttachments: [{
      view: context.getCurrentTexture().createView(),
      loadOp: "clear",
      clearValue: { r: 0.1, g: 0.1, b: 0.1, a: 1.0 },
      storeOp: "store",
    }],
  });
  passEncoder.setPipeline(pipeline);
  passEncoder.setVertexBuffer(0, vertexBuffer);
  passEncoder.draw(3, 1, 0, 0); // 绘制三角形
  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);
})();

代码解析

  1. GPU 初始化

    • navigator.gpu.requestAdapter() 请求 GPU 适配器。
    • adapter.requestDevice() 获取 GPU 设备。
  2. Canvas 配置
    使用 getPreferredCanvasFormat() 确保兼容性。

  3. 顶点数据

    • 包含位置和颜色信息。
    • 使用 Float32Array 存储。
  4. 着色器编写

    • 顶点着色器处理每个顶点的位置。
    • 片元着色器确定像素的颜色。
  5. 渲染管线
    定义顶点缓冲区格式和着色器入口。

  6. 渲染流程

    • 配置 RenderPass
    • 通过命令编码器将绘图命令提交到 GPU。

输出结果

运行代码后,您将在 Canvas 中看到一个红、绿、蓝三色的三角形。这是 WebGPU 基础应用的一个完整流程。


进一步学习方向

  1. 深入了解 WGSL
    学习 WebGPU 的着色器语言,优化渲染效果。

  2. 纹理处理
    实现纹理映射,加载外部图片。

  3. 计算着色器
    探索 WebGPU 的非图形计算能力。

  4. 性能优化
    掌握高效的资源管理和渲染技术。

欢迎各位随时交流~


网站公告

今日签到

点亮在社区的每一天
去签到