WebGPU Water Surface Plane Generating a plane triangle strip then mixing sinusoidal methods to oscilate the surface to create a water like motion document body style minHeight 600px var gls await fetch https cdnjs cloudflare com ajax libs gl matrix 2 6 0 gl matrix min js var glc await gls text var script document createElement script script type text javascript script async false script innerHTML glc document head appendChild script const canvas document createElement canvas document body appendChild canvas canvas width canvas height 512 console log canvas width canvas height const context canvas getContext webgpu const gpu navigator gpu console log gpu gpu const adapter await gpu requestAdapter const device await adapter requestDevice const devicePixelRatio 1 1 const presentationSize canvas clientWidth devicePixelRatio canvas clientHeight devicePixelRatio const presentationFormat navigator gpu getPreferredCanvasFormat context getPreferredFormat adapter no longer supported console log presentationFormat context configure device device format presentationFormat size presentationSize Triangle strip plane The first loop sets up the vertex array in a standard rectangular grid There are R C vertices The second loop sets up the indices In general there are two vertices per square in the grid Each vertex will cause a new triangle to be drawn with the previous two vertices so each square is drawn with two triangles The first and last vertex at the start and end of each row is duplicated This means there are two triangles of zero area degenerate triangles between each row This allows us to draw the entire grid in one big triangle strip This technique is called stitching let rows 50 let columns 50 let spacing 0 3 let varray let iarray Set up vertices for let r 0 r rows r for let c 0 c columns c varray push c spacing rows spacing 0 5 varray push 0 varray push r spacing rows spacing 0 5 Set up indices for let r 0 r rows 1 r iarray push r columns for let c 0 c columns c iarray push r columns c iarray push r 1 columns c iarray push r 1 columns columns 1 console log num vertices varray length num indices iarray length var positions new Float32Array varray var indices new Uint32Array iarray console log varray console log iarray const positionBuffer device createBuffer size positions byteLength usage GPUBufferUsage VERTEX GPUBufferUsage COPY_DST const indicesBuffer device createBuffer size indices byteLength usage GPUBufferUsage INDEX GPUBufferUsage COPY_DST device queue writeBuffer positionBuffer 0 positions device queue writeBuffer indicesBuffer 0 indices var vertWGSL struct Uniforms modelViewProjectionMatrix mat4x4 f32 timestep f32 binding 0 group 0 var uniform uniforms Uniforms struct VSOut builtin position Position vec4 f32 location 0 pos vec3 f32 vertex fn main location 0 inPos vec3 f32 VSOut var pos inPos pos y sin inPos x 1 0 uniforms timestep 0 3 cos inPos z 1 5 uniforms timestep 0 3 sin inPos x 6 0 uniforms timestep 3 0 0 05 sin inPos z 5 0 uniforms timestep 3 0 0 05 var vsOut VSOut vsOut Position uniforms modelViewProjectionMatrix vec4 f32 pos 1 0 vsOut pos pos return vsOut var fragWGSL fragment fn main location 0 pos vec3 f32 location 0 vec4 f32 return vec4 f32 1 0 sin pos x 0 5 pos y 1 0 sin pos z 0 5 1 0 const projectionMatrix mat4 create const viewMatrix mat4 create const viewProjectionMatrix mat4 create mat4 perspective projectionMatrix Math PI 2 canvas width canvas height 0 01 1000 0 mat4 lookAt viewMatrix 0 5 5 0 0 0 0 1 0 mat4 multiply viewProjectionMatrix projectionMatrix viewMatrix const vertexUniformBuffer device createBuffer size 80 64 4 usage GPUBufferUsage UNIFORM GPUBufferUsage COPY_DST const timestep new Float32Array 0 0 device queue writeBuffer vertexUniformBuffer 0 viewProjectionMatrix device queue writeBuffer vertexUniformBuffer 64 timestep const sceneUniformBindGroupLayout device createBindGroupLayout entries binding 0 visibility GPUShaderStage VERTEX buffer type uniform const uniformBindGroup device createBindGroup layout sceneUniformBindGroupLayout entries binding 0 resource buffer vertexUniformBuffer 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 fragment module device createShaderModule code fragWGSL entryPoint main targets format presentationFormat primitive topology triangle strip frontFace ccw cullMode back stripIndexFormat uint32 GPURenderPassDescriptor const renderPassDescriptor colorAttachments view undefined asign later in frame loadOp clear clearValue r 0 0 g 0 5 b 0 5 a 1 0 storeOp store function frame timestep 0 0 01 device queue writeBuffer vertexUniformBuffer 64 timestep renderPassDescriptor colorAttachments 0 view context getCurrentTexture createView const commandEncoder device createCommandEncoder const renderPass commandEncoder beginRenderPass renderPassDescriptor renderPass setPipeline pipeline renderPass setBindGroup 0 uniformBindGroup renderPass setVertexBuffer 0 positionBuffer renderPass setIndexBuffer indicesBuffer uint32 renderPass drawIndexed indices length 1 0 0 renderPass end device queue submit commandEncoder finish if you want constant updates animated keep refreshing requestAnimationFrame frame frame WebGPU Water Surface Plane Extended version which works on calculating extra information for the surface normals document body style minHeight 600px var gls await fetch https cdnjs cloudflare com ajax libs gl matrix 2 6 0 gl matrix min js var glc await gls text var script document createElement script script type text javascript script async false script innerHTML glc document head appendChild script const canvas document createElement canvas document body appendChild canvas canvas width canvas height 512 console log canvas width canvas height const context canvas getContext webgpu const gpu navigator gpu console log gpu gpu const adapter await gpu requestAdapter const device await adapter requestDevice const devicePixelRatio 1 1 const presentationSize canvas clientWidth devicePixelRatio canvas clientHeight devicePixelRatio const presentationFormat navigator gpu getPreferredCanvasFormat context getPreferredFormat adapter no longer supported console log presentationFormat context configure device device format presentationFormat size presentationSize Triangle strip plane The first loop sets up the vertex array in a standard rectangular grid There are R C vertices The second loop sets up the indices In general there are two vertices per square in the grid Each vertex will cause a new triangle to be drawn with the previous two vertices so each square is drawn with two triangles The first and last vertex at the start and end of each row is duplicated This means there are two triangles of zero area degenerate triangles between each row This allows us to draw the entire grid in one big triangle strip This technique is called stitching let rows 50 let columns 50 let spacing 0 3 let varray let iarray Set up vertices for let r 0 r rows r for let c 0 c columns c varray push c spacing rows spacing 0 5 varray push 0 varray push r spacing rows spacing 0 5 Set up indices for let r 0 r rows 1 r iarray push r columns for let c 0 c columns c iarray push r columns c iarray push r 1 columns c iarray push r 1 columns columns 1 console log num vertices varray length num indices iarray length var positions new Float32Array varray var indices new Uint32Array iarray console log varray console log iarray const positionBuffer device createBuffer size positions byteLength usage GPUBufferUsage VERTEX GPUBufferUsage COPY_DST const indicesBuffer device createBuffer size indices byteLength usage GPUBufferUsage INDEX GPUBufferUsage COPY_DST device queue writeBuffer positionBuffer 0 positions device queue writeBuffer indicesBuffer 0 indices var vertWGSL struct Uniforms modelViewProjectionMatrix mat4x4 f32 timestep f32 binding 0 group 0 var uniform uniforms Uniforms struct VSOut builtin position Position vec4 f32 location 0 pos vec3 f32 location 1 normal vec3 f32 fn getPos pp vec3 f32 t f32 vec3 f32 var ret vec3 f32 pp x 0 0 pp z ret y sin pp x 3 0 t 2 0 sin pp x 1 0 t 0 3 cos pp z 1 5 t 0 3 sin pp x 6 0 t 3 0 0 05 sin pp z 5 0 t 3 0 0 05 return ret vertex fn main location 0 inPos vec3 f32 VSOut var p0 getPos inPos uniforms timestep var p1 getPos inPos vec3 f32 0 01 0 0 0 0 uniforms timestep var p2 getPos inPos vec3 f32 0 0 0 0 0 01 uniforms timestep var normal cross p1 p0 p2 p0 normal normalize normal var vsOut VSOut vsOut Position uniforms modelViewProjectionMatrix vec4 f32 p0 1 0 vsOut pos p0 vsOut normal normal return vsOut var fragWGSL fragment fn main location 0 pos vec3 f32 location 1 normal vec3 f32 location 0 vec4 f32 return vec4 f32 normal 1 0 let lightdir normalize vec3 f32 0 0 0 5 1 0 let diffuse clamp dot normal lightdir 0 0 1 0 return vec4 f32 0 0 0 0 0 5 diffuse 1 0 const projectionMatrix mat4 create const viewMatrix mat4 create const viewProjectionMatrix mat4 create mat4 perspective projectionMatrix Math PI 2 canvas width canvas height 0 01 1000 0 mat4 lookAt viewMatrix 0 5 5 0 0 0 0 1 0 mat4 multiply viewProjectionMatrix projectionMatrix viewMatrix const vertexUniformBuffer device createBuffer size 80 68 64 4 usage GPUBufferUsage UNIFORM GPUBufferUsage COPY_DST const timestep new Float32Array 0 0 device queue writeBuffer vertexUniformBuffer 0 viewProjectionMatrix device queue writeBuffer vertexUniformBuffer 64 timestep const sceneUniformBindGroupLayout device createBindGroupLayout entries binding 0 visibility GPUShaderStage VERTEX buffer type uniform const uniformBindGroup device createBindGroup layout sceneUniformBindGroupLayout entries binding 0 resource buffer vertexUniformBuffer 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 fragment module device createShaderModule code fragWGSL entryPoint main targets format presentationFormat primitive topology triangle strip frontFace ccw cullMode back stripIndexFormat uint32 GPURenderPassDescriptor const renderPassDescriptor colorAttachments view undefined asign later in frame loadOp clear clearValue r 0 0 g 0 5 b 0 5 a 1 0 storeOp store function frame timestep 0 0 01 device queue writeBuffer vertexUniformBuffer 64 timestep renderPassDescriptor colorAttachments 0 view context getCurrentTexture createView const commandEncoder device createCommandEncoder const renderPass commandEncoder beginRenderPass renderPassDescriptor renderPass setPipeline pipeline renderPass setBindGroup 0 uniformBindGroup renderPass setVertexBuffer 0 positionBuffer renderPass setIndexBuffer indicesBuffer uint32 renderPass drawIndexed indices length 1 0 0 renderPass end device queue submit commandEncoder finish if you want constant updates animated keep refreshing requestAnimationFrame frame frame
t gls text var script document createElement script script type text javascript script async false script innerHTML glc document head appendChild script const canvas document createElement canvas document body appendChild canvas canvas width canvas height 512 console log canvas width canvas height const context canvas getContext webgpu const gpu navigator gpu console log gpu gpu const adapter await gpu requestAdapter const device await adapter requestDevice const devicePixelRatio 1 1 const presentationSize canvas clientWidth devicePixelRatio canvas clientHeight devicePixelRatio const presentationFormat navigator gpu getPreferredCanvasFormat context getPreferredFormat adapter no longer supported console log presentationFormat context configure device device format presentationFormat size presentationSize Triangle strip plane The first loop sets up the vertex array in a standard rectangular grid There are R C vertices The second loop sets up the indices In general there are two vertices per square in the grid Each vertex will cause a new triangle to be drawn with the previous two vertices so each square is drawn with two triangles The first and last vertex at the start and end of each row is duplicated This means there are two triangles of zero area degenerate triangles between each row This allows us to draw the entire grid in one big triangle strip This technique is called stitching let rows 50 let columns 50 let spacing 0 3 let varray let iarray Set up vertices for let r 0 r rows r for let c 0 c columns c varray push c spacing rows spacing 0 5 varray push 0 varray push r spacing rows spacing 0 5 Set up indices for let r 0 r rows 1 r iarray push r columns for let c 0 c columns c iarray push r columns c iarray push r 1 columns c iarray push r 1 columns columns 1 console log num vertices varray length num indices iarray length var positions new Float32Array varray var indices new Uint32Array iarray console log varray console log iarray const positionBuffer device createBuffer size positions byteLength usage GPUBufferUsage VERTEX GPUBufferUsage COPY_DST const indicesBuffer device createBuffer size indices byteLength usage GPUBufferUsage INDEX GPUBufferUsage COPY_DST device queue writeBuffer positionBuffer 0 positions device queue writeBuffer indicesBuffer 0 indices var vertWGSL struct Uniforms modelViewProjectionMatrix mat4x4 f32 timestep f32 binding 0 group 0 var uniform uniforms Uniforms struct VSOut builtin position Position vec4 f32 location 0 pos vec3 f32 location 1 normal vec3 f32 fn getPos pp vec3 f32 t f32 vec3 f32 var ret vec3 f32 pp x 0 0 pp z ret y sin pp x 3 0 t 2 0 sin pp x 1 0 t 0 3 cos pp z 1 5 t 0 3 sin pp x 6 0 t 3 0 0 05 sin pp z 5 0 t 3 0 0 05 return ret vertex fn main location 0 inPos vec3 f32 VSOut var p0 getPos inPos uniforms timestep var p1 getPos inPos vec3 f32 0 01 0 0 0 0 uniforms timestep var p2 getPos inPos vec3 f32 0 0 0 0 0 01 uniforms timestep var normal cross p1 p0 p2 p0 normal normalize normal var vsOut VSOut vsOut Position uniforms modelViewProjectionMatrix vec4 f32 p0 1 0 vsOut pos p0 vsOut normal normal return vsOut var fragWGSL fragment fn main location 0 pos vec3 f32 location 1 normal vec3 f32 location 0 vec4 f32 return vec4 f32 normal 1 0 let lightdir normalize vec3 f32 0 0 0 5 1 0 let diffuse clamp dot normal lightdir 0 0 1 0 return vec4 f32 0 0 0 0 0 5 diffuse 1 0 const projectionMatrix mat4 create const viewMatrix mat4 create const viewProjectionMatrix mat4 create mat4 perspective projectionMatrix Math PI 2 canvas width canvas height 0 01 1000 0 mat4 lookAt viewMatrix 0 5 5 0 0 0 0 1 0 mat4 multiply viewProjectionMatrix projectionMatrix viewMatrix const vertexUniformBuffer device createBuffer size 80 68 64 4 usage GPUBufferUsage UNIFORM GPUBufferUsage COPY_DST const timestep new Float32Array 0 0 device queue writeBuffer vertexUniformBuffer 0 viewProjectionMatrix device queue writeBuffer vertexUniformBuffer 64 timestep const sceneUniformBindGroupLayout device createBindGroupLayout entries binding 0 visibility GPUShaderStage VERTEX buffer type uniform const uniformBindGroup device createBindGroup layout sceneUniformBindGroupLayout entries binding 0 resource buffer vertexUniformBuffer 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 fragment module device createShaderModule code fragWGSL entryPoint main targets format presentationFormat primitive topology triangle strip frontFace ccw cullMode back stripIndexFormat uint32 GPURenderPassDescriptor const renderPassDescriptor colorAttachments view undefined asign later in frame loadOp clear clearValue r 0 0 g 0 5 b 0 5 a 1 0 storeOp store function frame timestep 0 0 01 device queue writeBuffer vertexUniformBuffer 64 timestep renderPassDescriptor colorAttachments 0 view context getCurrentTexture createView const commandEncoder device createCommandEncoder const renderPass commandEncoder beginRenderPass renderPassDescriptor renderPass setPipeline pipeline renderPass setBindGroup 0 uniformBindGroup renderPass setVertexBuffer 0 positionBuffer renderPass setIndexBuffer indicesBuffer uint32 renderPass drawIndexed indices length 1 0 0 renderPass end device queue submit commandEncoder finish if you want constant updates animated keep refreshing requestAnimationFrame frame frame