WebGPU Example Chaining multiple pipelines together Pipeline 1 and Pipeline 2 Pass along effects rain water rolling down window glass let canvas document createElement canvas document body appendChild canvas canvas width canvas height 512 const adapter await navigator gpu requestAdapter const device await adapter requestDevice const context canvas getContext webgpu 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 Note the extra usage as you ll be accessing copying context configure device device format presentationFormat size presentationSize usage GPUTextureUsage RENDER_ATTACHMENT GPUTextureUsage COPY_SRC const timerUniformBuffer device createBuffer size 4 usage GPUBufferUsage UNIFORM GPUBufferUsage COPY_DST const timestep new Float32Array 0 0 device queue writeBuffer timerUniformBuffer 0 timestep Create a sampler with linear filtering for smooth interpolation const textureSampler device createSampler magFilter linear minFilter linear const texture0 device createTexture size presentationSize format presentationFormat usage 0x2 0x4 0x10 GPUTextureUsage TEXTURE_BINDING GPUTextureUsage COPY_DST const texture1 device createTexture size presentationSize format presentationFormat usage 0x2 0x4 0x10 GPUTextureUsage TEXTURE_BINDING GPUTextureUsage COPY_DST const img document createElement img img src https notebook xbdev net var images test512 png await img decode const texture2 device createTexture size img width img height 1 format presentationFormat bgra8unorm rgba8unorm usage 0x2 0x4 GPUTextureUsage COPY_DST GPUTextureUsage TEXTURE_BINDING const imageCanvas document createElement canvas imageCanvas width img width imageCanvas height img height const imageCanvasContext imageCanvas getContext 2d imageCanvasContext drawImage img 0 0 imageCanvas width imageCanvas height const imageData imageCanvasContext getImageData 0 0 imageCanvas width imageCanvas height let textureData new Uint8Array img width img height 4 for let x 0 x img width img height 4 x textureData x imageData data x device queue writeTexture texture texture2 textureData offset 0 bytesPerRow img width 4 rowsPerImage img height img width img height 1 pipeline 1 var triangleVertWGSL struct vout builtin position pos vec4 f32 location 0 uvs vec2 f32 vertex fn main builtin vertex_index VertexIndex u32 builtin instance_index instanceIdx u32 vout let s 1 0 var uvs array vec2 f32 4 vec2 f32 s s vec2 f32 s s vec2 f32 s s vec2 f32 s s var pos array vec2 f32 4 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 var vo vout vo pos vec4 f32 pos VertexIndex 0 0 1 0 vo uvs uvs VertexIndex 0 5 0 5 0 1 return vo var redFragWGSL struct Uniforms mytimer f32 group 0 binding 0 var mySampler sampler group 0 binding 1 var myTexture0 texture_2d f32 group 0 binding 2 var myTexture1 texture_2d f32 group 0 binding 3 var uniform uniforms Uniforms fn getv p vec2 f32 vec4 f32 return textureSample myTexture0 mySampler p 2 0 1 0 fn maxv4 v vec4 f32 s f32 vec4 f32 return vec4 f32 max v x s max v y s max v z s max v w s fn minv4 v vec4 f32 s f32 vec4 f32 return vec4 f32 min v x s min v y s min v z s min v w s fn maxv2 v vec2 f32 s f32 vec2 f32 return vec2 f32 max v x s max v y s fn minv2 v vec2 f32 s f32 vec2 f32 return vec2 f32 min v x s min v y s fragment fn main location 0 uvs vec2 f32 location 0 vec4 f32 let R 4 0 watter attraction radius var fragColor vec4 f32 0 0 if uniforms mytimer 0 01 fragColor vec4 f32 0 0 0 0 0 0 0 0 else var vp getv uvs x let s 0 05 var dv vec4 f32 getv uvs vec2 f32 s 0 x getv uvs vec2 f32 0 s x getv uvs vec2 f32 s 0 x getv uvs vec2 f32 0 s x atract to water in close area var fd vec2 f32 0 var size vp for var dy R dy R dy dy 1 0 for var dx R dx R dx dx 1 0 if dx 0 0 dy 0 0 dx dx dy dy R R continue var a getv s uvs vec2 f32 dx dy x size size a var dir vec2 f32 dx dy var ndir normalize dir var c pow a 0 4 0 25 ndir pow length dir 0 9 if a 0 06 c c 2 a 1 0 fd fd c add gravity with tweaks to make smaller droplets stick var down vec2 f32 0 0 1 0 50 81 vp if vp 0 06 down down 1 1 pow vp 1 0 01 size else down down 0 05 fd fd down var dif maxv4 vec4 f32 vp dv 0 0 if uvs x 1 dv x 0 0 if uvs y 1 0 dv y 0 0 dif dif 0 9996 if vp 0 02 dif dif 0 5 var fa vec4 f32 abs minv2 fd xy 0 maxv2 fd xy 0 add force from attraction and gravity dif dif fa 0 008 try to avoid going in to negative values or exceeding maximum var sm dot dif vec4 f32 1 var red 1 0 if sm 0 0 red min vp sm sm dif dif red dif min dif vec4 f32 1 dv fragColor dif fragColor getv uvs fragColor w 1 0 return fragColor const sceneUniformBindGroupLayout1 device createBindGroupLayout entries binding 0 visibility GPUShaderStage FRAGMENT sampler type filtering binding 1 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 2 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 3 visibility GPUShaderStage FRAGMENT buffer type uniform const uniformBindGroup1 device createBindGroup layout sceneUniformBindGroupLayout1 entries binding 0 resource textureSampler binding 1 resource texture0 createView binding 2 resource texture1 createView binding 3 resource buffer timerUniformBuffer triangleVertWGSL triangleVertWGSL replace n r g redFragWGSL redFragWGSL replace n r g const pipeline1 device createRenderPipeline layout device createPipelineLayout bindGroupLayouts sceneUniformBindGroupLayout1 vertex module device createShaderModule code triangleVertWGSL entryPoint main fragment module device createShaderModule code redFragWGSL entryPoint main targets format presentationFormat primitive topology triangle strip stripIndexFormat uint32 pipeline 2 var triangleVertWGSL2 struct vout builtin position pos vec4 f32 location 0 uvs vec2 f32 vertex fn main builtin vertex_index VertexIndex u32 builtin instance_index instanceIdx u32 vout let s 1 0 var uvs array vec2 f32 4 vec2 f32 s s vec2 f32 s s vec2 f32 s s vec2 f32 s s var pos array vec2 f32 4 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 var vo vout vo pos vec4 f32 pos VertexIndex 0 0 1 0 vo uvs uvs VertexIndex 0 5 0 5 0 1 return vo var redFragWGSL2 struct Uniforms mytimer f32 group 0 binding 0 var mySampler sampler group 0 binding 1 var myTexture0 texture_2d f32 group 0 binding 2 var myTexture1 texture_2d f32 group 0 binding 3 var uniform uniforms Uniforms fn getv p vec2 f32 vec4 f32 return textureSample myTexture0 mySampler p 2 0 1 0 fn getm p vec2 f32 vec4 f32 return textureSample myTexture1 mySampler p 2 0 1 0 fn hash12 p vec2 f32 f32 var p3 fract vec3 f32 p xyx 1031 p3 p3 dot p3 p3 yzx 33 33 return fract p3 x p3 y p3 z fn hv p vec2 f32 f32 var iTime uniforms mytimer return hash12 p 152 iTime 1500 50 0 fragment fn main location 0 uvs vec2 f32 location 0 vec4 f32 let BIG_DROP_RATE 0 55 let BIG_DROP_SIZE 0 03 let BIG_DROP_DEPTH 0 4 let SMALL_DROP_RATE 0 001 let SMALL_DROP_SIZE 0 000003 var iTime uniforms mytimer var iResolution vec2 f32 1 0 1 0 var fragColor vec4 f32 0 0 0 0 0 0 0 0 if uniforms mytimer 0 001 fragColor vec4 f32 0 0 0 0 0 0 0 0 else var s 0 01 var uv uvs uv y uv y 0 001 var v getv uv if length p iMouse xy 10 iMouse z 0 v x 0 008 add little bit of water everywhere all the time var sh hv uv v x v x SMALL_DROP_SIZE step SMALL_DROP_RATE sh sh once in a while add big drop somewhere in the picture if hv vec2 f32 1 0 0 0 fract iTime BIG_DROP_RATE var dp vec2 f32 hv vec2 f32 iTime 0 0 hv vec2 f32 0 0 1 0 dp dp iResolution xy var size hv vec2 f32 2 0 0 0 if distance dp uv BIG_DROP_SIZE mix 0 5 1 size v x v x BIG_DROP_DEPTH var moveOut getm uvs var moveIn vec4 f32 getm uvs vec2 f32 s 0 z getm uvs vec2 f32 0 s w getm uvs vec2 f32 s 0 x getm uvs vec2 f32 0 s y v x v x 1 0 dot vec4 f32 1 moveIn moveOut v x clamp v x 0 0 1 0 v y clamp v y 0 0 1 0 v z clamp v z 0 0 1 0 v w clamp v w 0 0 1 0 if uvs y 1 uvs x 1 uvs x iResolution x 2 uvs y iResolution y 2 v y 0 fragColor v if uvs y 0 01 uvs y 0 99 uvs x 0 01 uvs x 0 99 fragColor vec4 f32 0 0 0 0 0 0 0 0 fragColor w 1 0 return fragColor const sceneUniformBindGroupLayout2 device createBindGroupLayout entries binding 0 visibility GPUShaderStage FRAGMENT sampler type filtering binding 1 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 2 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 3 visibility GPUShaderStage FRAGMENT buffer type uniform const uniformBindGroup2 device createBindGroup layout sceneUniformBindGroupLayout2 entries binding 0 resource textureSampler binding 1 resource texture0 createView binding 2 resource texture1 createView binding 3 resource buffer timerUniformBuffer const pipeline2 device createRenderPipeline layout device createPipelineLayout bindGroupLayouts sceneUniformBindGroupLayout2 vertex module device createShaderModule code triangleVertWGSL2 entryPoint main fragment module device createShaderModule code redFragWGSL2 entryPoint main targets format presentationFormat primitive topology triangle strip stripIndexFormat uint32 pipeline 3 var triangleVertWGSL3 struct vout builtin position pos vec4 f32 location 0 uvs vec2 f32 vertex fn main builtin vertex_index VertexIndex u32 builtin instance_index instanceIdx u32 vout let s 1 0 var uvs array vec2 f32 4 vec2 f32 s s vec2 f32 s s vec2 f32 s s vec2 f32 s s var pos array vec2 f32 4 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 var vo vout vo pos vec4 f32 pos VertexIndex 0 0 1 0 vo uvs uvs VertexIndex 0 5 0 5 0 1 return vo var redFragWGSL3 struct Uniforms mytimer f32 group 0 binding 0 var mySampler sampler group 0 binding 1 var myTexture0 texture_2d f32 group 0 binding 2 var myTexture1 texture_2d f32 group 0 binding 3 var uniform uniforms Uniforms group 0 binding 4 var myTexture2 texture_2d f32 fn getv p vec2 f32 vec4 f32 return textureSample myTexture0 mySampler p 2 0 1 0 fragment fn main location 0 uvs vec2 f32 location 0 vec4 f32 var uv uvs var a textureSample myTexture0 mySampler uv var dp vec3 f32 0 9 0 9 0 0 var b textureSample myTexture0 mySampler uv dp xz var c textureSample myTexture0 mySampler uv dp zy var dx a x b x var dy a x c x var normal normalize vec3 f32 vec2 f32 dx dy 1 0 var iray normalize vec3 f32 uvs xy 0 5 1 2 var d1 refract iray normal 1 3 var ic textureSample myTexture2 mySampler uvs var im vec4 f32 0 7 0 7 0 7 1 0 textureSample myTexture2 mySampler d1 var it im xyz var l length it it it 0 8 im x it x im y it y im z it z return im return textureSample myTexture2 mySampler uvs vec2 f32 normal x normal y let ill clamp dot vec3 f32 1 0 1 0 0 0 normal 0 0 1 0 return ic vec4 f32 0 0 0 0 1 0 1 0 ill return vec4 f32 normal 1 0 const sceneUniformBindGroupLayout3 device createBindGroupLayout entries binding 0 visibility GPUShaderStage FRAGMENT sampler type filtering binding 1 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 2 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 3 visibility GPUShaderStage FRAGMENT buffer type uniform binding 4 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d const uniformBindGroup3 device createBindGroup layout sceneUniformBindGroupLayout3 entries binding 0 resource textureSampler binding 1 resource texture0 createView binding 2 resource texture1 createView binding 3 resource buffer timerUniformBuffer binding 4 resource texture2 createView const pipeline3 device createRenderPipeline layout device createPipelineLayout bindGroupLayouts sceneUniformBindGroupLayout3 vertex module device createShaderModule code triangleVertWGSL3 entryPoint main fragment module device createShaderModule code redFragWGSL3 entryPoint main targets format presentationFormat primitive topology triangle strip stripIndexFormat uint32 const renderPassDescriptor colorAttachments GPURenderPassDescriptor view undefined set later loadOp clear clearValue r 0 0 g 1 0 b 0 0 a 1 0 storeOp store function frame device queue writeBuffer timerUniformBuffer 0 timestep const screenTexture context getCurrentTexture const commandEncoder device createCommandEncoder renderPassDescriptor colorAttachments 0 view screenTexture createView const commandEncoder device createCommandEncoder const passEncoder commandEncoder beginRenderPass renderPassDescriptor passEncoder setPipeline pipeline1 passEncoder setBindGroup 0 uniformBindGroup1 passEncoder draw 4 1 0 0 passEncoder end commandEncoder copyTextureToTexture texture screenTexture texture texture0 width presentationSize 0 height presentationSize 1 depthOrArrayLayers 1 device queue submit commandEncoder finish renderPassDescriptor colorAttachments 0 view screenTexture createView const commandEncoder device createCommandEncoder const passEncoder commandEncoder beginRenderPass renderPassDescriptor passEncoder setPipeline pipeline2 passEncoder setBindGroup 0 uniformBindGroup2 passEncoder draw 4 1 0 0 passEncoder end commandEncoder copyTextureToTexture texture screenTexture texture texture0 width presentationSize 0 height presentationSize 1 depthOrArrayLayers 1 device queue submit commandEncoder finish renderPassDescriptor colorAttachments 0 view screenTexture createView const commandEncoder device createCommandEncoder const passEncoder commandEncoder beginRenderPass renderPassDescriptor passEncoder setPipeline pipeline3 passEncoder setBindGroup 0 uniformBindGroup3 passEncoder draw 4 1 0 0 passEncoder end device queue submit commandEncoder finish device queue submit commandEncoder finish timestep 0 0 1 if you want constant updates animated keep refreshing requestAnimationFrame frame frame console log done
yzx 33 33 return fract p3 x p3 y p3 z fn hv p vec2 f32 f32 var iTime uniforms mytimer return hash12 p 152 iTime 1500 50 0 fragment fn main location 0 uvs vec2 f32 location 0 vec4 f32 let BIG_DROP_RATE 0 55 let BIG_DROP_SIZE 0 03 let BIG_DROP_DEPTH 0 4 let SMALL_DROP_RATE 0 001 let SMALL_DROP_SIZE 0 000003 var iTime uniforms mytimer var iResolution vec2 f32 1 0 1 0 var fragColor vec4 f32 0 0 0 0 0 0 0 0 if uniforms mytimer 0 001 fragColor vec4 f32 0 0 0 0 0 0 0 0 else var s 0 01 var uv uvs uv y uv y 0 001 var v getv uv if length p iMouse xy 10 iMouse z 0 v x 0 008 add little bit of water everywhere all the time var sh hv uv v x v x SMALL_DROP_SIZE step SMALL_DROP_RATE sh sh once in a while add big drop somewhere in the picture if hv vec2 f32 1 0 0 0 fract iTime BIG_DROP_RATE var dp vec2 f32 hv vec2 f32 iTime 0 0 hv vec2 f32 0 0 1 0 dp dp iResolution xy var size hv vec2 f32 2 0 0 0 if distance dp uv BIG_DROP_SIZE mix 0 5 1 size v x v x BIG_DROP_DEPTH var moveOut getm uvs var moveIn vec4 f32 getm uvs vec2 f32 s 0 z getm uvs vec2 f32 0 s w getm uvs vec2 f32 s 0 x getm uvs vec2 f32 0 s y v x v x 1 0 dot vec4 f32 1 moveIn moveOut v x clamp v x 0 0 1 0 v y clamp v y 0 0 1 0 v z clamp v z 0 0 1 0 v w clamp v w 0 0 1 0 if uvs y 1 uvs x 1 uvs x iResolution x 2 uvs y iResolution y 2 v y 0 fragColor v if uvs y 0 01 uvs y 0 99 uvs x 0 01 uvs x 0 99 fragColor vec4 f32 0 0 0 0 0 0 0 0 fragColor w 1 0 return fragColor const sceneUniformBindGroupLayout2 device createBindGroupLayout entries binding 0 visibility GPUShaderStage FRAGMENT sampler type filtering binding 1 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 2 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 3 visibility GPUShaderStage FRAGMENT buffer type uniform const uniformBindGroup2 device createBindGroup layout sceneUniformBindGroupLayout2 entries binding 0 resource textureSampler binding 1 resource texture0 createView binding 2 resource texture1 createView binding 3 resource buffer timerUniformBuffer const pipeline2 device createRenderPipeline layout device createPipelineLayout bindGroupLayouts sceneUniformBindGroupLayout2 vertex module device createShaderModule code triangleVertWGSL2 entryPoint main fragment module device createShaderModule code redFragWGSL2 entryPoint main targets format presentationFormat primitive topology triangle strip stripIndexFormat uint32 pipeline 3 var triangleVertWGSL3 struct vout builtin position pos vec4 f32 location 0 uvs vec2 f32 vertex fn main builtin vertex_index VertexIndex u32 builtin instance_index instanceIdx u32 vout let s 1 0 var uvs array vec2 f32 4 vec2 f32 s s vec2 f32 s s vec2 f32 s s vec2 f32 s s var pos array vec2 f32 4 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 vec2 f32 1 0 1 0 var vo vout vo pos vec4 f32 pos VertexIndex 0 0 1 0 vo uvs uvs VertexIndex 0 5 0 5 0 1 return vo var redFragWGSL3 struct Uniforms mytimer f32 group 0 binding 0 var mySampler sampler group 0 binding 1 var myTexture0 texture_2d f32 group 0 binding 2 var myTexture1 texture_2d f32 group 0 binding 3 var uniform uniforms Uniforms group 0 binding 4 var myTexture2 texture_2d f32 fn getv p vec2 f32 vec4 f32 return textureSample myTexture0 mySampler p 2 0 1 0 fragment fn main location 0 uvs vec2 f32 location 0 vec4 f32 var uv uvs var a textureSample myTexture0 mySampler uv var dp vec3 f32 0 9 0 9 0 0 var b textureSample myTexture0 mySampler uv dp xz var c textureSample myTexture0 mySampler uv dp zy var dx a x b x var dy a x c x var normal normalize vec3 f32 vec2 f32 dx dy 1 0 var iray normalize vec3 f32 uvs xy 0 5 1 2 var d1 refract iray normal 1 3 var ic textureSample myTexture2 mySampler uvs var im vec4 f32 0 7 0 7 0 7 1 0 textureSample myTexture2 mySampler d1 var it im xyz var l length it it it 0 8 im x it x im y it y im z it z return im return textureSample myTexture2 mySampler uvs vec2 f32 normal x normal y let ill clamp dot vec3 f32 1 0 1 0 0 0 normal 0 0 1 0 return ic vec4 f32 0 0 0 0 1 0 1 0 ill return vec4 f32 normal 1 0 const sceneUniformBindGroupLayout3 device createBindGroupLayout entries binding 0 visibility GPUShaderStage FRAGMENT sampler type filtering binding 1 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 2 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d binding 3 visibility GPUShaderStage FRAGMENT buffer type uniform binding 4 visibility GPUShaderStage FRAGMENT texture sampleType float viewDimension 2d const uniformBindGroup3 device createBindGroup layout sceneUniformBindGroupLayout3 entries binding 0 resource textureSampler binding 1 resource texture0 createView binding 2 resource texture1 createView binding 3 resource buffer timerUniformBuffer binding 4 resource texture2 createView const pipeline3 device createRenderPipeline layout device createPipelineLayout bindGroupLayouts sceneUniformBindGroupLayout3 vertex module device createShaderModule code triangleVertWGSL3 entryPoint main fragment module device createShaderModule code redFragWGSL3 entryPoint main targets format presentationFormat primitive topology triangle strip stripIndexFormat uint32 const renderPassDescriptor colorAttachments GPURenderPassDescriptor view undefined set later loadOp clear clearValue r 0 0 g 1 0 b 0 0 a 1 0 storeOp store function frame device queue writeBuffer timerUniformBuffer 0 timestep const screenTexture context getCurrentTexture const commandEncoder device createCommandEncoder renderPassDescriptor colorAttachments 0 view screenTexture createView const commandEncoder device createCommandEncoder const passEncoder commandEncoder beginRenderPass renderPassDescriptor passEncoder setPipeline pipeline1 passEncoder setBindGroup 0 uniformBindGroup1 passEncoder draw 4 1 0 0 passEncoder end commandEncoder copyTextureToTexture texture screenTexture texture texture0 width presentationSize 0 height presentationSize 1 depthOrArrayLayers 1 device queue submit commandEncoder finish renderPassDescriptor colorAttachments 0 view screenTexture createView const commandEncoder device createCommandEncoder const passEncoder commandEncoder beginRenderPass renderPassDescriptor passEncoder setPipeline pipeline2 passEncoder setBindGroup 0 uniformBindGroup2 passEncoder draw 4 1 0 0 passEncoder end commandEncoder copyTextureToTexture texture screenTexture texture texture0 width presentationSize 0 height presentationSize 1 depthOrArrayLayers 1 device queue submit commandEncoder finish renderPassDescriptor colorAttachments 0 view screenTexture createView const commandEncoder device createCommandEncoder const passEncoder commandEncoder beginRenderPass renderPassDescriptor passEncoder setPipeline pipeline3 passEncoder setBindGroup 0 uniformBindGroup3 passEncoder draw 4 1 0 0 passEncoder end device queue submit commandEncoder finish device queue submit commandEncoder finish timestep 0 0 1 if you want constant updates animated keep refreshing requestAnimationFrame frame frame console log done