diff --git a/404.html b/404.html index b7bbf7b3..19ef357b 100644 --- a/404.html +++ b/404.html @@ -1,4 +1,4 @@ -404: This page could not be found

404

This page could not be found.

\ No newline at end of file + }

404

This page could not be found.

\ No newline at end of file diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/A-buffer.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/A-buffer.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/A-buffer.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/A-buffer.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/animometer.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/animometer.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/animometer.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/animometer.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/bitonicSort.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/bitonicSort.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/bitonicSort.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/bitonicSort.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/cameras.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/cameras.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/cameras.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/cameras.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/computeBoids.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/computeBoids.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/computeBoids.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/computeBoids.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/cornell.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/cornell.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/cornell.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/cornell.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/cubemap.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/cubemap.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/cubemap.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/cubemap.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/deferredRendering.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/deferredRendering.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/deferredRendering.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/deferredRendering.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/fractalCube.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/fractalCube.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/fractalCube.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/fractalCube.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/gameOfLife.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/gameOfLife.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/gameOfLife.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/gameOfLife.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/helloTriangle.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/helloTriangle.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/helloTriangle.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/helloTriangle.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/helloTriangleMSAA.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/helloTriangleMSAA.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/helloTriangleMSAA.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/helloTriangleMSAA.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/imageBlur.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/imageBlur.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/imageBlur.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/imageBlur.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/instancedCube.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/instancedCube.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/instancedCube.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/instancedCube.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/normalMap.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/normalMap.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/normalMap.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/normalMap.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/particles.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/particles.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/particles.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/particles.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/renderBundles.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/renderBundles.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/renderBundles.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/renderBundles.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/resizeCanvas.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/resizeCanvas.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/resizeCanvas.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/resizeCanvas.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/reversedZ.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/reversedZ.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/reversedZ.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/reversedZ.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/rotatingCube.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/rotatingCube.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/rotatingCube.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/rotatingCube.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/samplerParameters.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/samplerParameters.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/samplerParameters.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/samplerParameters.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/shadowMapping.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/shadowMapping.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/shadowMapping.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/shadowMapping.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/texturedCube.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/texturedCube.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/texturedCube.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/texturedCube.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/twoCubes.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/twoCubes.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/twoCubes.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/twoCubes.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/videoUploading.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/videoUploading.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/videoUploading.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/videoUploading.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/videoUploadingWebCodecs.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/videoUploadingWebCodecs.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/videoUploadingWebCodecs.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/videoUploadingWebCodecs.json diff --git a/_next/data/B9Dh2tQO3E3w4r6tYigyI/samples/worker.json b/_next/data/vZNCmBfvooZ5MCx816w-j/samples/worker.json similarity index 100% rename from _next/data/B9Dh2tQO3E3w4r6tYigyI/samples/worker.json rename to _next/data/vZNCmBfvooZ5MCx816w-j/samples/worker.json diff --git a/_next/static/chunks/752.d82da5c3f7fbd984.js b/_next/static/chunks/752.d82da5c3f7fbd984.js new file mode 100644 index 00000000..51612907 --- /dev/null +++ b/_next/static/chunks/752.d82da5c3f7fbd984.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[752],{5671:function(e,n,t){"use strict";t.d(n,{Tl:function(){return p},hu:function(){return f}});var a=t(5893),r=t(9008),s=t.n(r),i=t(1163),o=t(7294),l=t(9147),c=t.n(l);t(7319);let u=e=>{let n=(0,o.useRef)(null),r=(0,o.useMemo)(()=>e.sources.map(e=>{let{name:n,contents:r}=e;return{name:n,...function(e){let n;let r=null;{r=document.createElement("div");let s=t(4631);n=s(r,{lineNumbers:!0,lineWrapping:!0,theme:"monokai",readOnly:!0})}return{Container:function(t){return(0,a.jsx)("div",{...t,children:(0,a.jsx)("div",{ref(t){r&&t&&(t.appendChild(r),n.setOption("value",e))}})})}}}(r)}}),e.sources),l=(0,o.useRef)(null),u=(0,o.useMemo)(()=>{if(e.gui){let n=t(4376);return new n.GUI({autoPlace:!1})}},[]),p=(0,o.useRef)(null),f=(0,o.useMemo)(()=>{if(e.stats){let n=t(2792);return new n}},[]),d=(0,i.useRouter)(),m=d.asPath.match(/#([a-zA-Z0-9\.\/]+)/),[g,v]=(0,o.useState)(null),[P,h]=(0,o.useState)(null);return(0,o.useEffect)(()=>{if(m?h(m[1]):h(r[0].name),u&&l.current)for(l.current.appendChild(u.domElement);u.__controllers.length>0;)u.__controllers[0].remove();f&&p.current&&(f.dom.style.position="absolute",f.showPanel(1),p.current.appendChild(f.dom));let t={active:!0},a=()=>{t.active=!1};try{let s=n.current;if(!s)throw Error("The canvas is not available");let i=e.init({canvas:s,pageState:t,gui:u,stats:f});i instanceof Promise&&i.catch(e=>{console.error(e),v(e)})}catch(o){console.error(o),v(o)}return a},[]),(0,a.jsxs)("main",{children:[(0,a.jsxs)(s(),{children:[(0,a.jsx)("style",{dangerouslySetInnerHTML:{__html:"\n .CodeMirror {\n height: auto !important;\n margin: 1em 0;\n }\n\n .CodeMirror-scroll {\n height: auto !important;\n overflow: visible !important;\n }\n "}}),(0,a.jsx)("title",{children:"".concat(e.name," - WebGPU Samples")}),(0,a.jsx)("meta",{name:"description",content:e.description}),(0,a.jsx)("meta",{httpEquiv:"origin-trial",content:e.originTrial})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h1",{children:e.name}),(0,a.jsx)("a",{target:"_blank",rel:"noreferrer",href:"https://github.com/".concat("webgpu/webgpu-samples","/tree/main/").concat(e.filename),children:"See it on Github!"}),(0,a.jsx)("p",{children:e.description}),g?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"Something went wrong. Do your browser and device support WebGPU?"}),(0,a.jsx)("p",{children:"".concat(g)})]}):null]}),(0,a.jsxs)("div",{className:c().canvasContainer,children:[(0,a.jsx)("div",{style:{position:"absolute",left:10},ref:p}),(0,a.jsx)("div",{style:{position:"absolute",right:10},ref:l}),(0,a.jsx)("canvas",{ref:n})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("nav",{className:c().sourceFileNav,children:(0,a.jsx)("ul",{children:r.map((e,n)=>(0,a.jsx)("li",{children:(0,a.jsx)("a",{href:"#".concat(e.name),"data-active":P==e.name,onClick(){h(e.name)},children:e.name})},n))})}),r.map((e,n)=>(0,a.jsx)(e.Container,{className:c().sourceFileContainer,"data-active":P==e.name},n))]})]})},p=e=>(0,a.jsx)(u,{...e});function f(e,n){if(!e)throw Error(n)}},2752:function(e,n,t){"use strict";t.r(n),t.d(n,{default:function(){return c}});var a=t(5671),r="struct VertexOutput {\n @builtin(position) position : vec4,\n @location(4) color : vec4,\n}\n\n@vertex\nfn vert_main(\n @location(0) a_particlePos : vec2,\n @location(1) a_particleVel : vec2,\n @location(2) a_pos : vec2\n) -> VertexOutput {\n let angle = -atan2(a_particleVel.x, a_particleVel.y);\n let pos = vec2(\n (a_pos.x * cos(angle)) - (a_pos.y * sin(angle)),\n (a_pos.x * sin(angle)) + (a_pos.y * cos(angle))\n );\n \n var output : VertexOutput;\n output.position = vec4(pos + a_particlePos, 0.0, 1.0);\n output.color = vec4(\n 1.0 - sin(angle + 1.0) - a_particleVel.y,\n pos.x * 100.0 - a_particleVel.y + 0.1,\n a_particleVel.x + cos(angle + 0.5),\n 1.0);\n return output;\n}\n\n@fragment\nfn frag_main(@location(4) color : vec4) -> @location(0) vec4 {\n return color;\n}",s="struct Particle {\n pos : vec2,\n vel : vec2,\n}\nstruct SimParams {\n deltaT : f32,\n rule1Distance : f32,\n rule2Distance : f32,\n rule3Distance : f32,\n rule1Scale : f32,\n rule2Scale : f32,\n rule3Scale : f32,\n}\nstruct Particles {\n particles : array,\n}\n@binding(0) @group(0) var params : SimParams;\n@binding(1) @group(0) var particlesA : Particles;\n@binding(2) @group(0) var particlesB : Particles;\n\n// https://github.com/austinEng/Project6-Vulkan-Flocking/blob/master/data/shaders/computeparticles/particle.comp\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) GlobalInvocationID : vec3) {\n var index = GlobalInvocationID.x;\n\n var vPos = particlesA.particles[index].pos;\n var vVel = particlesA.particles[index].vel;\n var cMass = vec2(0.0);\n var cVel = vec2(0.0);\n var colVel = vec2(0.0);\n var cMassCount = 0u;\n var cVelCount = 0u;\n var pos : vec2;\n var vel : vec2;\n\n for (var i = 0u; i < arrayLength(&particlesA.particles); i++) {\n if (i == index) {\n continue;\n }\n\n pos = particlesA.particles[i].pos.xy;\n vel = particlesA.particles[i].vel.xy;\n if (distance(pos, vPos) < params.rule1Distance) {\n cMass += pos;\n cMassCount++;\n }\n if (distance(pos, vPos) < params.rule2Distance) {\n colVel -= pos - vPos;\n }\n if (distance(pos, vPos) < params.rule3Distance) {\n cVel += vel;\n cVelCount++;\n }\n }\n if (cMassCount > 0) {\n cMass = (cMass / vec2(f32(cMassCount))) - vPos;\n }\n if (cVelCount > 0) {\n cVel /= f32(cVelCount);\n }\n vVel += (cMass * params.rule1Scale) + (colVel * params.rule2Scale) + (cVel * params.rule3Scale);\n\n // clamp velocity for a more pleasing simulation\n vVel = normalize(vVel) * clamp(length(vVel), 0.0, 0.1);\n // kinematic update\n vPos = vPos + (vVel * params.deltaT);\n // Wrap around boundary\n if (vPos.x < -1.0) {\n vPos.x = 1.0;\n }\n if (vPos.x > 1.0) {\n vPos.x = -1.0;\n }\n if (vPos.y < -1.0) {\n vPos.y = 1.0;\n }\n if (vPos.y > 1.0) {\n vPos.y = -1.0;\n }\n // Write back\n particlesB.particles[index].pos = vPos;\n particlesB.particles[index].vel = vVel;\n}\n",i="src/sample/computeBoids/main.ts";let o=async e=>{let n,t,{canvas:i,pageState:o,gui:l}=e,c=await navigator.gpu.requestAdapter();(0,a.hu)(c,"requestAdapter returned null");let u=c.features.has("timestamp-query"),p=await c.requestDevice({requiredFeatures:u?["timestamp-query"]:[]}),f=document.createElement("div");f.style.color="white",f.style.background="black",f.style.position="absolute",f.style.top="10px",f.style.left="10px",f.style.textAlign="left";let d=document.createElement("pre");if(f.appendChild(d),i.parentNode?i.parentNode.appendChild(f):console.error("canvas.parentNode is null"),!o.active)return;let m=i.getContext("webgpu"),g=window.devicePixelRatio;i.width=i.clientWidth*g,i.height=i.clientHeight*g;let v=navigator.gpu.getPreferredCanvasFormat();m.configure({device:p,format:v,alphaMode:"premultiplied"});let P=p.createShaderModule({code:r}),h=p.createRenderPipeline({layout:"auto",vertex:{module:P,entryPoint:"vert_main",buffers:[{arrayStride:16,stepMode:"instance",attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"}]},{arrayStride:8,stepMode:"vertex",attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]}]},fragment:{module:P,entryPoint:"frag_main",targets:[{format:v}]},primitive:{topology:"triangle-list"}}),y=p.createComputePipeline({layout:"auto",compute:{module:p.createShaderModule({code:s}),entryPoint:"main"}}),b={colorAttachments:[{view:void 0,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]},S={},x=[];u&&(n=p.createQuerySet({type:"timestamp",count:4}),t=p.createBuffer({size:4*BigInt64Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),S.timestampWrites={querySet:n,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1},b.timestampWrites={querySet:n,beginningOfPassWriteIndex:2,endOfPassWriteIndex:3});let B=new Float32Array([-.01,-.02,.01,-.02,0,.02]),E=p.createBuffer({size:B.byteLength,usage:GPUBufferUsage.VERTEX,mappedAtCreation:!0});new Float32Array(E.getMappedRange()).set(B),E.unmap();let D={deltaT:.04,rule1Distance:.1,rule2Distance:.025,rule3Distance:.025,rule1Scale:.02,rule2Scale:.05,rule3Scale:.005},_=7*Float32Array.BYTES_PER_ELEMENT,C=p.createBuffer({size:_,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});function w(){p.queue.writeBuffer(C,0,new Float32Array([D.deltaT,D.rule1Distance,D.rule2Distance,D.rule3Distance,D.rule1Scale,D.rule2Scale,D.rule3Scale]))}w(),Object.keys(D).forEach(e=>{void 0===l?console.error("GUI not initialized"):l.add(D,e).onFinishChange(w)});let M=new Float32Array(6e3);for(let A=0;A<1500;++A)M[4*A+0]=2*(Math.random()-.5),M[4*A+1]=2*(Math.random()-.5),M[4*A+2]=2*(Math.random()-.5)*.1,M[4*A+3]=2*(Math.random()-.5)*.1;let U=[,,],G=[,,];for(let R=0;R<2;++R)U[R]=p.createBuffer({size:M.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.STORAGE,mappedAtCreation:!0}),new Float32Array(U[R].getMappedRange()).set(M),U[R].unmap();for(let T=0;T<2;++T)G[T]=p.createBindGroup({layout:y.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:C}},{binding:1,resource:{buffer:U[T],offset:0,size:M.byteLength}},{binding:2,resource:{buffer:U[(T+1)%2],offset:0,size:M.byteLength}}]});let V=0,k=0,L=0,F=0;requestAnimationFrame(function e(){let a;if(!o.active)return;b.colorAttachments[0].view=m.getCurrentTexture().createView();let r=p.createCommandEncoder();{let s=r.beginComputePass(S);s.setPipeline(y),s.setBindGroup(0,G[V%2]),s.dispatchWorkgroups(Math.ceil(23.4375)),s.end()}{let i=r.beginRenderPass(b);i.setPipeline(h),i.setVertexBuffer(0,U[(V+1)%2]),i.setVertexBuffer(1,E),i.draw(3,1500,0,0),i.end()}u&&(a=x.pop()||p.createBuffer({size:4*BigInt64Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),r.resolveQuerySet(n,0,4,t,0),r.copyBufferToBuffer(t,0,a,0,a.size)),p.queue.submit([r.finish()]),u&&a.mapAsync(GPUMapMode.READ).then(()=>{let e=new BigInt64Array(a.getMappedRange()),n=Number(e[1]-e[0]),t=Number(e[3]-e[2]);if(n>0&&t>0&&(k+=n,L+=t,F++),a.unmap(),F>=100){let r=Math.round(k/F/1e3),s=Math.round(L/F/1e3);d.textContent="avg compute pass duration: ".concat(r,"\xb5s\navg render pass duration: ").concat(s,"\xb5s\nspare readback buffers: ").concat(x.length),k=0,L=0,F=0}x.push(a)}),++V,requestAnimationFrame(e)})},l=()=>(0,a.Tl)({name:"Compute Boids",description:"A GPU compute particle simulation that mimics the flocking behavior of birds. A compute shader updates two ping-pong buffers which store particle data. The data is used to draw instanced particles.",gui:!0,init:o,sources:[{name:i.substring(24),contents:"import { assert, makeSample, SampleInit } from '../../components/SampleLayout';\n\nimport spriteWGSL from './sprite.wgsl';\nimport updateSpritesWGSL from './updateSprites.wgsl';\n\nconst init: SampleInit = async ({ canvas, pageState, gui }) => {\n const adapter = await navigator.gpu.requestAdapter();\n assert(adapter, 'requestAdapter returned null');\n\n const hasTimestampQuery = adapter.features.has('timestamp-query');\n const device = await adapter.requestDevice({\n requiredFeatures: hasTimestampQuery ? ['timestamp-query'] : [],\n });\n\n const perfDisplayContainer = document.createElement('div');\n perfDisplayContainer.style.color = 'white';\n perfDisplayContainer.style.background = 'black';\n perfDisplayContainer.style.position = 'absolute';\n perfDisplayContainer.style.top = '10px';\n perfDisplayContainer.style.left = '10px';\n perfDisplayContainer.style.textAlign = 'left';\n\n const perfDisplay = document.createElement('pre');\n perfDisplayContainer.appendChild(perfDisplay);\n if (canvas.parentNode) {\n canvas.parentNode.appendChild(perfDisplayContainer);\n } else {\n console.error('canvas.parentNode is null');\n }\n\n if (!pageState.active) return;\n const context = canvas.getContext('webgpu') as GPUCanvasContext;\n const devicePixelRatio = window.devicePixelRatio;\n canvas.width = canvas.clientWidth * devicePixelRatio;\n canvas.height = canvas.clientHeight * devicePixelRatio;\n const presentationFormat = navigator.gpu.getPreferredCanvasFormat();\n\n context.configure({\n device,\n format: presentationFormat,\n alphaMode: 'premultiplied',\n });\n\n const spriteShaderModule = device.createShaderModule({ code: spriteWGSL });\n const renderPipeline = device.createRenderPipeline({\n layout: 'auto',\n vertex: {\n module: spriteShaderModule,\n entryPoint: 'vert_main',\n buffers: [\n {\n // instanced particles buffer\n arrayStride: 4 * 4,\n stepMode: 'instance',\n attributes: [\n {\n // instance position\n shaderLocation: 0,\n offset: 0,\n format: 'float32x2',\n },\n {\n // instance velocity\n shaderLocation: 1,\n offset: 2 * 4,\n format: 'float32x2',\n },\n ],\n },\n {\n // vertex buffer\n arrayStride: 2 * 4,\n stepMode: 'vertex',\n attributes: [\n {\n // vertex positions\n shaderLocation: 2,\n offset: 0,\n format: 'float32x2',\n },\n ],\n },\n ],\n },\n fragment: {\n module: spriteShaderModule,\n entryPoint: 'frag_main',\n targets: [\n {\n format: presentationFormat,\n },\n ],\n },\n primitive: {\n topology: 'triangle-list',\n },\n });\n\n const computePipeline = device.createComputePipeline({\n layout: 'auto',\n compute: {\n module: device.createShaderModule({\n code: updateSpritesWGSL,\n }),\n entryPoint: 'main',\n },\n });\n\n const renderPassDescriptor: GPURenderPassDescriptor = {\n colorAttachments: [\n {\n view: undefined as GPUTextureView, // Assigned later\n clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },\n loadOp: 'clear' as const,\n storeOp: 'store' as const,\n },\n ],\n };\n\n const computePassDescriptor: GPUComputePassDescriptor = {};\n\n /** Storage for timestamp query results */\n let querySet: GPUQuerySet | undefined = undefined;\n /** Timestamps are resolved into this buffer */\n let resolveBuffer: GPUBuffer | undefined = undefined;\n /** Pool of spare buffers for MAP_READing the timestamps back to CPU. A buffer\n * is taken from the pool (if available) when a readback is needed, and placed\n * back into the pool once the readback is done and it's unmapped. */\n const spareResultBuffers = [];\n\n if (hasTimestampQuery) {\n querySet = device.createQuerySet({\n type: 'timestamp',\n count: 4,\n });\n resolveBuffer = device.createBuffer({\n size: 4 * BigInt64Array.BYTES_PER_ELEMENT,\n usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,\n });\n computePassDescriptor.timestampWrites = {\n querySet,\n beginningOfPassWriteIndex: 0,\n endOfPassWriteIndex: 1,\n };\n renderPassDescriptor.timestampWrites = {\n querySet,\n beginningOfPassWriteIndex: 2,\n endOfPassWriteIndex: 3,\n };\n }\n\n // prettier-ignore\n const vertexBufferData = new Float32Array([\n -0.01, -0.02, 0.01,\n -0.02, 0.0, 0.02,\n ]);\n\n const spriteVertexBuffer = device.createBuffer({\n size: vertexBufferData.byteLength,\n usage: GPUBufferUsage.VERTEX,\n mappedAtCreation: true,\n });\n new Float32Array(spriteVertexBuffer.getMappedRange()).set(vertexBufferData);\n spriteVertexBuffer.unmap();\n\n const simParams = {\n deltaT: 0.04,\n rule1Distance: 0.1,\n rule2Distance: 0.025,\n rule3Distance: 0.025,\n rule1Scale: 0.02,\n rule2Scale: 0.05,\n rule3Scale: 0.005,\n };\n\n const simParamBufferSize = 7 * Float32Array.BYTES_PER_ELEMENT;\n const simParamBuffer = device.createBuffer({\n size: simParamBufferSize,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n function updateSimParams() {\n device.queue.writeBuffer(\n simParamBuffer,\n 0,\n new Float32Array([\n simParams.deltaT,\n simParams.rule1Distance,\n simParams.rule2Distance,\n simParams.rule3Distance,\n simParams.rule1Scale,\n simParams.rule2Scale,\n simParams.rule3Scale,\n ])\n );\n }\n\n updateSimParams();\n Object.keys(simParams).forEach((k) => {\n const key = k as keyof typeof simParams;\n if (gui === undefined) {\n console.error('GUI not initialized');\n } else {\n gui.add(simParams, key).onFinishChange(updateSimParams);\n }\n });\n\n const numParticles = 1500;\n const initialParticleData = new Float32Array(numParticles * 4);\n for (let i = 0; i < numParticles; ++i) {\n initialParticleData[4 * i + 0] = 2 * (Math.random() - 0.5);\n initialParticleData[4 * i + 1] = 2 * (Math.random() - 0.5);\n initialParticleData[4 * i + 2] = 2 * (Math.random() - 0.5) * 0.1;\n initialParticleData[4 * i + 3] = 2 * (Math.random() - 0.5) * 0.1;\n }\n\n const particleBuffers: GPUBuffer[] = new Array(2);\n const particleBindGroups: GPUBindGroup[] = new Array(2);\n for (let i = 0; i < 2; ++i) {\n particleBuffers[i] = device.createBuffer({\n size: initialParticleData.byteLength,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE,\n mappedAtCreation: true,\n });\n new Float32Array(particleBuffers[i].getMappedRange()).set(\n initialParticleData\n );\n particleBuffers[i].unmap();\n }\n\n for (let i = 0; i < 2; ++i) {\n particleBindGroups[i] = device.createBindGroup({\n layout: computePipeline.getBindGroupLayout(0),\n entries: [\n {\n binding: 0,\n resource: {\n buffer: simParamBuffer,\n },\n },\n {\n binding: 1,\n resource: {\n buffer: particleBuffers[i],\n offset: 0,\n size: initialParticleData.byteLength,\n },\n },\n {\n binding: 2,\n resource: {\n buffer: particleBuffers[(i + 1) % 2],\n offset: 0,\n size: initialParticleData.byteLength,\n },\n },\n ],\n });\n }\n\n let t = 0;\n let computePassDurationSum = 0;\n let renderPassDurationSum = 0;\n let timerSamples = 0;\n function frame() {\n // Sample is no longer the active page.\n if (!pageState.active) return;\n\n renderPassDescriptor.colorAttachments[0].view = context\n .getCurrentTexture()\n .createView();\n\n const commandEncoder = device.createCommandEncoder();\n {\n const passEncoder = commandEncoder.beginComputePass(\n computePassDescriptor\n );\n passEncoder.setPipeline(computePipeline);\n passEncoder.setBindGroup(0, particleBindGroups[t % 2]);\n passEncoder.dispatchWorkgroups(Math.ceil(numParticles / 64));\n passEncoder.end();\n }\n {\n const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);\n passEncoder.setPipeline(renderPipeline);\n passEncoder.setVertexBuffer(0, particleBuffers[(t + 1) % 2]);\n passEncoder.setVertexBuffer(1, spriteVertexBuffer);\n passEncoder.draw(3, numParticles, 0, 0);\n passEncoder.end();\n }\n\n let resultBuffer: GPUBuffer | undefined = undefined;\n if (hasTimestampQuery) {\n resultBuffer =\n spareResultBuffers.pop() ||\n device.createBuffer({\n size: 4 * BigInt64Array.BYTES_PER_ELEMENT,\n usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,\n });\n commandEncoder.resolveQuerySet(querySet, 0, 4, resolveBuffer, 0);\n commandEncoder.copyBufferToBuffer(\n resolveBuffer,\n 0,\n resultBuffer,\n 0,\n resultBuffer.size\n );\n }\n\n device.queue.submit([commandEncoder.finish()]);\n\n if (hasTimestampQuery) {\n resultBuffer.mapAsync(GPUMapMode.READ).then(() => {\n const times = new BigInt64Array(resultBuffer.getMappedRange());\n const computePassDuration = Number(times[1] - times[0]);\n const renderPassDuration = Number(times[3] - times[2]);\n\n // In some cases the timestamps may wrap around and produce a negative\n // number as the GPU resets it's timings. These can safely be ignored.\n if (computePassDuration > 0 && renderPassDuration > 0) {\n computePassDurationSum += computePassDuration;\n renderPassDurationSum += renderPassDuration;\n timerSamples++;\n }\n resultBuffer.unmap();\n\n // Periodically update the text for the timer stats\n const kNumTimerSamplesPerUpdate = 100;\n if (timerSamples >= kNumTimerSamplesPerUpdate) {\n const avgComputeMicroseconds = Math.round(\n computePassDurationSum / timerSamples / 1000\n );\n const avgRenderMicroseconds = Math.round(\n renderPassDurationSum / timerSamples / 1000\n );\n perfDisplay.textContent = `\\\navg compute pass duration: ${avgComputeMicroseconds}\xb5s\navg render pass duration: ${avgRenderMicroseconds}\xb5s\nspare readback buffers: ${spareResultBuffers.length}`;\n computePassDurationSum = 0;\n renderPassDurationSum = 0;\n timerSamples = 0;\n }\n spareResultBuffers.push(resultBuffer);\n });\n }\n\n ++t;\n requestAnimationFrame(frame);\n }\n requestAnimationFrame(frame);\n};\n\nconst ComputeBoids: () => JSX.Element = () =>\n makeSample({\n name: 'Compute Boids',\n description:\n 'A GPU compute particle simulation that mimics \\\nthe flocking behavior of birds. A compute shader updates \\\ntwo ping-pong buffers which store particle data. The data \\\nis used to draw instanced particles.',\n gui: true,\n init,\n sources: [\n {\n name: __filename.substring(__dirname.length + 1),\n contents: __SOURCE__,\n },\n {\n name: 'updateSprites.wgsl',\n contents: updateSpritesWGSL,\n editable: true,\n },\n {\n name: 'sprite.wgsl',\n contents: spriteWGSL,\n editable: true,\n },\n ],\n filename: __filename,\n });\n\nexport default ComputeBoids;\n"},{name:"updateSprites.wgsl",contents:s,editable:!0},{name:"sprite.wgsl",contents:r,editable:!0}],filename:i});var c=l},9147:function(e){e.exports={canvasContainer:"SampleLayout_canvasContainer__zRR_l",sourceFileNav:"SampleLayout_sourceFileNav__ml48P",sourceFileContainer:"SampleLayout_sourceFileContainer__3s84x"}}}]); \ No newline at end of file diff --git a/_next/static/chunks/752.e7b78c9ef05d0be0.js b/_next/static/chunks/752.e7b78c9ef05d0be0.js deleted file mode 100644 index c6e56e5e..00000000 --- a/_next/static/chunks/752.e7b78c9ef05d0be0.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[752],{5671:function(e,n,t){"use strict";t.d(n,{Tl:function(){return p},hu:function(){return f}});var a=t(5893),r=t(9008),i=t.n(r),s=t(1163),o=t(7294),l=t(9147),c=t.n(l);t(7319);let u=e=>{let n=(0,o.useRef)(null),r=(0,o.useMemo)(()=>e.sources.map(e=>{let{name:n,contents:r}=e;return{name:n,...function(e){let n;let r=null;{r=document.createElement("div");let i=t(4631);n=i(r,{lineNumbers:!0,lineWrapping:!0,theme:"monokai",readOnly:!0})}return{Container:function(t){return(0,a.jsx)("div",{...t,children:(0,a.jsx)("div",{ref(t){r&&t&&(t.appendChild(r),n.setOption("value",e))}})})}}}(r)}}),e.sources),l=(0,o.useRef)(null),u=(0,o.useMemo)(()=>{if(e.gui){let n=t(4376);return new n.GUI({autoPlace:!1})}},[]),p=(0,o.useRef)(null),f=(0,o.useMemo)(()=>{if(e.stats){let n=t(2792);return new n}},[]),d=(0,s.useRouter)(),m=d.asPath.match(/#([a-zA-Z0-9\.\/]+)/),[g,v]=(0,o.useState)(null),[P,h]=(0,o.useState)(null);return(0,o.useEffect)(()=>{if(m?h(m[1]):h(r[0].name),u&&l.current)for(l.current.appendChild(u.domElement);u.__controllers.length>0;)u.__controllers[0].remove();f&&p.current&&(f.dom.style.position="absolute",f.showPanel(1),p.current.appendChild(f.dom));let t={active:!0},a=()=>{t.active=!1};try{let i=n.current;if(!i)throw Error("The canvas is not available");let s=e.init({canvas:i,pageState:t,gui:u,stats:f});s instanceof Promise&&s.catch(e=>{console.error(e),v(e)})}catch(o){console.error(o),v(o)}return a},[]),(0,a.jsxs)("main",{children:[(0,a.jsxs)(i(),{children:[(0,a.jsx)("style",{dangerouslySetInnerHTML:{__html:"\n .CodeMirror {\n height: auto !important;\n margin: 1em 0;\n }\n\n .CodeMirror-scroll {\n height: auto !important;\n overflow: visible !important;\n }\n "}}),(0,a.jsx)("title",{children:"".concat(e.name," - WebGPU Samples")}),(0,a.jsx)("meta",{name:"description",content:e.description}),(0,a.jsx)("meta",{httpEquiv:"origin-trial",content:e.originTrial})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h1",{children:e.name}),(0,a.jsx)("a",{target:"_blank",rel:"noreferrer",href:"https://github.com/".concat("webgpu/webgpu-samples","/tree/main/").concat(e.filename),children:"See it on Github!"}),(0,a.jsx)("p",{children:e.description}),g?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"Something went wrong. Do your browser and device support WebGPU?"}),(0,a.jsx)("p",{children:"".concat(g)})]}):null]}),(0,a.jsxs)("div",{className:c().canvasContainer,children:[(0,a.jsx)("div",{style:{position:"absolute",left:10},ref:p}),(0,a.jsx)("div",{style:{position:"absolute",right:10},ref:l}),(0,a.jsx)("canvas",{ref:n})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("nav",{className:c().sourceFileNav,children:(0,a.jsx)("ul",{children:r.map((e,n)=>(0,a.jsx)("li",{children:(0,a.jsx)("a",{href:"#".concat(e.name),"data-active":P==e.name,onClick(){h(e.name)},children:e.name})},n))})}),r.map((e,n)=>(0,a.jsx)(e.Container,{className:c().sourceFileContainer,"data-active":P==e.name},n))]})]})},p=e=>(0,a.jsx)(u,{...e});function f(e,n){if(!e)throw Error(n)}},2752:function(e,n,t){"use strict";t.r(n),t.d(n,{default:function(){return c}});var a=t(5671),r="struct VertexOutput {\n @builtin(position) position : vec4,\n @location(4) color : vec4,\n}\n\n@vertex\nfn vert_main(\n @location(0) a_particlePos : vec2,\n @location(1) a_particleVel : vec2,\n @location(2) a_pos : vec2\n) -> VertexOutput {\n let angle = -atan2(a_particleVel.x, a_particleVel.y);\n let pos = vec2(\n (a_pos.x * cos(angle)) - (a_pos.y * sin(angle)),\n (a_pos.x * sin(angle)) + (a_pos.y * cos(angle))\n );\n \n var output : VertexOutput;\n output.position = vec4(pos + a_particlePos, 0.0, 1.0);\n output.color = vec4(\n 1.0 - sin(angle + 1.0) - a_particleVel.y,\n pos.x * 100.0 - a_particleVel.y + 0.1,\n a_particleVel.x + cos(angle + 0.5),\n 1.0);\n return output;\n}\n\n@fragment\nfn frag_main(@location(4) color : vec4) -> @location(0) vec4 {\n return color;\n}",i="struct Particle {\n pos : vec2,\n vel : vec2,\n}\nstruct SimParams {\n deltaT : f32,\n rule1Distance : f32,\n rule2Distance : f32,\n rule3Distance : f32,\n rule1Scale : f32,\n rule2Scale : f32,\n rule3Scale : f32,\n}\nstruct Particles {\n particles : array,\n}\n@binding(0) @group(0) var params : SimParams;\n@binding(1) @group(0) var particlesA : Particles;\n@binding(2) @group(0) var particlesB : Particles;\n\n// https://github.com/austinEng/Project6-Vulkan-Flocking/blob/master/data/shaders/computeparticles/particle.comp\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) GlobalInvocationID : vec3) {\n var index = GlobalInvocationID.x;\n\n var vPos = particlesA.particles[index].pos;\n var vVel = particlesA.particles[index].vel;\n var cMass = vec2(0.0);\n var cVel = vec2(0.0);\n var colVel = vec2(0.0);\n var cMassCount = 0u;\n var cVelCount = 0u;\n var pos : vec2;\n var vel : vec2;\n\n for (var i = 0u; i < arrayLength(&particlesA.particles); i++) {\n if (i == index) {\n continue;\n }\n\n pos = particlesA.particles[i].pos.xy;\n vel = particlesA.particles[i].vel.xy;\n if (distance(pos, vPos) < params.rule1Distance) {\n cMass += pos;\n cMassCount++;\n }\n if (distance(pos, vPos) < params.rule2Distance) {\n colVel -= pos - vPos;\n }\n if (distance(pos, vPos) < params.rule3Distance) {\n cVel += vel;\n cVelCount++;\n }\n }\n if (cMassCount > 0) {\n cMass = (cMass / vec2(f32(cMassCount))) - vPos;\n }\n if (cVelCount > 0) {\n cVel /= f32(cVelCount);\n }\n vVel += (cMass * params.rule1Scale) + (colVel * params.rule2Scale) + (cVel * params.rule3Scale);\n\n // clamp velocity for a more pleasing simulation\n vVel = normalize(vVel) * clamp(length(vVel), 0.0, 0.1);\n // kinematic update\n vPos = vPos + (vVel * params.deltaT);\n // Wrap around boundary\n if (vPos.x < -1.0) {\n vPos.x = 1.0;\n }\n if (vPos.x > 1.0) {\n vPos.x = -1.0;\n }\n if (vPos.y < -1.0) {\n vPos.y = 1.0;\n }\n if (vPos.y > 1.0) {\n vPos.y = -1.0;\n }\n // Write back\n particlesB.particles[index].pos = vPos;\n particlesB.particles[index].vel = vVel;\n}\n",s="src/sample/computeBoids/main.ts";let o=async e=>{let n,t,{canvas:s,pageState:o,gui:l}=e,c=await navigator.gpu.requestAdapter();(0,a.hu)(c,"requestAdapter returned null");let u=c.features.has("timestamp-query"),p=await c.requestDevice({requiredFeatures:u?["timestamp-query"]:[]}),f=document.createElement("div");f.style.color="white",f.style.background="black",f.style.position="absolute",f.style.top="10px",f.style.left="10px",f.style.textAlign="left";let d=document.createElement("pre");if(f.appendChild(d),s.parentNode?s.parentNode.appendChild(f):console.error("canvas.parentNode is null"),!o.active)return;let m=s.getContext("webgpu"),g=window.devicePixelRatio;s.width=s.clientWidth*g,s.height=s.clientHeight*g;let v=navigator.gpu.getPreferredCanvasFormat();m.configure({device:p,format:v,alphaMode:"premultiplied"});let P=p.createShaderModule({code:r}),h=p.createRenderPipeline({layout:"auto",vertex:{module:P,entryPoint:"vert_main",buffers:[{arrayStride:16,stepMode:"instance",attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"}]},{arrayStride:8,stepMode:"vertex",attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]}]},fragment:{module:P,entryPoint:"frag_main",targets:[{format:v}]},primitive:{topology:"triangle-list"}}),y=p.createComputePipeline({layout:"auto",compute:{module:p.createShaderModule({code:i}),entryPoint:"main"}}),b={colorAttachments:[{view:void 0,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]},x={},S=[];u&&(n=p.createQuerySet({type:"timestamp",count:4}),t=p.createBuffer({size:4*BigInt64Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),x.timestampWrites={querySet:n,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1},b.timestampWrites={querySet:n,beginningOfPassWriteIndex:2,endOfPassWriteIndex:3});let B=new Float32Array([-.01,-.02,.01,-.02,0,.02]),E=p.createBuffer({size:B.byteLength,usage:GPUBufferUsage.VERTEX,mappedAtCreation:!0});new Float32Array(E.getMappedRange()).set(B),E.unmap();let _={deltaT:.04,rule1Distance:.1,rule2Distance:.025,rule3Distance:.025,rule1Scale:.02,rule2Scale:.05,rule3Scale:.005},C=7*Float32Array.BYTES_PER_ELEMENT,D=p.createBuffer({size:C,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});function w(){p.queue.writeBuffer(D,0,new Float32Array([_.deltaT,_.rule1Distance,_.rule2Distance,_.rule3Distance,_.rule1Scale,_.rule2Scale,_.rule3Scale]))}w(),Object.keys(_).forEach(e=>{void 0===l?console.error("GUI not initialized"):l.add(_,e).onFinishChange(w)});let M=new Float32Array(6e3);for(let A=0;A<1500;++A)M[4*A+0]=2*(Math.random()-.5),M[4*A+1]=2*(Math.random()-.5),M[4*A+2]=2*(Math.random()-.5)*.1,M[4*A+3]=2*(Math.random()-.5)*.1;let U=[,,],G=[,,];for(let R=0;R<2;++R)U[R]=p.createBuffer({size:M.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.STORAGE,mappedAtCreation:!0}),new Float32Array(U[R].getMappedRange()).set(M),U[R].unmap();for(let T=0;T<2;++T)G[T]=p.createBindGroup({layout:y.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:D}},{binding:1,resource:{buffer:U[T],offset:0,size:M.byteLength}},{binding:2,resource:{buffer:U[(T+1)%2],offset:0,size:M.byteLength}}]});let V=0,k=0,L=0;requestAnimationFrame(function e(){let a;if(!o.active)return;b.colorAttachments[0].view=m.getCurrentTexture().createView();let r=p.createCommandEncoder();{let i=r.beginComputePass(x);i.setPipeline(y),i.setBindGroup(0,G[V%2]),i.dispatchWorkgroups(Math.ceil(23.4375)),i.end()}{let s=r.beginRenderPass(b);s.setPipeline(h),s.setVertexBuffer(0,U[(V+1)%2]),s.setVertexBuffer(1,E),s.draw(3,1500,0,0),s.end()}u&&(a=S.pop()||p.createBuffer({size:4*BigInt64Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),r.resolveQuerySet(n,0,4,t,0),r.copyBufferToBuffer(t,0,a,0,a.size)),p.queue.submit([r.finish()]),u&&a.mapAsync(GPUMapMode.READ).then(()=>{let e=new BigInt64Array(a.getMappedRange());if(k+=Number(e[1]-e[0]),L+=Number(e[3]-e[2]),a.unmap(),V%100==0){let n=Math.round(k/100/1e3),t=Math.round(L/100/1e3);d.textContent="avg compute pass duration: ".concat(n,"\xb5s\navg render pass duration: ").concat(t,"\xb5s\nspare readback buffers: ").concat(S.length),k=0,L=0}S.push(a)}),++V,requestAnimationFrame(e)})},l=()=>(0,a.Tl)({name:"Compute Boids",description:"A GPU compute particle simulation that mimics the flocking behavior of birds. A compute shader updates two ping-pong buffers which store particle data. The data is used to draw instanced particles.",gui:!0,init:o,sources:[{name:s.substring(24),contents:"import { assert, makeSample, SampleInit } from '../../components/SampleLayout';\n\nimport spriteWGSL from './sprite.wgsl';\nimport updateSpritesWGSL from './updateSprites.wgsl';\n\nconst init: SampleInit = async ({ canvas, pageState, gui }) => {\n const adapter = await navigator.gpu.requestAdapter();\n assert(adapter, 'requestAdapter returned null');\n\n const hasTimestampQuery = adapter.features.has('timestamp-query');\n const device = await adapter.requestDevice({\n requiredFeatures: hasTimestampQuery ? ['timestamp-query'] : [],\n });\n\n const perfDisplayContainer = document.createElement('div');\n perfDisplayContainer.style.color = 'white';\n perfDisplayContainer.style.background = 'black';\n perfDisplayContainer.style.position = 'absolute';\n perfDisplayContainer.style.top = '10px';\n perfDisplayContainer.style.left = '10px';\n perfDisplayContainer.style.textAlign = 'left';\n\n const perfDisplay = document.createElement('pre');\n perfDisplayContainer.appendChild(perfDisplay);\n if (canvas.parentNode) {\n canvas.parentNode.appendChild(perfDisplayContainer);\n } else {\n console.error('canvas.parentNode is null');\n }\n\n if (!pageState.active) return;\n const context = canvas.getContext('webgpu') as GPUCanvasContext;\n const devicePixelRatio = window.devicePixelRatio;\n canvas.width = canvas.clientWidth * devicePixelRatio;\n canvas.height = canvas.clientHeight * devicePixelRatio;\n const presentationFormat = navigator.gpu.getPreferredCanvasFormat();\n\n context.configure({\n device,\n format: presentationFormat,\n alphaMode: 'premultiplied',\n });\n\n const spriteShaderModule = device.createShaderModule({ code: spriteWGSL });\n const renderPipeline = device.createRenderPipeline({\n layout: 'auto',\n vertex: {\n module: spriteShaderModule,\n entryPoint: 'vert_main',\n buffers: [\n {\n // instanced particles buffer\n arrayStride: 4 * 4,\n stepMode: 'instance',\n attributes: [\n {\n // instance position\n shaderLocation: 0,\n offset: 0,\n format: 'float32x2',\n },\n {\n // instance velocity\n shaderLocation: 1,\n offset: 2 * 4,\n format: 'float32x2',\n },\n ],\n },\n {\n // vertex buffer\n arrayStride: 2 * 4,\n stepMode: 'vertex',\n attributes: [\n {\n // vertex positions\n shaderLocation: 2,\n offset: 0,\n format: 'float32x2',\n },\n ],\n },\n ],\n },\n fragment: {\n module: spriteShaderModule,\n entryPoint: 'frag_main',\n targets: [\n {\n format: presentationFormat,\n },\n ],\n },\n primitive: {\n topology: 'triangle-list',\n },\n });\n\n const computePipeline = device.createComputePipeline({\n layout: 'auto',\n compute: {\n module: device.createShaderModule({\n code: updateSpritesWGSL,\n }),\n entryPoint: 'main',\n },\n });\n\n const renderPassDescriptor: GPURenderPassDescriptor = {\n colorAttachments: [\n {\n view: undefined as GPUTextureView, // Assigned later\n clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },\n loadOp: 'clear' as const,\n storeOp: 'store' as const,\n },\n ],\n };\n\n const computePassDescriptor: GPUComputePassDescriptor = {};\n\n /** Storage for timestamp query results */\n let querySet: GPUQuerySet | undefined = undefined;\n /** Timestamps are resolved into this buffer */\n let resolveBuffer: GPUBuffer | undefined = undefined;\n /** Pool of spare buffers for MAP_READing the timestamps back to CPU. A buffer\n * is taken from the pool (if available) when a readback is needed, and placed\n * back into the pool once the readback is done and it's unmapped. */\n const spareResultBuffers = [];\n\n if (hasTimestampQuery) {\n querySet = device.createQuerySet({\n type: 'timestamp',\n count: 4,\n });\n resolveBuffer = device.createBuffer({\n size: 4 * BigInt64Array.BYTES_PER_ELEMENT,\n usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,\n });\n computePassDescriptor.timestampWrites = {\n querySet,\n beginningOfPassWriteIndex: 0,\n endOfPassWriteIndex: 1,\n };\n renderPassDescriptor.timestampWrites = {\n querySet,\n beginningOfPassWriteIndex: 2,\n endOfPassWriteIndex: 3,\n };\n }\n\n // prettier-ignore\n const vertexBufferData = new Float32Array([\n -0.01, -0.02, 0.01,\n -0.02, 0.0, 0.02,\n ]);\n\n const spriteVertexBuffer = device.createBuffer({\n size: vertexBufferData.byteLength,\n usage: GPUBufferUsage.VERTEX,\n mappedAtCreation: true,\n });\n new Float32Array(spriteVertexBuffer.getMappedRange()).set(vertexBufferData);\n spriteVertexBuffer.unmap();\n\n const simParams = {\n deltaT: 0.04,\n rule1Distance: 0.1,\n rule2Distance: 0.025,\n rule3Distance: 0.025,\n rule1Scale: 0.02,\n rule2Scale: 0.05,\n rule3Scale: 0.005,\n };\n\n const simParamBufferSize = 7 * Float32Array.BYTES_PER_ELEMENT;\n const simParamBuffer = device.createBuffer({\n size: simParamBufferSize,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n function updateSimParams() {\n device.queue.writeBuffer(\n simParamBuffer,\n 0,\n new Float32Array([\n simParams.deltaT,\n simParams.rule1Distance,\n simParams.rule2Distance,\n simParams.rule3Distance,\n simParams.rule1Scale,\n simParams.rule2Scale,\n simParams.rule3Scale,\n ])\n );\n }\n\n updateSimParams();\n Object.keys(simParams).forEach((k) => {\n const key = k as keyof typeof simParams;\n if (gui === undefined) {\n console.error('GUI not initialized');\n } else {\n gui.add(simParams, key).onFinishChange(updateSimParams);\n }\n });\n\n const numParticles = 1500;\n const initialParticleData = new Float32Array(numParticles * 4);\n for (let i = 0; i < numParticles; ++i) {\n initialParticleData[4 * i + 0] = 2 * (Math.random() - 0.5);\n initialParticleData[4 * i + 1] = 2 * (Math.random() - 0.5);\n initialParticleData[4 * i + 2] = 2 * (Math.random() - 0.5) * 0.1;\n initialParticleData[4 * i + 3] = 2 * (Math.random() - 0.5) * 0.1;\n }\n\n const particleBuffers: GPUBuffer[] = new Array(2);\n const particleBindGroups: GPUBindGroup[] = new Array(2);\n for (let i = 0; i < 2; ++i) {\n particleBuffers[i] = device.createBuffer({\n size: initialParticleData.byteLength,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE,\n mappedAtCreation: true,\n });\n new Float32Array(particleBuffers[i].getMappedRange()).set(\n initialParticleData\n );\n particleBuffers[i].unmap();\n }\n\n for (let i = 0; i < 2; ++i) {\n particleBindGroups[i] = device.createBindGroup({\n layout: computePipeline.getBindGroupLayout(0),\n entries: [\n {\n binding: 0,\n resource: {\n buffer: simParamBuffer,\n },\n },\n {\n binding: 1,\n resource: {\n buffer: particleBuffers[i],\n offset: 0,\n size: initialParticleData.byteLength,\n },\n },\n {\n binding: 2,\n resource: {\n buffer: particleBuffers[(i + 1) % 2],\n offset: 0,\n size: initialParticleData.byteLength,\n },\n },\n ],\n });\n }\n\n let t = 0;\n let computePassDurationSum = 0;\n let renderPassDurationSum = 0;\n function frame() {\n // Sample is no longer the active page.\n if (!pageState.active) return;\n\n renderPassDescriptor.colorAttachments[0].view = context\n .getCurrentTexture()\n .createView();\n\n const commandEncoder = device.createCommandEncoder();\n {\n const passEncoder = commandEncoder.beginComputePass(\n computePassDescriptor\n );\n passEncoder.setPipeline(computePipeline);\n passEncoder.setBindGroup(0, particleBindGroups[t % 2]);\n passEncoder.dispatchWorkgroups(Math.ceil(numParticles / 64));\n passEncoder.end();\n }\n {\n const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);\n passEncoder.setPipeline(renderPipeline);\n passEncoder.setVertexBuffer(0, particleBuffers[(t + 1) % 2]);\n passEncoder.setVertexBuffer(1, spriteVertexBuffer);\n passEncoder.draw(3, numParticles, 0, 0);\n passEncoder.end();\n }\n\n let resultBuffer: GPUBuffer | undefined = undefined;\n if (hasTimestampQuery) {\n resultBuffer =\n spareResultBuffers.pop() ||\n device.createBuffer({\n size: 4 * BigInt64Array.BYTES_PER_ELEMENT,\n usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,\n });\n commandEncoder.resolveQuerySet(querySet, 0, 4, resolveBuffer, 0);\n commandEncoder.copyBufferToBuffer(\n resolveBuffer,\n 0,\n resultBuffer,\n 0,\n resultBuffer.size\n );\n }\n\n device.queue.submit([commandEncoder.finish()]);\n\n if (hasTimestampQuery) {\n resultBuffer.mapAsync(GPUMapMode.READ).then(() => {\n const times = new BigInt64Array(resultBuffer.getMappedRange());\n computePassDurationSum += Number(times[1] - times[0]);\n renderPassDurationSum += Number(times[3] - times[2]);\n resultBuffer.unmap();\n\n // Periodically update the text for the timer stats\n const kNumTimerSamples = 100;\n if (t % kNumTimerSamples === 0) {\n const avgComputeMicroseconds = Math.round(\n computePassDurationSum / kNumTimerSamples / 1000\n );\n const avgRenderMicroseconds = Math.round(\n renderPassDurationSum / kNumTimerSamples / 1000\n );\n perfDisplay.textContent = `\\\navg compute pass duration: ${avgComputeMicroseconds}\xb5s\navg render pass duration: ${avgRenderMicroseconds}\xb5s\nspare readback buffers: ${spareResultBuffers.length}`;\n computePassDurationSum = 0;\n renderPassDurationSum = 0;\n }\n spareResultBuffers.push(resultBuffer);\n });\n }\n\n ++t;\n requestAnimationFrame(frame);\n }\n requestAnimationFrame(frame);\n};\n\nconst ComputeBoids: () => JSX.Element = () =>\n makeSample({\n name: 'Compute Boids',\n description:\n 'A GPU compute particle simulation that mimics \\\nthe flocking behavior of birds. A compute shader updates \\\ntwo ping-pong buffers which store particle data. The data \\\nis used to draw instanced particles.',\n gui: true,\n init,\n sources: [\n {\n name: __filename.substring(__dirname.length + 1),\n contents: __SOURCE__,\n },\n {\n name: 'updateSprites.wgsl',\n contents: updateSpritesWGSL,\n editable: true,\n },\n {\n name: 'sprite.wgsl',\n contents: spriteWGSL,\n editable: true,\n },\n ],\n filename: __filename,\n });\n\nexport default ComputeBoids;\n"},{name:"updateSprites.wgsl",contents:i,editable:!0},{name:"sprite.wgsl",contents:r,editable:!0}],filename:s});var c=l},9147:function(e){e.exports={canvasContainer:"SampleLayout_canvasContainer__zRR_l",sourceFileNav:"SampleLayout_sourceFileNav__ml48P",sourceFileContainer:"SampleLayout_sourceFileContainer__3s84x"}}}]); \ No newline at end of file diff --git a/_next/static/chunks/webpack-078c99310462cd53.js b/_next/static/chunks/webpack-a203d11d4ee88f02.js similarity index 98% rename from _next/static/chunks/webpack-078c99310462cd53.js rename to _next/static/chunks/webpack-a203d11d4ee88f02.js index 76f2ef64..57cff4ed 100644 --- a/_next/static/chunks/webpack-078c99310462cd53.js +++ b/_next/static/chunks/webpack-a203d11d4ee88f02.js @@ -1 +1 @@ -!function(){"use strict";var e,t,r,n,f,a,c,o,i,u,b={},d={};function l(e){var t=d[e];if(void 0!==t)return t.exports;var r=d[e]={exports:{}},n=!0;try{b[e].call(r.exports,r,r.exports,l),n=!1}finally{n&&delete d[e]}return r.exports}l.m=b,e=[],l.O=function(t,r,n,f){if(r){f=f||0;for(var a=e.length;a>0&&e[a-1][2]>f;a--)e[a]=e[a-1];e[a]=[r,n,f];return}for(var c=1/0,a=0;a=f&&Object.keys(l.O).every(function(e){return l.O[e](r[i])})?r.splice(i--,1):(o=!1,f0&&e[a-1][2]>f;a--)e[a]=e[a-1];e[a]=[r,n,f];return}for(var c=1/0,a=0;a=f&&Object.keys(l.O).every(function(e){return l.O[e](r[i])})?r.splice(i--,1):(o=!1,fWebGPU Samples \ No newline at end of file +WebGPU Samples \ No newline at end of file diff --git a/samples/A-buffer.html b/samples/A-buffer.html index 66729d58..77f6c2ba 100644 --- a/samples/A-buffer.html +++ b/samples/A-buffer.html @@ -10,6 +10,6 @@ } A-Buffer - WebGPU Samples

A-Buffer

See it on Github!

Demonstrates order independent transparency using a per-pixel + limiting memory usage (when required)."/>

\ No newline at end of file + limiting memory usage (when required).

\ No newline at end of file diff --git a/samples/animometer.html b/samples/animometer.html index 734115ef..332f449a 100644 --- a/samples/animometer.html +++ b/samples/animometer.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Animometer - WebGPU Samples \ No newline at end of file + Animometer - WebGPU Samples \ No newline at end of file diff --git a/samples/bitonicSort.html b/samples/bitonicSort.html index 5414d0a8..be3dcace 100644 --- a/samples/bitonicSort.html +++ b/samples/bitonicSort.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Bitonic Sort - WebGPU Samples

Bitonic Sort

See it on Github!

A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.

\ No newline at end of file + Bitonic Sort - WebGPU Samples

Bitonic Sort

See it on Github!

A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.

\ No newline at end of file diff --git a/samples/cameras.html b/samples/cameras.html index 0ca0752b..7d478d1a 100644 --- a/samples/cameras.html +++ b/samples/cameras.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Cameras - WebGPU Samples \ No newline at end of file + Cameras - WebGPU Samples \ No newline at end of file diff --git a/samples/computeBoids.html b/samples/computeBoids.html index 3f35572d..e55a3e5b 100644 --- a/samples/computeBoids.html +++ b/samples/computeBoids.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Compute Boids - WebGPU Samples \ No newline at end of file + Compute Boids - WebGPU Samples \ No newline at end of file diff --git a/samples/cornell.html b/samples/cornell.html index 0d28a981..c7634acc 100644 --- a/samples/cornell.html +++ b/samples/cornell.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Cornell box - WebGPU Samples \ No newline at end of file + Cornell box - WebGPU Samples \ No newline at end of file diff --git a/samples/cubemap.html b/samples/cubemap.html index f7de5fd1..3ceb9701 100644 --- a/samples/cubemap.html +++ b/samples/cubemap.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Cubemap - WebGPU Samples \ No newline at end of file + Cubemap - WebGPU Samples \ No newline at end of file diff --git a/samples/deferredRendering.html b/samples/deferredRendering.html index e87b2707..90dcd7de 100644 --- a/samples/deferredRendering.html +++ b/samples/deferredRendering.html @@ -16,7 +16,7 @@ We also update light position in a compute shader, where further operations like tile/cluster culling could happen. The debug view shows the depth buffer on the left (flipped and scaled a bit to make it more visible), the normal G buffer in the middle, and the albedo G-buffer on the right side of the screen. - "/>

Deferred Rendering

See it on Github!

This example shows how to do deferred rendering with webgpu. + "/>

Deferred Rendering

See it on Github!

This example shows how to do deferred rendering with webgpu. Render geometry info to multiple targets in the gBuffers in the first pass. In this sample we have 2 gBuffers for normals and albedo, along with a depth texture. And then do the lighting in a second pass with per fragment data read from gBuffers so it's independent of scene complexity. @@ -24,4 +24,4 @@ We also update light position in a compute shader, where further operations like tile/cluster culling could happen. The debug view shows the depth buffer on the left (flipped and scaled a bit to make it more visible), the normal G buffer in the middle, and the albedo G-buffer on the right side of the screen. -

\ No newline at end of file +

\ No newline at end of file diff --git a/samples/fractalCube.html b/samples/fractalCube.html index 873f4c34..4c166a1c 100644 --- a/samples/fractalCube.html +++ b/samples/fractalCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Fractal Cube - WebGPU Samples \ No newline at end of file + Fractal Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/gameOfLife.html b/samples/gameOfLife.html index 6369801d..b8552021 100644 --- a/samples/gameOfLife.html +++ b/samples/gameOfLife.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Conway's Game of Life - WebGPU Samples \ No newline at end of file + Conway's Game of Life - WebGPU Samples \ No newline at end of file diff --git a/samples/helloTriangle.html b/samples/helloTriangle.html index d34d98b4..3f546c08 100644 --- a/samples/helloTriangle.html +++ b/samples/helloTriangle.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Hello Triangle - WebGPU Samples \ No newline at end of file + Hello Triangle - WebGPU Samples \ No newline at end of file diff --git a/samples/helloTriangleMSAA.html b/samples/helloTriangleMSAA.html index 701b726a..7de4b2a7 100644 --- a/samples/helloTriangleMSAA.html +++ b/samples/helloTriangleMSAA.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Hello Triangle MSAA - WebGPU Samples \ No newline at end of file + Hello Triangle MSAA - WebGPU Samples \ No newline at end of file diff --git a/samples/imageBlur.html b/samples/imageBlur.html index 8872f38e..06ffbe83 100644 --- a/samples/imageBlur.html +++ b/samples/imageBlur.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Image Blur - WebGPU Samples \ No newline at end of file + Image Blur - WebGPU Samples \ No newline at end of file diff --git a/samples/instancedCube.html b/samples/instancedCube.html index fe474e95..8ef42dbd 100644 --- a/samples/instancedCube.html +++ b/samples/instancedCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Instanced Cube - WebGPU Samples \ No newline at end of file + Instanced Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/normalMap.html b/samples/normalMap.html index 125cd45e..80dbd521 100644 --- a/samples/normalMap.html +++ b/samples/normalMap.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Normal Mapping - WebGPU Samples \ No newline at end of file + Normal Mapping - WebGPU Samples \ No newline at end of file diff --git a/samples/particles.html b/samples/particles.html index 1dabbc5a..cdd56a94 100644 --- a/samples/particles.html +++ b/samples/particles.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Particles - WebGPU Samples \ No newline at end of file + Particles - WebGPU Samples \ No newline at end of file diff --git a/samples/renderBundles.html b/samples/renderBundles.html index c1007575..0e5209b6 100644 --- a/samples/renderBundles.html +++ b/samples/renderBundles.html @@ -11,7 +11,7 @@ Render Bundles - WebGPU Samples

Render Bundles

See it on Github!

This example shows how to use render bundles. It renders a large number of + of instancing to reduce draw overhead.)"/>

Render Bundles

See it on Github!

This example shows how to use render bundles. It renders a large number of meshes individually as a proxy for a more complex scene in order to demonstrate the reduction in JavaScript time spent to issue render commands. (Typically a scene like this would make use - of instancing to reduce draw overhead.)

\ No newline at end of file + of instancing to reduce draw overhead.)

\ No newline at end of file diff --git a/samples/resizeCanvas.html b/samples/resizeCanvas.html index adfc440a..fdd5458a 100644 --- a/samples/resizeCanvas.html +++ b/samples/resizeCanvas.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Resize Canvas - WebGPU Samples \ No newline at end of file + Resize Canvas - WebGPU Samples \ No newline at end of file diff --git a/samples/reversedZ.html b/samples/reversedZ.html index 360bbbe9..7b202854 100644 --- a/samples/reversedZ.html +++ b/samples/reversedZ.html @@ -17,7 +17,7 @@ Related reading: https://developer.nvidia.com/content/depth-precision-visualized https://thxforthefish.com/posts/reverse_z/ - "/>

Reversed Z

See it on Github!

This example shows the use of reversed z technique for better utilization of depth buffer precision. + "/>

Reversed Z

See it on Github!

This example shows the use of reversed z technique for better utilization of depth buffer precision. The left column uses regular method, while the right one uses reversed z technique. Both are using depth32float as their depth buffer format. A set of red and green planes are positioned very close to each other. Higher sets are placed further from camera (and are scaled for better visual purpose). @@ -26,4 +26,4 @@ Related reading: https://developer.nvidia.com/content/depth-precision-visualized https://thxforthefish.com/posts/reverse_z/ -

\ No newline at end of file +

\ No newline at end of file diff --git a/samples/rotatingCube.html b/samples/rotatingCube.html index e5de32ee..65a45af4 100644 --- a/samples/rotatingCube.html +++ b/samples/rotatingCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Rotating Cube - WebGPU Samples \ No newline at end of file + Rotating Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/samplerParameters.html b/samples/samplerParameters.html index 9119d034..678a0b58 100644 --- a/samples/samplerParameters.html +++ b/samples/samplerParameters.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Sampler Parameters - WebGPU Samples

Sampler Parameters

See it on Github!

Visualizes what all the sampler parameters do. Shows a textured plane at various scales (rotated, head-on, in perspective, and in vanishing perspective). The bottom-right view shows the raw contents of the 4 mipmap levels of the test texture (16x16, 8x8, 4x4, and 2x2).

\ No newline at end of file + Sampler Parameters - WebGPU Samples

Sampler Parameters

See it on Github!

Visualizes what all the sampler parameters do. Shows a textured plane at various scales (rotated, head-on, in perspective, and in vanishing perspective). The bottom-right view shows the raw contents of the 4 mipmap levels of the test texture (16x16, 8x8, 4x4, and 2x2).

\ No newline at end of file diff --git a/samples/shadowMapping.html b/samples/shadowMapping.html index b523465f..4fc2d6bc 100644 --- a/samples/shadowMapping.html +++ b/samples/shadowMapping.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Shadow Mapping - WebGPU Samples \ No newline at end of file + Shadow Mapping - WebGPU Samples \ No newline at end of file diff --git a/samples/texturedCube.html b/samples/texturedCube.html index 3bc3d2a2..de3e3276 100644 --- a/samples/texturedCube.html +++ b/samples/texturedCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Textured Cube - WebGPU Samples \ No newline at end of file + Textured Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/twoCubes.html b/samples/twoCubes.html index 17d325e9..a08854e5 100644 --- a/samples/twoCubes.html +++ b/samples/twoCubes.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Two Cubes - WebGPU Samples \ No newline at end of file + Two Cubes - WebGPU Samples \ No newline at end of file diff --git a/samples/videoUploading.html b/samples/videoUploading.html index d79b9d81..dd39e067 100644 --- a/samples/videoUploading.html +++ b/samples/videoUploading.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Video Uploading - WebGPU Samples \ No newline at end of file + Video Uploading - WebGPU Samples \ No newline at end of file diff --git a/samples/videoUploadingWebCodecs.html b/samples/videoUploadingWebCodecs.html index e8cbbbe5..60c73268 100644 --- a/samples/videoUploadingWebCodecs.html +++ b/samples/videoUploadingWebCodecs.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Video Uploading with WebCodecs - WebGPU Samples \ No newline at end of file + Video Uploading with WebCodecs - WebGPU Samples \ No newline at end of file diff --git a/samples/worker.html b/samples/worker.html index 2443359b..bae7896e 100644 --- a/samples/worker.html +++ b/samples/worker.html @@ -10,6 +10,6 @@ } WebGPU in a Worker - WebGPU Samples

WebGPU in a Worker

See it on Github!

This example shows one method of using WebGPU in a web worker and presenting to + which is then transferred to the worker where all the WebGPU calls are made."/>

\ No newline at end of file + which is then transferred to the worker where all the WebGPU calls are made.

\ No newline at end of file