WebGPU Example Simple uncluttered example no libraries just raw WebGPU Obj 3d model loader viewer use a custom loader single file function as an obj file can have multiple meshes Select obj file local computer loads the obj parses the data and re initializes the buffers Cut down test version just basics but fully functional use strict document body style height 600px let p document createElement p p innerHTML select obj file visualized drawn using webgpu document body appendChild p let input document createElement input document body appendChild input input type file input onchange onFileSelected function onFileSelected event let selectedFile event target files 0 console log file selectedFile name somefile obj let reader new FileReader reader onload function event let objtxt event target result objects readObj objtxt processObjFile createBuffers updateMatrices reader readAsText selectedFile ref https notebook xbdev net index php page obj function readObj txt console log readObj let objects objects push name test v vt vn f usemtl let data v n f txt txt replaceAll let lines txt split n console log num lines lines length for let i 0 i lines length i let line lines i line line trim if line length 2 continue if line 0 continue let parts line split if parts length 1 continue switch parts 0 case v v 0 089624 1 419387 0 052847 objects reverse 0 v push parts 1 objects reverse 0 v push parts 2 objects reverse 0 v push parts 3 break case vt vt 0 818181 0 000000 objects reverse 0 vt push parts 1 objects reverse 0 vt push parts 2 break case vn vn 0 5499 0 7413 0 3847 objects reverse 0 vn push parts 1 objects reverse 0 vn push parts 2 objects reverse 0 vn push parts 3 break case f f 1 1 1 14 2 1 13 3 1 f v1 vt1 vn1 v2 vt2 vn2 v3 vt3 vn3 f v1 vn1 v2 vn2 v3 vn3 double slashes If you have 4 indices e g 0 1 2 3 The division into two triangles would be one with the first 3 indices and one with the first third and fourth In this example 0 1 2 0 2 3 Let s try some ASCII art to illustrate this 3 2 0 1 let i0 parts 1 split 0 1 let i1 parts 2 split 0 1 let i2 parts 3 split 0 1 let i3 parts length 4 undefined parts 4 split 0 1 let n0 parts 1 split 2 1 let n1 parts 2 split 2 1 let n2 parts 3 split 2 1 let n3 parts length 4 undefined parts 4 split 2 1 if parts 1 includes n0 parts 1 split 1 1 n1 parts 2 split 1 1 n2 parts 3 split 1 1 n3 parts length 4 undefined parts 4 split 1 1 if i3 undefined triangles for let g 0 g 3 g let idx i0 i1 i2 g let x0 objects reverse 0 v 3 idx 0 let y0 objects reverse 0 v 3 idx 1 let z0 objects reverse 0 v 3 idx 2 data v push x0 data v push y0 data v push z0 data f push data f length for let g 0 g n0 n1 n2 length g let nx0 objects reverse 0 vn 3 n0 n1 n2 g 0 let ny0 objects reverse 0 vn 3 n0 n1 n2 g 1 let nz0 objects reverse 0 vn 3 n0 n1 n2 g 2 data n push nx0 data n push ny0 data n push nz0 else quads let v for let g 0 g 4 g let idx i0 i1 i2 i3 g let x0 objects reverse 0 v 3 idx 0 let y0 objects reverse 0 v 3 idx 1 let z0 objects reverse 0 v 3 idx 2 v push x x0 y y0 z z0 data v push v 0 x data v push v 0 y data v push v 0 z data v push v 1 x data v push v 1 y data v push v 1 z data v push v 2 x data v push v 2 y data v push v 2 z data f push data f length data f push data f length data f push data f length data v push v 0 x data v push v 0 y data v push v 0 z data v push v 2 x data v push v 2 y data v push v 2 z data v push v 3 x data v push v 3 y data v push v 3 z data f push data f length data f push data f length data f push data f length let n for let g 0 g 4 g let idx n0 n1 n2 n3 g let nx0 objects reverse 0 vn 3 idx 0 let ny0 objects reverse 0 vn 3 idx 1 let nz0 objects reverse 0 vn 3 idx 2 n push x nx0 y ny0 z nz0 data n push n 0 x data n push n 0 y data n push n 0 z data n push n 1 x data n push n 1 y data n push n 1 z data n push n 2 x data n push n 2 y data n push n 2 z data n push n 0 x data n push n 0 y data n push n 0 z data n push n 2 x data n push n 2 y data n push n 2 z data n push n 3 x data n push n 3 y data n push n 3 z break end switch for return data readObj get some model data use json as it s easy to load setup let response await fetch var scripts tree obj let objtext await response text let objects readObj objtext let middle null let dist null function processObjFile console log processObjFile console log num meshes objects length console log vertices objects 0 v length console log faces objects 0 f length console log normals objects 0 n length get some bounds for the model doesn t go off screen let min x 10000 y 10000 z 10000 let max x 10000 y 10000 z 10000 for let i 0 i objects 0 v length 3 i min x Math min min x objects 0 v i 3 0 min y Math min min y objects 0 v i 3 1 min z Math min min z objects 0 v i 3 2 if i 10 console log objects 0 v i 3 0 max x Math max max x objects 0 v i 3 0 max y Math max max y objects 0 v i 3 1 max z Math max max z objects 0 v i 3 2 let delta x max x min x y max y min y z max z min z middle x min x delta x 0 5 y min y delta y 0 5 z min z delta z 0 5 dist Math sqrt delta x delta x delta y delta y delta z delta z console log model size dist console log min min x min y min z console log max max x max y max z console log middle middle x middle y middle z processObjFile var script document createElement script script type text javascript script async false script src https cdnjs cloudflare com ajax libs gl matrix 2 6 0 gl matrix min js document head appendChild script let canvas document createElement canvas document body appendChild canvas canvas width 600 canvas height 600 const adapter await navigator gpu requestAdapter const device await adapter requestDevice const context canvas getContext webgpu const presentationSize canvas width window devicePixelRatio canvas height window devicePixelRatio const presentationFormat context getPreferredFormat adapter let translateMat mat4 create let rotateXMat mat4 create let rotateYMat mat4 create let rotateZMat mat4 create let scaleMat mat4 create const projectionMatrix mat4 create const viewMatrix mat4 create const modelMatrix mat4 create const viewProjectionMatrix mat4 create const modelRotation mat4 create const rotation 0 0 0 const uniformBuffer device createBuffer size 192 3 x mat4x4 3x64 192 usage GPUBufferUsage UNIFORM GPUBufferUsage COPY_DST function updateMatrices mat4 perspective projectionMatrix Math PI 2 canvas width canvas height 0 001 1500 0 mat4 lookAt viewMatrix 0 0 dist 0 5 0 0 0 0 1 0 mat4 multiply viewProjectionMatrix projectionMatrix viewMatrix device queue writeBuffer uniformBuffer 64 viewProjectionMatrix updateMatrices const sceneUniformBindGroupLayout device createBindGroupLayout entries binding 0 visibility GPUShaderStage VERTEX buffer type uniform const sceneUniformBindGroup device createBindGroup layout sceneUniformBindGroupLayout entries binding 0 resource buffer uniformBuffer context configure device device format presentationFormat size presentationSize const vertWGSL block struct Uniforms modelMatrix mat4x4 f32 modelViewProjectionMatrix mat4x4 f32 modelRotation mat4x4 f32 binding 0 group 0 var uniform uniforms Uniforms struct VSOut builtin position Position vec4 f32 location 0 position vec3 f32 location 1 normal vec3 f32 stage vertex fn main location 0 inPos vec3 f32 location 1 normal vec3 f32 VSOut var vsOut VSOut vsOut Position uniforms modelViewProjectionMatrix uniforms modelMatrix vec4 f32 inPos 1 0 vsOut position uniforms modelMatrix vec4 f32 inPos 1 0 xyz let n normalize normal let tiM uniforms modelRotation transpose uniforms modelRotation let fN tiM vec4 f32 n 0 0 xyz vsOut normal fN uniforms modelMatrix vec4 f32 n 0 0 xyz return vsOut const fragWGSL stage fragment fn main location 0 position vec3 f32 location 1 normal vec3 f32 location 0 vec4 f32 color channels are clamped 0 1 0 0 0 is black and 1 1 1 is completely white normalized vector components are in the range 1 1 normal facing the camera 0 0 1 should be rgb values 0 5 0 5 1 0 let normalCol normalize normal 0 5 0 5 return vec4 f32 normalCol 1 0 1 0 let positionCol abs normalize position return vec4 f32 positionCol 1 0 1 0 let diffuse max 0 0 dot normal vec3 f32 0 0 0 2 1 0 return vec4 f32 diffuse diffuse diffuse 1 0 return vec4 f32 1 0 0 0 0 0 1 0 let positions null let normals null let indices null var positionBuffer null var normalBuffer null var indexBuffer null put the buffer creation update inside a function so it can be changed dynamically after loaded running function createBuffers console log creating buffers positions new Float32Array objects 0 v normals new Float32Array objects 0 n indices new Uint32Array objects 0 f if we don t have normals let s use the position data if objects 0 n length 0 normals new Float32Array objects 0 v positionBuffer device createBuffer size positions byteLength 3 3 usage GPUBufferUsage VERTEX GPUBufferUsage COPY_DST normalBuffer device createBuffer size normals byteLength 3 3 usage GPUBufferUsage VERTEX GPUBufferUsage COPY_DST indexBuffer device createBuffer size indices byteLength 3 3 usage GPUBufferUsage INDEX GPUBufferUsage COPY_DST device queue writeBuffer positionBuffer 0 positions device queue writeBuffer normalBuffer 0 normals device queue writeBuffer indexBuffer 0 indices createBuffers const pipeline device createRenderPipeline layout device createPipelineLayout bindGroupLayouts sceneUniformBindGroupLayout vertex module device createShaderModule code vertWGSL entryPoint main buffers arrayStride 12 attributes shaderLocation 0 format float32x3 offset 0 arrayStride 12 attributes shaderLocation 1 format float32x3 offset 0 fragment module device createShaderModule code fragWGSL entryPoint main targets format presentationFormat primitive topology triangle list frontFace ccw cullMode back depthStencil format depth24plus depthWriteEnabled true depthCompare less const texture device createTexture size presentationSize sampleCount 4 format presentationFormat usage GPUTextureUsage RENDER_ATTACHMENT const view texture createView const depthTexture device createTexture size canvas width canvas height 1 format depth24plus usage GPUTextureUsage RENDER_ATTACHMENT const renderPassDescription colorAttachments view context getCurrentTexture createView loadValue 0 0 0 8 0 8 1 clear screen storeOp store depthStencilAttachment view depthTexture createView depthLoadValue 1 depthStoreOp store stencilLoadValue 0 stencilStoreOp store function frame function xformMatrix xform translate rotate scale xrot translate translate 0 0 0 rotate rotate 0 0 0 scale scale 1 1 1 mat4 fromTranslation translateMat translate mat4 fromXRotation rotateXMat rotate 0 mat4 fromYRotation rotateYMat rotate 1 mat4 fromZRotation rotateZMat rotate 2 mat4 fromScaling scaleMat scale mat4 multiply xform translateMat scaleMat mat4 multiply xform rotateXMat xform mat4 multiply xform rotateYMat xform mat4 multiply xform rotateZMat xform mat4 multiply xrot rotateXMat scaleMat mat4 multiply xrot rotateYMat xrot mat4 multiply xrot rotateZMat xrot rotation 1 0 005 rotation 0 0 002 let translate middle x middle y middle z xformMatrix modelMatrix translate rotation null modelRotation device queue writeBuffer uniformBuffer 0 modelMatrix device queue writeBuffer uniformBuffer 128 modelRotation renderPassDescription colorAttachments 0 view context getCurrentTexture createView const commandEncoder device createCommandEncoder const renderPass commandEncoder beginRenderPass renderPassDescription renderPass setPipeline pipeline renderPass setVertexBuffer 0 positionBuffer renderPass setVertexBuffer 1 normalBuffer renderPass setIndexBuffer indexBuffer uint32 renderPass setBindGroup 0 sceneUniformBindGroup renderPass drawIndexed objects 0 f length 1 renderPass endPass device queue submit commandEncoder finish requestAnimationFrame frame frame more controlled updates onmousemove function frame console log ready
ps cdnjs cloudflare com ajax libs gl matrix 2 6 0 gl matrix min js document head appendChild script let canvas document createElement canvas document body appendChild canvas canvas width 600 canvas height 600 const adapter await navigator gpu requestAdapter const device await adapter requestDevice const context canvas getContext webgpu const presentationSize canvas width window devicePixelRatio canvas height window devicePixelRatio const presentationFormat context getPreferredFormat adapter let translateMat mat4 create let rotateXMat mat4 create let rotateYMat mat4 create let rotateZMat mat4 create let scaleMat mat4 create const projectionMatrix mat4 create const viewMatrix mat4 create const modelMatrix mat4 create const viewProjectionMatrix mat4 create const modelRotation mat4 create const rotation 0 0 0 const uniformBuffer device createBuffer size 192 3 x mat4x4 3x64 192 usage GPUBufferUsage UNIFORM GPUBufferUsage COPY_DST function updateMatrices mat4 perspective projectionMatrix Math PI 2 canvas width canvas height 0 001 1500 0 mat4 lookAt viewMatrix 0 0 dist 0 5 0 0 0 0 1 0 mat4 multiply viewProjectionMatrix projectionMatrix viewMatrix device queue writeBuffer uniformBuffer 64 viewProjectionMatrix updateMatrices const sceneUniformBindGroupLayout device createBindGroupLayout entries binding 0 visibility GPUShaderStage VERTEX buffer type uniform const sceneUniformBindGroup device createBindGroup layout sceneUniformBindGroupLayout entries binding 0 resource buffer uniformBuffer context configure device device format presentationFormat size presentationSize const vertWGSL block struct Uniforms modelMatrix mat4x4 f32 modelViewProjectionMatrix mat4x4 f32 modelRotation mat4x4 f32 binding 0 group 0 var uniform uniforms Uniforms struct VSOut builtin position Position vec4 f32 location 0 position vec3 f32 location 1 normal vec3 f32 stage vertex fn main location 0 inPos vec3 f32 location 1 normal vec3 f32 VSOut var vsOut VSOut vsOut Position uniforms modelViewProjectionMatrix uniforms modelMatrix vec4 f32 inPos 1 0 vsOut position uniforms modelMatrix vec4 f32 inPos 1 0 xyz let n normalize normal let tiM uniforms modelRotation transpose uniforms modelRotation let fN tiM vec4 f32 n 0 0 xyz vsOut normal fN uniforms modelMatrix vec4 f32 n 0 0 xyz return vsOut const fragWGSL stage fragment fn main location 0 position vec3 f32 location 1 normal vec3 f32 location 0 vec4 f32 color channels are clamped 0 1 0 0 0 is black and 1 1 1 is completely white normalized vector components are in the range 1 1 normal facing the camera 0 0 1 should be rgb values 0 5 0 5 1 0 let normalCol normalize normal 0 5 0 5 return vec4 f32 normalCol 1 0 1 0 let positionCol abs normalize position return vec4 f32 positionCol 1 0 1 0 let diffuse max 0 0 dot normal vec3 f32 0 0 0 2 1 0 return vec4 f32 diffuse diffuse diffuse 1 0 return vec4 f32 1 0 0 0 0 0 1 0 let positions null let normals null let indices null var positionBuffer null var normalBuffer null var indexBuffer null put the buffer creation update inside a function so it can be changed dynamically after loaded running function createBuffers console log creating buffers positions new Float32Array objects 0 v normals new Float32Array objects 0 n indices new Uint32Array objects 0 f if we don t have normals let s use the position data if objects 0 n length 0 normals new Float32Array objects 0 v positionBuffer device createBuffer size positions byteLength 3 3 usage GPUBufferUsage VERTEX GPUBufferUsage COPY_DST normalBuffer device createBuffer size normals byteLength 3 3 usage GPUBufferUsage VERTEX GPUBufferUsage COPY_DST indexBuffer device createBuffer size indices byteLength 3 3 usage GPUBufferUsage INDEX GPUBufferUsage COPY_DST device queue writeBuffer positionBuffer 0 positions device queue writeBuffer normalBuffer 0 normals device queue writeBuffer indexBuffer 0 indices createBuffers const pipeline device createRenderPipeline layout device createPipelineLayout bindGroupLayouts sceneUniformBindGroupLayout vertex module device createShaderModule code vertWGSL entryPoint main buffers arrayStride 12 attributes shaderLocation 0 format float32x3 offset 0 arrayStride 12 attributes shaderLocation 1 format float32x3 offset 0 fragment module device createShaderModule code fragWGSL entryPoint main targets format presentationFormat primitive topology triangle list frontFace ccw cullMode back depthStencil format depth24plus depthWriteEnabled true depthCompare less const texture device createTexture size presentationSize sampleCount 4 format presentationFormat usage GPUTextureUsage RENDER_ATTACHMENT const view texture createView const depthTexture device createTexture size canvas width canvas height 1 format depth24plus usage GPUTextureUsage RENDER_ATTACHMENT const renderPassDescription colorAttachments view context getCurrentTexture createView loadValue 0 0 0 8 0 8 1 clear screen storeOp store depthStencilAttachment view depthTexture createView depthLoadValue 1 depthStoreOp store stencilLoadValue 0 stencilStoreOp store function frame function xformMatrix xform translate rotate scale xrot translate translate 0 0 0 rotate rotate 0 0 0 scale scale 1 1 1 mat4 fromTranslation translateMat translate mat4 fromXRotation rotateXMat rotate 0 mat4 fromYRotation rotateYMat rotate 1 mat4 fromZRotation rotateZMat rotate 2 mat4 fromScaling scaleMat scale mat4 multiply xform translateMat scaleMat mat4 multiply xform rotateXMat xform mat4 multiply xform rotateYMat xform mat4 multiply xform rotateZMat xform mat4 multiply xrot rotateXMat scaleMat mat4 multiply xrot rotateYMat xrot mat4 multiply xrot rotateZMat xrot rotation 1 0 005 rotation 0 0 002 let translate middle x middle y middle z xformMatrix modelMatrix translate rotation null modelRotation device queue writeBuffer uniformBuffer 0 modelMatrix device queue writeBuffer uniformBuffer 128 modelRotation renderPassDescription colorAttachments 0 view context getCurrentTexture createView const commandEncoder device createCommandEncoder const renderPass commandEncoder beginRenderPass renderPassDescription renderPass setPipeline pipeline renderPass setVertexBuffer 0 positionBuffer renderPass setVertexBuffer 1 normalBuffer renderPass setIndexBuffer indexBuffer uint32 renderPass setBindGroup 0 sceneUniformBindGroup renderPass drawIndexed objects 0 f length 1 renderPass endPass device queue submit commandEncoder finish requestAnimationFrame frame frame more controlled updates onmousemove function frame console log ready