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 )