從 WebGPU 開始:用瀏覽器新一代圖形標準打造高效能 3D 渲染實戰指南

如果你做過前端可視化——比如 3D 地球、圖表大屏、資產拓撲圖——大概率碰過 Three.js 與 WebGL。但 WebGL 已經是十多年前的標準了,瀏覽器圖形的下一站叫 WebGPU:更接近現代 GPU 的設計、更低的 CPU 開銷,還能把 GPU 當平行運算器用。這篇我們從零開始,把第一個 WebGPU 程式跑起來,再接回 Three.js 看看實戰怎麼落地。

一、WebGPU 是什麼?和 WebGL 差在哪?

可以把 WebGL 想成「模仿老式 OpenGL 的相容層」,而 WebGPU 是「原生對接現代圖形 API(Vulkan / Metal / D3D12)」的新通道。

  • 效能:管線(Pipeline)預先編譯驗證,每幀 CPU 開銷大幅下降,大量 draw call 不再是噩夢。
  • Compute Shader:不只畫圖,還能跑通用平行運算——粒子模擬、物理、資料預處理都在 GPU 上完成。
  • 支援度:Chrome / Edge 113+ 已預設支援,Safari 與 Firefox 也已跟進;舊瀏覽器仍需 WebGL 降級方案。

重點:WebGPU 不是 WebGL 的升級版,而是全新 API。設計思路從「全域狀態機」轉為「顯式管線與資源綁定」,心智模型完全不同。

二、步驟 1:檢測支援,取得 Adapter 與 Device

一切從 navigator.gpu 開始。先判斷瀏覽器支不支援,再依序取得轉接器與邏輯設備:

if (!navigator.gpu) {
  alert('此瀏覽器不支援 WebGPU,請降級 WebGL');
}

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

特別注意:device 可能因驅動重置而遺失(lost)。正式專案要監聽 device.lost 事件,做設備重建與狀態恢復。

三、步驟 2:設定 Canvas Context 與渲染管線

接著讓 canvas 的 context 綁定 device,並建立管線。著色器用 WGSL——WebGPU 專屬的著色器語言:

const context = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format, alphaMode: 'opaque' });

const shader = device.createShaderModule({
  code: `
    @vertex
    fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
      var pos = array<vec2f, 3>(
        vec2f(0.0, 0.6), vec2f(-0.6, -0.6), vec2f(0.6, -0.6));
      return vec4f(pos[i], 0.0, 1.0);
    }
    @fragment
    fn fs() -> @location(0) vec4f {
      return vec4f(0.1, 0.7, 0.9, 1.0);
    }
  `
});

const pipeline = device.createRenderPipeline({
  layout: 'auto',
  vertex: { module: shader, entryPoint: 'vs' },
  fragment: { module: shader, entryPoint: 'fs',
    targets: [{ format }] }
});

注意這裡只有「建立」管線,還沒畫任何東西——這就是 WebGPU 的顯式哲學:所有狀態先宣告清楚,執行時零歧義。

四、步驟 3:編碼指令,送出渲染

真正畫圖靠三步:建 CommandEncoder → 開 RenderPass → submit:

const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
  colorAttachments: [{
    view: context.getCurrentTexture().createView(),
    clearValue: { r: 0.05, g: 0.06, b: 0.1, a: 1 },
    loadOp: 'clear',
    storeOp: 'store',
  }]
});
pass.setPipeline(pipeline);
pass.draw(3);          // 畫 3 個頂點
pass.end();
device.queue.submit([encoder.finish()]);

跑起來,canvas 上會出現一個青色三角形——你的第一個 WebGPU 渲染完成。重點:每一幀都是「編碼指令 → 一次性提交」的模式,encoder 用完即棄,不可重複 submit。

五、實戰落地:接回 Three.js 與專案選型

手寫管線適合理解原理,但業務專案不用從零造輪子:

  • Three.js WebGPURenderer:把 WebGLRenderer 換成 WebGPURenderer,場景程式碼幾乎不動,底層自動走 WebGPU,不支援時降級 WebGL2。3D 地球、情報大屏這類既有專案遷移成本最低。
  • TSL(Node Material):Three.js 的節點材質系統,一套材質程式碼同時編譯成 WGSL 與 GLSL,兩種後端都能跑。
  • Compute 場景:十萬級粒子、即時物理模擬,用 compute shader 代替 CPU 循環,幀率提升非常可觀。

特別注意:WebGPU 要求安全上下文(HTTPS 或 localhost),本地開發沒問題,部署正式環境前記得確認。

小結:WebGPU 把瀏覽器變成了現代 GPU 的一等公民——顯式管線、compute shader、更低開銷。建議路徑:先用 Three.js WebGPURenderer 白撿紅利,再視需求深入 WGSL 與 compute 實戰。

互動話題:你的專案有沒有被 WebGL 效能卡過脖子(十萬粒子、3D 地球掉幀)?留言聊聊,下篇可以展開講 compute shader 粒子實戰!