First WebGPU Program
WebGPU tutorial that shows how to draw a triangle.
On the journey to mastering WebGPU graphics and games - the journey should start with something simple - say hello to your first triangle!
Functions Used: getContext(), requestAdapter(), getPreferredCanvasFormat(), createCommandEncoder(), beginRenderPass(), setPipeline(), draw(), end(), submit(), getCurrentTexture(), createView(), createShaderModule()
WARNING
For those who are fairly inexperienced in programming and think jumping into 3D development is going to be possible, I'd strongly caution you to go back and get a lot of experience building 2D games. 3D development is one of the hardest programming you can do as a developer and you will get frustrated if you don't already have a strong knowledge of programming.
/*
WebGPU Example (Minimal Working Demo - Color Triangle) - 50 lines
*/
let canvas = document . createElement ( 'canvas' );
document . body . appendChild ( canvas ); canvas . height = canvas . width = 512 ;
const context = canvas . getContext ( 'webgpu' );
const adapter = await navigator . gpu . requestAdapter ();
const device = await adapter . requestDevice ();
const presentationFormat = navigator . gpu . getPreferredCanvasFormat (); // context.getPreferredFormat(adapter); - no longer supported - no longer supported
context . configure ({ device : device , format : presentationFormat });
let shaderWGSL = `
@vertex fn vsmain(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32>
{ // build the triangle here (based on the 'index')
var pos = array<vec2<f32>, 3>(vec2<f32>( 0.0, 1.0),
vec2<f32>(-1.0, -1.0),
vec2<f32>( 1.0, -1.0));
return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
}
@fragment fn psmain() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.5, 0.5, 1.0);
} `;
const shaderModule = device . createShaderModule ({ code : shaderWGSL });
const pipeline = device . createRenderPipeline ({
layout : "auto" ,
vertex : { module : shaderModule , entryPoint : 'vsmain' , },
fragment : { module : shaderModule , entryPoint : 'psmain' ,
targets : [ { format : presentationFormat } ]
},
primitive : { topology : 'triangle-list' },
});
function frame ()
{
const commandEncoder = device . createCommandEncoder ();
const renderPassDescriptor = { // GPURenderPassDescriptor
colorAttachments : [ { view : context . getCurrentTexture (). createView (),
loadOp : "clear" ,
loadOp : "clear" , clearValue : [ 0 , 0.5 , 0.5 , 1 ], // clear screen to green
//clearValue : { r: 0.1, g: 1.0, b: 1.0, a: 1.0 },
storeOp : 'store' } ] };
const passEncoder = commandEncoder . beginRenderPass ( renderPassDescriptor );
passEncoder . setPipeline ( pipeline );
passEncoder . draw ( 3 , 1 , 0 , 0 );
passEncoder . end ();
device . queue . submit ([ commandEncoder . finish ()]);
requestAnimationFrame ( frame );
}
frame ();
console . log ( 'done...' );
Resources & Links
• Live WebGPU Lab Version (LINK )