11/* eslint-disable prettier/prettier */ 
22import  {  mat4 ,  mat3  }  from  'wgpu-matrix' ; 
3+ import  {  GUI  }  from  'dat.gui' ; 
34import  {  modelData  }  from  './models' ; 
5+ import  {  randElement ,  randColor  }  from  './utils' ; 
46import  solidColorLitWGSL  from  './solidColorLit.wgsl' ; 
57import  wireframeWGSL  from  './wireframe.wgsl' ; 
68
@@ -9,11 +11,11 @@ type TypedArrayView = Float32Array | Uint32Array;
911function  createBufferWithData ( 
1012  device : GPUDevice , 
1113  data : TypedArrayView , 
12-   usage : number 
14+   usage : GPUBufferUsageFlags , 
1315)  { 
1416  const  buffer  =  device . createBuffer ( { 
1517    size : data . byteLength , 
16-     usage :  usage , 
18+     usage, 
1719  } ) ; 
1820  device . queue . writeBuffer ( buffer ,  0 ,  data ) ; 
1921  return  buffer ; 
@@ -66,25 +68,6 @@ const depthFormat = 'depth24plus';
6668
6769const  models  =  Object . values ( modelData ) . map ( data  =>  createVertexAndIndexBuffer ( device ,  data ) ) ; 
6870
69- function  rand ( min ?: number ,  max ?: number )  { 
70-   if  ( min  ===  undefined )  { 
71-     max  =  1 ; 
72-     min  =  0 ; 
73-   }  else  if  ( max  ===  undefined )  { 
74-     max  =  min ; 
75-     min  =  0 ; 
76-   } 
77-   return  Math . random ( )  *  ( max  -  min )  +  min ; 
78- } 
79- 
80- function  randInt ( min : number ,  max ?: number )  { 
81-   return  Math . floor ( rand ( min ,  max ) ) ; 
82- } 
83- 
84- function  randColor ( )  { 
85-   return  [ rand ( ) ,  rand ( ) ,  rand ( ) ,  1 ] ; 
86- } 
87- 
8871const  litModule  =  device . createShaderModule ( { 
8972  code : solidColorLitWGSL , 
9073} ) ; 
@@ -141,6 +124,7 @@ const wireframePipeline = device.createRenderPipeline({
141124  } , 
142125  fragment : { 
143126    module : wireframeModule , 
127+     entryPoint : 'fs' , 
144128    targets : [ {  format : presentationFormat  } ] , 
145129  } , 
146130  primitive : { 
@@ -153,13 +137,51 @@ const wireframePipeline = device.createRenderPipeline({
153137  } , 
154138} ) ; 
155139
140+ const  barycentricCoordinatesBasedWireframePipeline  =  device . createRenderPipeline ( { 
141+   label : 'barycentric coordinates based wireframe pipeline' , 
142+   layout : 'auto' , 
143+   vertex : { 
144+     module : wireframeModule , 
145+     entryPoint : 'vsIndexedU32BarycentricCoordinateBasedLines' , 
146+   } , 
147+   fragment : { 
148+     module : wireframeModule , 
149+     entryPoint : 'fsBarycentricCoordinateBasedLines' , 
150+     targets : [ 
151+       { 
152+         format : presentationFormat , 
153+         blend : { 
154+           color : { 
155+             srcFactor : 'one' , 
156+             dstFactor : 'one-minus-src-alpha' , 
157+           } , 
158+           alpha : { 
159+             srcFactor : 'one' , 
160+             dstFactor : 'one-minus-src-alpha' , 
161+           } , 
162+         } , 
163+       } , 
164+     ] , 
165+   } , 
166+   primitive : { 
167+     topology : 'triangle-list' , 
168+   } , 
169+   depthStencil : { 
170+     depthWriteEnabled : true , 
171+     depthCompare : 'less-equal' , 
172+     format : depthFormat , 
173+   } , 
174+ } ) ; 
175+ 
156176type  ObjectInfo  =  { 
157177  worldViewProjectionMatrixValue : Float32Array ; 
158178  worldMatrixValue : Float32Array ; 
159179  uniformValues : Float32Array ; 
160180  uniformBuffer : GPUBuffer ; 
181+   lineUniformValues : Float32Array ; 
182+   lineUniformBuffer : GPUBuffer ; 
161183  litBindGroup : GPUBindGroup ; 
162-   wireframeBindGroup : GPUBindGroup ; 
184+   wireframeBindGroups : GPUBindGroup [ ] ; 
163185  model : Model ; 
164186} ; 
165187
@@ -187,29 +209,47 @@ for (let i = 0; i < numObjects; ++i) {
187209  const  colorValue  =  uniformValues . subarray ( kColorOffset ,  kColorOffset  +  4 ) ; 
188210  colorValue . set ( randColor ( ) ) ; 
189211
190-   const  model  =  models [ randInt ( models . length ) ] ; 
212+   const  model  =  randElement ( models ) ; 
191213
192214  // Make a bind group for this uniform 
193215  const  litBindGroup  =  device . createBindGroup ( { 
194216    layout : litPipeline . getBindGroupLayout ( 0 ) , 
195217    entries : [ {  binding : 0 ,  resource : {  buffer : uniformBuffer  }  } ] , 
196218  } ) ; 
197219
198-   const  strideValues  =  new  Uint32Array ( 1  +  3 ) ; 
199-   const  strideBuffer  =  device . createBuffer ( { 
200-     size : strideValues . byteLength , 
220+   // Note: We're making one lineUniformBuffer per object. 
221+   // This is only because stride might be different per object. 
222+   // In this sample stride is the same across all objects so 
223+   // we could have made just a single shared uniform buffer for  
224+   // these settings. 
225+   const  lineUniformValues  =  new  Float32Array ( 3  +  1 ) ; 
226+   const  lineUniformValuesAsU32  =  new  Uint32Array ( lineUniformValues . buffer ) ; 
227+   const  lineUniformBuffer  =  device . createBuffer ( { 
228+     size : lineUniformValues . byteLength , 
201229    usage : GPUBufferUsage . UNIFORM  |  GPUBufferUsage . COPY_DST , 
202230  } ) ; 
203-   strideValues [ 0 ]  =  6 ; 
204-   device . queue . writeBuffer ( strideBuffer ,  0 ,  strideValues ) ; 
231+   lineUniformValuesAsU32 [ 0 ]  =  6 ;   // the array stride for positions for this model. 
205232
233+   // We're creating 2 bindGroups, one for each pipeline. 
234+   // We could create just one since they are identical. To do 
235+   // so we'd have to manually create a bindGroupLayout. 
206236  const  wireframeBindGroup  =  device . createBindGroup ( { 
207237    layout : wireframePipeline . getBindGroupLayout ( 0 ) , 
208238    entries : [ 
209239      {  binding : 0 ,  resource : {  buffer : uniformBuffer  }  } , 
210240      {  binding : 1 ,  resource : {  buffer : model . vertexBuffer  }  } , 
211241      {  binding : 2 ,  resource : {  buffer : model . indexBuffer  }  } , 
212-       {  binding : 3 ,  resource : {  buffer : strideBuffer  }  } , 
242+       {  binding : 3 ,  resource : {  buffer : lineUniformBuffer  }  } , 
243+     ] , 
244+   } ) ; 
245+ 
246+   const  barycentricCoordinatesBasedWireframeBindGroup  =  device . createBindGroup ( { 
247+     layout : barycentricCoordinatesBasedWireframePipeline . getBindGroupLayout ( 0 ) , 
248+     entries : [ 
249+       {  binding : 0 ,  resource : {  buffer : uniformBuffer  }  } , 
250+       {  binding : 1 ,  resource : {  buffer : model . vertexBuffer  }  } , 
251+       {  binding : 2 ,  resource : {  buffer : model . indexBuffer  }  } , 
252+       {  binding : 3 ,  resource : {  buffer : lineUniformBuffer  }  } , 
213253    ] , 
214254  } ) ; 
215255
@@ -218,8 +258,13 @@ for (let i = 0; i < numObjects; ++i) {
218258    worldMatrixValue, 
219259    uniformValues, 
220260    uniformBuffer, 
261+     lineUniformValues, 
262+     lineUniformBuffer, 
221263    litBindGroup, 
222-     wireframeBindGroup, 
264+     wireframeBindGroups : [ 
265+       wireframeBindGroup , 
266+       barycentricCoordinatesBasedWireframeBindGroup , 
267+     ] , 
223268    model, 
224269  } ) ; 
225270} 
@@ -242,7 +287,45 @@ const renderPassDescriptor: GPURenderPassDescriptor = {
242287  } , 
243288} ; 
244289
245- let  depthTexture ; 
290+ const  settings  =  { 
291+   barycentricCoordinatesBased : false , 
292+   thickness : 2 , 
293+   alphaThreshold : 0.5 , 
294+   lines : true , 
295+   models : true , 
296+ } ; 
297+ 
298+ const  gui  =  new  GUI ( ) ; 
299+ gui . add ( settings ,  'barycentricCoordinatesBased' ) . onChange ( addRemoveGUI ) ; 
300+ gui . add ( settings ,  'lines' ) ; 
301+ gui . add ( settings ,  'models' ) ; 
302+ 
303+ const  guis  =  [ ] ; 
304+ function  addRemoveGUI ( )  { 
305+   if  ( settings . barycentricCoordinatesBased )  { 
306+     guis . push ( 
307+       gui . add ( settings ,  'thickness' ,  0.0 ,  10 ) . onChange ( updateThickness ) , 
308+       gui . add ( settings ,  'alphaThreshold' ,  0 ,  1 ) . onChange ( updateThickness ) , 
309+     ) ; 
310+   }  else  { 
311+     guis . forEach ( g  =>  g . remove ( ) ) ; 
312+     guis . length  =  0 ; 
313+   } 
314+ } 
315+ 
316+ function  updateThickness ( )  { 
317+   objectInfos . forEach ( ( { 
318+     lineUniformBuffer, 
319+     lineUniformValues, 
320+   } )  =>  { 
321+     lineUniformValues [ 1 ]  =  settings . thickness ; 
322+     lineUniformValues [ 2 ]  =  settings . alphaThreshold ; 
323+     device . queue . writeBuffer ( lineUniformBuffer ,  0 ,  lineUniformValues ) ; 
324+   } ) ; 
325+ } 
326+ updateThickness ( ) ; 
327+ 
328+ let  depthTexture : GPUTexture  |  undefined ; 
246329
247330function  render ( time : number )  { 
248331  time  *=  0.001 ;  // convert to seconds; 
@@ -311,20 +394,27 @@ function render(time: number) {
311394    // Upload our uniform values. 
312395    device . queue . writeBuffer ( uniformBuffer ,  0 ,  uniformValues ) ; 
313396
314-     pass . setVertexBuffer ( 0 ,  vertexBuffer ) ; 
315-     pass . setIndexBuffer ( indexBuffer ,  indexFormat ) ; 
316-     pass . setBindGroup ( 0 ,  litBindGroup ) ; 
317-     pass . drawIndexed ( vertexCount ) ; 
397+     if  ( settings . models )  { 
398+       pass . setVertexBuffer ( 0 ,  vertexBuffer ) ; 
399+       pass . setIndexBuffer ( indexBuffer ,  indexFormat ) ; 
400+       pass . setBindGroup ( 0 ,  litBindGroup ) ; 
401+       pass . drawIndexed ( vertexCount ) ; 
402+     } 
318403  } ) ; 
319404
320-   objectInfos . forEach ( ( { 
321-       wireframeBindGroup, 
322-       model : {  vertexCount } , 
323-     } )  =>  { 
324-     pass . setPipeline ( wireframePipeline ) ; 
325-     pass . setBindGroup ( 0 ,  wireframeBindGroup ) 
326-     pass . draw ( vertexCount  *  2 ) ; 
327-   } ) ; 
405+   if  ( settings . lines )  { 
406+     // Note: If we're using the line-list based pipeline then we need to 
407+     // multiply the vertex count by 2 since we need to emit 6 vertices 
408+     // for each triangle (3 edges). 
409+     const  [ bindGroupNdx ,  countMult ,  pipeline ]  =  settings . barycentricCoordinatesBased 
410+        ? [ 1 ,  1 ,  barycentricCoordinatesBasedWireframePipeline ] 
411+        : [ 0 ,  2 ,  wireframePipeline ] ; 
412+     pass . setPipeline ( pipeline ) ; 
413+     objectInfos . forEach ( ( {  wireframeBindGroups,  model : {  vertexCount }  } )  =>  { 
414+       pass . setBindGroup ( 0 ,  wireframeBindGroups [ bindGroupNdx ] ) ; 
415+       pass . draw ( vertexCount  *  countMult ) ; 
416+     } ) ; 
417+   } 
328418
329419  pass . end ( ) ; 
330420
0 commit comments