先用一句大白話:WebGL 像在瀏覽器裡使用「老派的 OpenGL ES」來畫圖;WebGPU 則把「現代顯示卡的工作方式(Vulkan / Metal / Direct3D 12)」帶進網頁世界。
換句話說,WebGPU 給你更接近原生的效能、更清楚的資源/流程控制,還多了通用運算(Compute),能做的事不只畫三角形,還能跑機器學習、粒子模擬、影像處理等。
WebGPU 是瀏覽器內建的 GPU API,由 W3C 團隊制定,背後對應平台原生 API:Windows 對應 D3D12、Linux/Android 對應 Vulkan、macOS/iOS 對應 Metal。
它提供兩大能力:
為什麼重要:以前用 WebGL,做很多進階效果必須「鑽漏洞」;WebGPU 把這些能力正規化,而且與現代顯卡設計一一對齊,效能與可預測性更好。
WebGL 1/2 分別對應 OpenGL ES 2.0/3.0,屬於「狀態機」的古早風格:你不停 glBind...
、glEnable...
改全域狀態,再 draw
。
這種方式好上手,但也有幾個痛點:
結論:WebGL 非常適合入門與廣泛兼容;但當你想做更大規模、更寫實、更大量運算的內容時,就會碰到天花板。
glBind*
。這幾個詞對應原生 API(Vulkan/D3D12/Metal)的設計,所以學會 WebGPU,也就學會了現代 GPU 的思考方式。
主題 | WebGL(OpenGL ES風格) | WebGPU(現代顯式API) | 對你的意義 |
---|---|---|---|
API 風格 | 全域狀態機、即時改狀態再 draw | 先錄好指令再一次提交 | CPU 開銷更低、可多執行緒準備工作 |
資源綁定 | glBind* 分散又頻繁 |
Bind Group 成套綁定 | 更少樣板、更快切換 |
管線狀態 | 零碎開關 | Pipeline 物件一次打包 | 效能更穩、難犯錯 |
Shader 語言 | GLSL | WGSL(更安全、為 Web 設計) | 編譯訊息清楚、避免未定義行為 |
Compute | 幾乎沒有(要繞路) | 一等公民(Compute Pass) | ML/影像處理/模擬更容易 |
記憶體/同步 | 驅動多幫你猜 | 你明確宣告用途/用法 | 可預測、可最佳化 |
安全模型 | 舊 API 補救 | 以 Web 安全為前提(沙箱) | 不易崩潰/越界,錯誤早揭示 |
若你只是快速畫圖、想兼容最舊的裝置,WebGL 仍是穩妥選擇;但新專案預設就用 WebGPU,會省很多「把舊 API 推到極限」的力氣。
拿到 GPU:navigator.gpu.requestAdapter()
→ adapter.requestDevice()
。
設定畫布:canvas.getContext('webgpu')
並 configure
(指定格式、尺寸)。
準備資源:建立 GPUBuffer
(頂點)、寫一小段 WGSL(VS/FS)。
建立 Pipeline:把著色器 + 固定狀態打包成 GPURenderPipeline
。
每幀渲染:
context.getCurrentTexture()
拿可寫入的畫面。device.createCommandEncoder()
→ beginRenderPass()
→ setPipeline
/setVertexBuffer
/draw
→ end
→ queue.submit()
。WGSL(shader.wgsl)
struct VSOut {
@builtin(position) pos : vec4<f32>,
@location(0) color : vec3<f32>,
};
@vertex
fn vs_main(@builtin(vertex_index) vid : u32) -> VSOut {
var p = array<vec2<f32>, 3>(
vec2<f32>( 0.0, 0.6),
vec2<f32>(-0.6, -0.6),
vec2<f32>( 0.6, -0.6));
var c = array<vec3<f32>, 3>(
vec3<f32>(1.0, 0.2, 0.2),
vec3<f32>(0.2, 1.0, 0.2),
vec3<f32>(0.2, 0.4, 1.0));
var o : VSOut;
o.pos = vec4<f32>(p[vid], 0.0, 1.0);
o.color = c[vid];
return o;
}
@fragment
fn fs_main(@location(0) color : vec3<f32>) -> @location(0) vec4<f32> {
return vec4<f32>(color, 1.0);
}
JavaScript(main.js)
const canvas = document.querySelector('canvas');
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const ctx = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
ctx.configure({ device, format, alphaMode: 'opaque' });
const module = device.createShaderModule({
code: await (await fetch('shader.wgsl')).text()
});
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module, entryPoint: 'vs_main' },
fragment: { module, entryPoint: 'fs_main',
targets: [{ format }] },
primitive: { topology: 'triangle-list', cullMode: 'none' }
});
function frame(){
const encoder = device.createCommandEncoder();
const view = ctx.getCurrentTexture().createView();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view,
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()]);
requestAnimationFrame(frame);
}
frame();
(index.html)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebGPU Life</title>
</head>
<body>
<script src="main.js" type="module"></script>
<canvas width="512" height="512"></canvas>
</body>
</html>
你可以直接放到一個簡單的靜態網站(或本地端伺服器)跑起來,看見彩色三角形。
dispatchWorkgroups
)→ 再把結果拿去畫或讀回 CPU。glBind
」→ 換成「預先建立 Pipeline/BindGroup,每幀只做最少切換」。context.configure({ device, format })
。BindGroupLayout
與 WGSL 的 @group/@binding
必須一一對應。struct
(vec4/mat4)避免踩洞。storeOp
→ 不設定或設錯,畫完可能不保留內容。GPUTexture
+ Sampler
,在 WGSL 取樣。WebGL 讓網頁能「畫 3D」,WebGPU 讓網頁能「像原生程式一樣運用 GPU」。
它提供明確的指令錄製、現代化的資源綁定、與一等的 Compute 支援,既能提升效能,也讓大型專案更好維護。
如果你正準備新專案、或想把 Web 上的即時圖形/運算做得更穩更快,WebGPU 是更好的起點。