three-gpu-pathtracer 0.0.23 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +53 -528
  2. package/build/index.module.js +319 -66
  3. package/build/index.module.js.map +1 -1
  4. package/build/index.umd.cjs +318 -64
  5. package/build/index.umd.cjs.map +1 -1
  6. package/package.json +35 -18
  7. package/src/core/PathTracingSceneGenerator.js +21 -2
  8. package/src/core/WebGLPathTracer.js +16 -7
  9. package/src/core/utils/mergeGeometries.js +14 -1
  10. package/src/core/utils/sceneUpdateUtils.js +8 -12
  11. package/src/detectors/PrecisionMaterial.js +9 -9
  12. package/src/index.d.ts +2 -1
  13. package/src/index.js +1 -0
  14. package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +2 -1
  15. package/src/materials/pathtracing/glsl/attenuate_hit_function.glsl.js +2 -1
  16. package/src/materials/pathtracing/glsl/camera_util_functions.glsl.js +1 -1
  17. package/src/materials/pathtracing/glsl/get_surface_record_function.glsl.js +2 -1
  18. package/src/materials/surface/AmbientOcclusionMaterial.js +2 -0
  19. package/src/objects/PhysicalSpotLight.js +2 -0
  20. package/src/shader/bsdf/bsdf_functions.glsl.js +0 -1
  21. package/src/shader/bvh/inside_fog_volume_function.glsl.js +1 -1
  22. package/src/shader/structs/material_struct.glsl.js +3 -1
  23. package/src/textures/BlueNoiseTexture.js +6 -6
  24. package/src/textures/ProceduralEquirectTexture.js +8 -7
  25. package/src/textures/turquinMetal.png +0 -0
  26. package/src/uniforms/EquirectHdrInfoUniform.js +9 -4
  27. package/src/uniforms/FloatAttributeTextureArray.js +11 -11
  28. package/src/uniforms/MaterialsTexture.js +13 -10
  29. package/src/webgpu/API.md +762 -0
  30. package/src/webgpu/AtlasTexture.js +471 -0
  31. package/src/webgpu/BlurredEnvMapGenerator.js +129 -0
  32. package/src/webgpu/EquirectBackgroundInfo.js +97 -0
  33. package/src/webgpu/EquirectHdrInfoNode.js +151 -0
  34. package/src/webgpu/LightsInfoNode.js +224 -0
  35. package/src/webgpu/MegaKernelPathTracer.js +277 -0
  36. package/src/webgpu/PathTracerBackend.js +216 -0
  37. package/src/webgpu/TurquinTexture.js +169 -0
  38. package/src/webgpu/WaveFrontPathTracer.js +586 -0
  39. package/src/webgpu/WebGPUPathTracer.js +1302 -0
  40. package/src/webgpu/compute/ComputeKernel.js +92 -0
  41. package/src/webgpu/compute/CopyBufferKernel.js +40 -0
  42. package/src/webgpu/compute/PathTracerMegaKernel.js +470 -0
  43. package/src/webgpu/compute/SampleDebugKernel.js +51 -0
  44. package/src/webgpu/compute/TallySampleCountsKernel.js +111 -0
  45. package/src/webgpu/compute/ZeroOutBufferKernel.js +35 -0
  46. package/src/webgpu/compute/ZeroOutKernel.js +31 -0
  47. package/src/webgpu/compute/wavefront/LogicKernel.js +349 -0
  48. package/src/webgpu/compute/wavefront/MaterialKernel.js +371 -0
  49. package/src/webgpu/compute/wavefront/PopulatePixelIndicesKernel.js +72 -0
  50. package/src/webgpu/compute/wavefront/QueueLengthToDispatchKernel.js +38 -0
  51. package/src/webgpu/compute/wavefront/ResetSlotsKernel.js +66 -0
  52. package/src/webgpu/compute/wavefront/TraceRayKernel.js +71 -0
  53. package/src/webgpu/compute/wavefront/TraceShadowRayKernel.js +67 -0
  54. package/src/webgpu/compute/wavefront/structs.js +155 -0
  55. package/src/webgpu/constants.js +62 -0
  56. package/src/webgpu/denoise/OIDNDenoiser.js +431 -0
  57. package/src/webgpu/index.d.ts +176 -0
  58. package/src/webgpu/index.js +11 -0
  59. package/src/webgpu/materials/GltfCompliantMaterial.js +608 -0
  60. package/src/webgpu/materials/GraphMaterial.js +331 -0
  61. package/src/webgpu/materials/PathtracingMaterial.js +89 -0
  62. package/src/webgpu/materials/RenderToScreenMaterial.js +150 -0
  63. package/src/webgpu/materials/debug/AtlasDebugMaterial.js +41 -0
  64. package/src/webgpu/materials/debug/SampleDensityMaterial.js +61 -0
  65. package/src/webgpu/nodes/PathtracerBVHComputeData.js +1037 -0
  66. package/src/webgpu/nodes/debugBounds.wgsl.js +228 -0
  67. package/src/webgpu/nodes/eon.wgsl.js +262 -0
  68. package/src/webgpu/nodes/ggx.wgsl.js +190 -0
  69. package/src/webgpu/nodes/lights.wgsl.js +203 -0
  70. package/src/webgpu/nodes/material.wgsl.js +990 -0
  71. package/src/webgpu/nodes/rand/bluedither.wgsl.js +92 -0
  72. package/src/webgpu/nodes/rand/pcg.wgsl.js +81 -0
  73. package/src/webgpu/nodes/rand/sobol.wgsl.js +287 -0
  74. package/src/webgpu/nodes/random.wgsl.js +20 -0
  75. package/src/webgpu/nodes/reset.wgsl.js +21 -0
  76. package/src/webgpu/nodes/sampling.wgsl.js +193 -0
  77. package/src/webgpu/nodes/sheen.wgsl.js +148 -0
  78. package/src/webgpu/nodes/structs.wgsl.js +272 -0
  79. package/src/webgpu/nodes/utils.wgsl.js +366 -0
  80. package/src/webgpu/shims/ArrayCameraShim.js +74 -0
  81. package/src/webgpu/shims/EquirectCameraShim.js +37 -0
  82. package/src/webgpu/shims/PhysicalCameraShim.js +151 -0
  83. package/src/webgpu/upscale/FSRUpscaler.js +108 -0
@@ -1,4 +1,4 @@
1
- import { BufferAttribute, BufferGeometry, Matrix4, Vector3, Vector4, Matrix3, MeshBasicMaterial, Mesh, ShaderMaterial, NoBlending, Vector2, WebGLRenderTarget, FloatType, RGBAFormat, NearestFilter, PerspectiveCamera, DataUtils, HalfFloatType, Source, DataTexture, LinearFilter, RepeatWrapping, RedFormat, ClampToEdgeWrapping, Quaternion, DataArrayTexture, DoubleSide, BackSide, FrontSide, Color, WebGLArrayRenderTarget, UnsignedByteType, NoToneMapping, RGFormat, NormalBlending, Spherical, EquirectangularReflectionMapping, LinearMipMapLinearFilter, Clock, Scene, AdditiveBlending, Camera, SpotLight, RectAreaLight, PMREMGenerator, MeshStandardMaterial } from 'three';
1
+ import { BufferAttribute, BufferGeometry, Matrix4, Vector3, Vector4, Matrix3, MeshBasicMaterial, Mesh, ShaderMaterial, NoBlending, Vector2, WebGLRenderTarget, FloatType, RGBAFormat, NearestFilter, PerspectiveCamera, DataUtils, HalfFloatType, Source, DataTexture, LinearFilter, RepeatWrapping, RedFormat, ClampToEdgeWrapping, Quaternion, DataArrayTexture, DoubleSide, BackSide, FrontSide, Color, WebGLArrayRenderTarget, UnsignedByteType, NoToneMapping, RGFormat, NormalBlending, Spherical, EquirectangularReflectionMapping, LinearMipMapLinearFilter, Clock, Scene, AdditiveBlending, Camera, SpotLight, RectAreaLight, PMREMGenerator, MeshStandardMaterial, TangentSpaceNormalMap } from 'three';
2
2
  import { SAH, MeshBVH, FloatVertexAttributeTexture, MeshBVHUniformStruct, UIntVertexAttributeTexture, BVHShaderGLSL } from 'three-mesh-bvh';
3
3
  import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
4
4
 
@@ -277,7 +277,20 @@ function mergeGeometries( geometries, options = {}, targetGeometry = new BufferG
277
277
  const attr = geometry.getAttribute( key );
278
278
  if ( ! skip ) {
279
279
 
280
- copyAttributeContents( attr, targetAttribute, offset );
280
+ if ( key === 'color' && targetAttribute.itemSize !== attr.itemSize ) {
281
+
282
+ // make sure the color attribute is aligned with itemSize 3 to 4
283
+ for ( let index = offset, l = attr.count; index < l; index ++ ) {
284
+
285
+ attr.setXYZW( index, targetAttribute.getX( index ), targetAttribute.getY( index ), targetAttribute.getZ( index ), 1.0 );
286
+
287
+ }
288
+
289
+ } else {
290
+
291
+ copyAttributeContents( attr, targetAttribute, offset );
292
+
293
+ }
281
294
 
282
295
  }
283
296
 
@@ -1315,6 +1328,7 @@ class PathTracingSceneGenerator {
1315
1328
  this._bvhWorker = null;
1316
1329
  this._pendingGenerate = null;
1317
1330
  this._buildAsync = false;
1331
+ this._materialUuids = null;
1318
1332
 
1319
1333
  }
1320
1334
 
@@ -1396,12 +1410,29 @@ class PathTracingSceneGenerator {
1396
1410
  // generate the geometry
1397
1411
  const result = staticGeometryGenerator.generate( geometry );
1398
1412
  const materials = result.materials;
1413
+ let needsMaterialIndexUpdate = result.changeType !== NO_CHANGE || this._materialUuids === null || this._materialUuids.length !== length;
1414
+ if ( ! needsMaterialIndexUpdate ) {
1415
+
1416
+ for ( let i = 0, length = materials.length; i < length; i ++ ) {
1417
+
1418
+ const material = materials[ i ];
1419
+ if ( material.uuid !== this._materialUuids[ i ] ) {
1420
+
1421
+ needsMaterialIndexUpdate = true;
1422
+ break;
1423
+
1424
+ }
1425
+
1426
+ }
1427
+
1428
+ }
1429
+
1399
1430
  const textures = getTextures$1( materials );
1400
1431
  const { lights, iesTextures } = getLights$1( objects );
1401
-
1402
- if ( result.changeType !== NO_CHANGE ) {
1432
+ if ( needsMaterialIndexUpdate ) {
1403
1433
 
1404
1434
  updateMaterialIndexAttribute( geometry, materials, materials );
1435
+ this._materialUuids = materials.map( material => material.uuid );
1405
1436
 
1406
1437
  }
1407
1438
 
@@ -1445,6 +1476,7 @@ class PathTracingSceneGenerator {
1445
1476
  return {
1446
1477
  bvhChanged: result.changeType !== NO_CHANGE,
1447
1478
  bvh: this.bvh,
1479
+ needsMaterialIndexUpdate,
1448
1480
  lights,
1449
1481
  iesTextures,
1450
1482
  geometry,
@@ -2214,6 +2246,12 @@ class EquirectHdrInfoUniform {
2214
2246
 
2215
2247
  }
2216
2248
 
2249
+ getPixelWeight( r, g, b ) {
2250
+
2251
+ return colorToLuminance( r, g, b );
2252
+
2253
+ }
2254
+
2217
2255
  dispose() {
2218
2256
 
2219
2257
  this.marginalWeights.dispose();
@@ -2254,10 +2292,9 @@ class EquirectHdrInfoUniform {
2254
2292
  const g = DataUtils.fromHalfFloat( data[ 4 * i + 1 ] );
2255
2293
  const b = DataUtils.fromHalfFloat( data[ 4 * i + 2 ] );
2256
2294
 
2257
- // the probability of the pixel being selected in this row is the
2258
- // scale of the luminance relative to the rest of the pixels.
2259
- // TODO: this should also account for the solid angle of the pixel when sampling
2260
- const weight = colorToLuminance( r, g, b );
2295
+ // the probability of the pixel being selected in its row is proportional
2296
+ // to its luminance relative to the other pixels.
2297
+ const weight = this.getPixelWeight( r, g, b, y, height );
2261
2298
  cumulativeRowWeight += weight;
2262
2299
  totalSumValue += weight;
2263
2300
 
@@ -2588,17 +2625,17 @@ function copyArrayToArray( fromArray, fromStride, toArray, toStride, offset ) {
2588
2625
  let maxValue = 1.0;
2589
2626
  switch ( fromArray.constructor ) {
2590
2627
 
2591
- case Uint8Array:
2592
- case Uint16Array:
2593
- case Uint32Array:
2594
- maxValue = 2 ** bpe - 1;
2595
- break;
2628
+ case Uint8Array:
2629
+ case Uint16Array:
2630
+ case Uint32Array:
2631
+ maxValue = 2 ** bpe - 1;
2632
+ break;
2596
2633
 
2597
- case Int8Array:
2598
- case Int16Array:
2599
- case Int32Array:
2600
- maxValue = 2 ** ( bpe - 1 ) - 1;
2601
- break;
2634
+ case Int8Array:
2635
+ case Int16Array:
2636
+ case Int32Array:
2637
+ maxValue = 2 ** ( bpe - 1 ) - 1;
2638
+ break;
2602
2639
 
2603
2640
  }
2604
2641
 
@@ -2849,20 +2886,16 @@ function getTextures( materials ) {
2849
2886
  function getLights( scene ) {
2850
2887
 
2851
2888
  const lights = [];
2852
- scene.traverse( c => {
2889
+ scene.traverseVisible( c => {
2853
2890
 
2854
- if ( c.visible ) {
2855
-
2856
- if (
2857
- c.isRectAreaLight ||
2858
- c.isSpotLight ||
2859
- c.isPointLight ||
2860
- c.isDirectionalLight
2861
- ) {
2891
+ if (
2892
+ c.isRectAreaLight ||
2893
+ c.isSpotLight ||
2894
+ c.isPointLight ||
2895
+ c.isDirectionalLight
2896
+ ) {
2862
2897
 
2863
- lights.push( c );
2864
-
2865
- }
2898
+ lights.push( c );
2866
2899
 
2867
2900
  }
2868
2901
 
@@ -2872,7 +2905,7 @@ function getLights( scene ) {
2872
2905
 
2873
2906
  }
2874
2907
 
2875
- const MATERIAL_PIXELS = 45;
2908
+ const MATERIAL_PIXELS = 47;
2876
2909
  const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
2877
2910
 
2878
2911
  class MaterialFeatures {
@@ -3232,15 +3265,15 @@ class MaterialsTexture extends DataTexture {
3232
3265
 
3233
3266
  switch ( m.side ) {
3234
3267
 
3235
- case FrontSide:
3236
- floatArray[ index ++ ] = 1;
3237
- break;
3238
- case BackSide:
3239
- floatArray[ index ++ ] = - 1;
3240
- break;
3241
- case DoubleSide:
3242
- floatArray[ index ++ ] = 0;
3243
- break;
3268
+ case FrontSide:
3269
+ floatArray[ index ++ ] = 1;
3270
+ break;
3271
+ case BackSide:
3272
+ floatArray[ index ++ ] = - 1;
3273
+ break;
3274
+ case DoubleSide:
3275
+ floatArray[ index ++ ] = 0;
3276
+ break;
3244
3277
 
3245
3278
  }
3246
3279
 
@@ -3297,6 +3330,9 @@ class MaterialsTexture extends DataTexture {
3297
3330
  // specularIntensityMap transform 43
3298
3331
  index += writeTextureMatrixToArray( m, 'specularIntensityMap', floatArray, index );
3299
3332
 
3333
+ // alphaMap transform 45
3334
+ index += writeTextureMatrixToArray( m, 'alphaMap', floatArray, index );
3335
+
3300
3336
  }
3301
3337
 
3302
3338
  // check if the contents have changed
@@ -4110,12 +4146,12 @@ function getFormat( channels ) {
4110
4146
 
4111
4147
  switch ( channels ) {
4112
4148
 
4113
- case 1:
4114
- return RedFormat;
4115
- case 2:
4116
- return RGFormat;
4117
- default:
4118
- return RGBAFormat;
4149
+ case 1:
4150
+ return RedFormat;
4151
+ case 2:
4152
+ return RGFormat;
4153
+ default:
4154
+ return RGBAFormat;
4119
4155
 
4120
4156
  }
4121
4157
 
@@ -4376,6 +4412,7 @@ const material_struct = /* glsl */ `
4376
4412
  mat3 iridescenceThicknessMapTransform;
4377
4413
  mat3 specularColorMapTransform;
4378
4414
  mat3 specularIntensityMapTransform;
4415
+ mat3 alphaMapTransform;
4379
4416
 
4380
4417
  };
4381
4418
 
@@ -4396,7 +4433,7 @@ const material_struct = /* glsl */ `
4396
4433
 
4397
4434
  Material readMaterialInfo( sampler2D tex, uint index ) {
4398
4435
 
4399
- uint i = index * 45u;
4436
+ uint i = index * uint( MATERIAL_PIXELS );
4400
4437
 
4401
4438
  vec4 s0 = texelFetch1D( tex, i + 0u );
4402
4439
  vec4 s1 = texelFetch1D( tex, i + 1u );
@@ -4495,6 +4532,7 @@ const material_struct = /* glsl */ `
4495
4532
  m.iridescenceThicknessMapTransform = m.iridescenceThicknessMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 24u );
4496
4533
  m.specularColorMapTransform = m.specularColorMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 26u );
4497
4534
  m.specularIntensityMapTransform = m.specularIntensityMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 28u );
4535
+ m.alphaMapTransform = m.alphaMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 30u );
4498
4536
 
4499
4537
  return m;
4500
4538
 
@@ -5675,7 +5713,6 @@ const bsdf_functions = /* glsl */`
5675
5713
  // See equation (1) in http://www.aconty.com/pdf/s2017_pbs_imageworks_sheen.pdf
5676
5714
  vec3 color = surf.sheenColor;
5677
5715
  color *= D * G / ( 4.0 * abs( cosThetaO * cosThetaI ) );
5678
- color *= wi.z;
5679
5716
 
5680
5717
  return color;
5681
5718
 
@@ -6261,7 +6298,7 @@ const inside_fog_volume_function = /* glsl */`
6261
6298
  // returns whether the given material is a fog material or not
6262
6299
  bool isMaterialFogVolume( sampler2D materials, uint materialIndex ) {
6263
6300
 
6264
- uint i = materialIndex * 45u;
6301
+ uint i = materialIndex * uint( MATERIAL_PIXELS );
6265
6302
  vec4 s14 = texelFetch1D( materials, i + 14u );
6266
6303
  return bool( int( s14.b ) & 4 );
6267
6304
 
@@ -6491,7 +6528,8 @@ const attenuate_hit_function = /* glsl */`
6491
6528
  // alphaMap
6492
6529
  if ( material.alphaMap != - 1 ) {
6493
6530
 
6494
- albedo.a *= texture2D( textures, vec3( uv, material.alphaMap ) ).x;
6531
+ vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
6532
+ albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
6495
6533
 
6496
6534
  }
6497
6535
 
@@ -6633,7 +6671,7 @@ const camera_util_functions = /* glsl */`
6633
6671
  vec3 shapeUVW= rand3( 1 );
6634
6672
  int blades = physicalCamera.apertureBlades;
6635
6673
  float anamorphicRatio = physicalCamera.anamorphicRatio;
6636
- vec2 apertureSample = blades == 0 ? sampleCircle( shapeUVW.xy ) : sampleRegularPolygon( blades, shapeUVW );
6674
+ vec2 apertureSample = sampleAperture( blades, shapeUVW );
6637
6675
  apertureSample *= physicalCamera.bokehSize * 0.5 * 1e-3;
6638
6676
 
6639
6677
  // rotate the aperture shape
@@ -6803,7 +6841,8 @@ const get_surface_record_function = /* glsl */`
6803
6841
  // alphaMap
6804
6842
  if ( material.alphaMap != - 1 ) {
6805
6843
 
6806
- albedo.a *= texture2D( textures, vec3( uv, material.alphaMap ) ).x;
6844
+ vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
6845
+ albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
6807
6846
 
6808
6847
  }
6809
6848
 
@@ -7218,6 +7257,7 @@ class PhysicalPathTracingMaterial extends MaterialBase {
7218
7257
  ATTR_TANGENT: 1,
7219
7258
  ATTR_UV: 2,
7220
7259
  ATTR_COLOR: 3,
7260
+ MATERIAL_PIXELS: MATERIAL_PIXELS,
7221
7261
  },
7222
7262
 
7223
7263
  uniforms: {
@@ -8153,8 +8193,8 @@ class ProceduralEquirectTexture extends DataTexture {
8153
8193
  constructor( width = 512, height = 512 ) {
8154
8194
 
8155
8195
  super(
8156
- new Float32Array( width * height * 4 ),
8157
- width, height, RGBAFormat, FloatType, EquirectangularReflectionMapping,
8196
+ new Uint16Array( width * height * 4 ),
8197
+ width, height, RGBAFormat, HalfFloatType, EquirectangularReflectionMapping,
8158
8198
  RepeatWrapping, ClampToEdgeWrapping, LinearFilter, LinearFilter,
8159
8199
  );
8160
8200
 
@@ -8186,10 +8226,10 @@ class ProceduralEquirectTexture extends DataTexture {
8186
8226
 
8187
8227
  const i = y * width + x;
8188
8228
  const i4 = 4 * i;
8189
- data[ i4 + 0 ] = ( _color.r );
8190
- data[ i4 + 1 ] = ( _color.g );
8191
- data[ i4 + 2 ] = ( _color.b );
8192
- data[ i4 + 3 ] = ( 1.0 );
8229
+ data[ i4 + 0 ] = DataUtils.toHalfFloat( _color.r );
8230
+ data[ i4 + 1 ] = DataUtils.toHalfFloat( _color.g );
8231
+ data[ i4 + 2 ] = DataUtils.toHalfFloat( _color.b );
8232
+ data[ i4 + 3 ] = DataUtils.toHalfFloat( 1.0 );
8193
8233
 
8194
8234
  }
8195
8235
 
@@ -8590,6 +8630,8 @@ class WebGLPathTracer {
8590
8630
 
8591
8631
  constructor( renderer ) {
8592
8632
 
8633
+ console.warn( 'WebGLPathTracer: This class has been deprecated and will be removed in a future release. Use "WebGPUPathTracer" instead.' );
8634
+
8593
8635
  // members
8594
8636
  this._renderer = renderer;
8595
8637
  this._generator = new PathTracingSceneGenerator();
@@ -8794,7 +8836,7 @@ class WebGLPathTracer {
8794
8836
  }
8795
8837
 
8796
8838
  // update scene environment
8797
- material.environmentIntensity = scene.environmentIntensity ?? 1;
8839
+ material.environmentIntensity = scene.environment !== null ? ( scene.environmentIntensity ?? 1 ) : 0;
8798
8840
  material.environmentRotation.makeRotationFromEuler( scene.environmentRotation ).invert();
8799
8841
  if ( this._previousEnvironment !== scene.environment ) {
8800
8842
 
@@ -8814,10 +8856,6 @@ class WebGLPathTracer {
8814
8856
 
8815
8857
  }
8816
8858
 
8817
- } else {
8818
-
8819
- material.environmentIntensity = 0;
8820
-
8821
8859
  }
8822
8860
 
8823
8861
  }
@@ -8835,6 +8873,7 @@ class WebGLPathTracer {
8835
8873
  geometry,
8836
8874
  bvh,
8837
8875
  bvhChanged,
8876
+ needsMaterialIndexUpdate,
8838
8877
  } = results;
8839
8878
 
8840
8879
  this._materials = materials;
@@ -8852,6 +8891,10 @@ class WebGLPathTracer {
8852
8891
  geometry.attributes.color,
8853
8892
  );
8854
8893
 
8894
+ }
8895
+
8896
+ if ( needsMaterialIndexUpdate ) {
8897
+
8855
8898
  material.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
8856
8899
 
8857
8900
  }
@@ -8982,8 +9025,8 @@ class WebGLPathTracer {
8982
9025
 
8983
9026
  dispose() {
8984
9027
 
8985
- this._renderQuad.dispose();
8986
- this._renderQuad.material.dispose();
9028
+ this._quad.dispose();
9029
+ this._quad.material.dispose();
8987
9030
  this._pathTracer.dispose();
8988
9031
 
8989
9032
  }
@@ -9011,6 +9054,12 @@ class WebGLPathTracer {
9011
9054
 
9012
9055
  }
9013
9056
 
9057
+ getRenderTime() {
9058
+
9059
+ return this._clock.getElapsedTime() * 1e3;
9060
+
9061
+ }
9062
+
9014
9063
  }
9015
9064
 
9016
9065
  class EquirectCamera extends Camera {
@@ -9025,6 +9074,8 @@ class EquirectCamera extends Camera {
9025
9074
 
9026
9075
  }
9027
9076
 
9077
+ // TODO: this should extend IESSpotLight, but the class is only exported from "three/webgpu" and
9078
+ // the node library resolves light nodes by exact constructor so a subclass would not rasterize
9028
9079
  class PhysicalSpotLight extends SpotLight {
9029
9080
 
9030
9081
  constructor( ...args ) {
@@ -9355,7 +9406,209 @@ class FogVolumeMaterial extends MeshStandardMaterial {
9355
9406
 
9356
9407
  }
9357
9408
 
9409
+ class AmbientOcclusionMaterial extends MaterialBase {
9410
+
9411
+ get normalMap() {
9412
+
9413
+ return this.uniforms.normalMap.value;
9414
+
9415
+ }
9416
+
9417
+ set normalMap( v ) {
9418
+
9419
+ this.uniforms.normalMap.value = v;
9420
+ this.setDefine( 'USE_NORMALMAP', v ? null : '' );
9421
+
9422
+ }
9423
+
9424
+ get normalMapType() {
9425
+
9426
+ return TangentSpaceNormalMap;
9427
+
9428
+ }
9429
+
9430
+ set normalMapType( v ) {
9431
+
9432
+ if ( v !== TangentSpaceNormalMap ) {
9433
+
9434
+ throw new Error( 'AmbientOcclusionMaterial: Only tangent space normal map are supported' );
9435
+
9436
+ }
9437
+
9438
+ }
9439
+
9440
+ constructor( parameters ) {
9441
+
9442
+ super( {
9443
+
9444
+ defines: {
9445
+ SAMPLES: 10,
9446
+ MATERIAL_PIXELS: MATERIAL_PIXELS,
9447
+ },
9448
+
9449
+ uniforms: {
9450
+ bvh: { value: new MeshBVHUniformStruct() },
9451
+ radius: { value: 1.0 },
9452
+ seed: { value: 0 },
9453
+
9454
+ normalMap: { value: null },
9455
+ normalScale: { value: new Vector2( 1, 1 ) },
9456
+ },
9457
+
9458
+ vertexShader: /* glsl */`
9459
+
9460
+ varying vec3 vNorm;
9461
+ varying vec3 vPos;
9462
+
9463
+ #if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
9464
+
9465
+ varying vec2 vUv;
9466
+ varying vec4 vTan;
9467
+
9468
+ #endif
9469
+
9470
+ void main() {
9471
+
9472
+ vec4 mvPosition = vec4( position, 1.0 );
9473
+ mvPosition = modelViewMatrix * mvPosition;
9474
+ gl_Position = projectionMatrix * mvPosition;
9475
+
9476
+ mat3 modelNormalMatrix = transpose( inverse( mat3( modelMatrix ) ) );
9477
+ vNorm = normalize( modelNormalMatrix * normal );
9478
+ vPos = ( modelMatrix * vec4( position, 1.0 ) ).xyz;
9479
+
9480
+ #if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
9481
+
9482
+ vUv = uv;
9483
+ vTan = tangent;
9484
+
9485
+ #endif
9486
+
9487
+ }
9488
+
9489
+ `,
9490
+
9491
+ fragmentShader: /* glsl */`
9492
+ #define RAY_OFFSET 1e-4
9493
+
9494
+ precision highp isampler2D;
9495
+ precision highp usampler2D;
9496
+ precision highp sampler2DArray;
9497
+ #include <common>
9498
+ #include <cube_uv_reflection_fragment>
9499
+
9500
+ // bvh
9501
+ ${ BVHShaderGLSL.common_functions }
9502
+ ${ BVHShaderGLSL.bvh_struct_definitions }
9503
+ ${ BVHShaderGLSL.bvh_ray_functions }
9504
+
9505
+ // uniform structs
9506
+ ${ material_struct }
9507
+
9508
+ // rand
9509
+ ${ pcg_functions }
9510
+
9511
+ // common
9512
+ ${ shape_sampling_functions }
9513
+
9514
+ uniform BVH bvh;
9515
+ uniform int seed;
9516
+ uniform float radius;
9517
+
9518
+ varying vec3 vNorm;
9519
+ varying vec3 vPos;
9520
+
9521
+ #if defined(USE_NORMALMAP) && defined(USE_TANGENT)
9522
+
9523
+ uniform sampler2D normalMap;
9524
+ uniform vec2 normalScale;
9525
+ varying vec2 vUv;
9526
+ varying vec4 vTan;
9527
+
9528
+ #endif
9529
+
9530
+ void main() {
9531
+
9532
+ rng_initialize( gl_FragCoord.xy, seed );
9533
+
9534
+ // compute the flat face surface normal
9535
+ vec3 fdx = vec3( dFdx( vPos.x ), dFdx( vPos.y ), dFdx( vPos.z ) );
9536
+ vec3 fdy = vec3( dFdy( vPos.x ), dFdy( vPos.y ), dFdy( vPos.z ) );
9537
+ vec3 faceNormal = normalize( cross( fdx, fdy ) );
9538
+
9539
+ // find the max component to scale the offset to account for floating point error
9540
+ vec3 absPoint = abs( vPos );
9541
+ float maxPoint = max( absPoint.x, max( absPoint.y, absPoint.z ) );
9542
+ vec3 normal = vNorm;
9543
+
9544
+ #if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
9545
+
9546
+ // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate
9547
+ // resulting in NaNs and slow path tracing.
9548
+ if ( length( vTan.xyz ) > 0.0 ) {
9549
+
9550
+ vec2 uv = vUv;
9551
+ vec3 tangent = normalize( vTan.xyz );
9552
+ vec3 bitangent = normalize( cross( normal, tangent ) * vTan.w );
9553
+ mat3 vTBN = mat3( tangent, bitangent, normal );
9554
+
9555
+ vec3 texNormal = texture2D( normalMap, uv ).xyz * 2.0 - 1.0;
9556
+ texNormal.xy *= normalScale;
9557
+ normal = vTBN * texNormal;
9558
+
9559
+ }
9560
+
9561
+ #endif
9562
+
9563
+ normal *= gl_FrontFacing ? 1.0 : - 1.0;
9564
+
9565
+ vec3 rayOrigin = vPos + faceNormal * ( maxPoint + 1.0 ) * RAY_OFFSET;
9566
+ float accumulated = 0.0;
9567
+ for ( int i = 0; i < SAMPLES; i ++ ) {
9568
+
9569
+ // sample the cosine weighted hemisphere and discard the sample if it's below
9570
+ // the geometric surface
9571
+ vec3 rayDirection = sampleHemisphere( normalize( normal ), pcgRand4().xy );
9572
+
9573
+ // check if we hit the mesh and its within the specified radius
9574
+ float side = 1.0;
9575
+ float dist = 0.0;
9576
+ vec3 barycoord = vec3( 0.0 );
9577
+ vec3 outNormal = vec3( 0.0 );
9578
+ uvec4 faceIndices = uvec4( 0u );
9579
+
9580
+ // if the ray is above the geometry surface, and it doesn't hit another surface within the specified radius then
9581
+ // we consider it lit
9582
+ if (
9583
+ dot( rayDirection, faceNormal ) > 0.0 &&
9584
+ (
9585
+ ! bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, outNormal, barycoord, side, dist ) ||
9586
+ dist >= radius
9587
+ )
9588
+ ) {
9589
+
9590
+ accumulated += 1.0;
9591
+
9592
+ }
9593
+
9594
+ }
9595
+
9596
+ gl_FragColor.rgb = vec3( accumulated / float( SAMPLES ) );
9597
+ gl_FragColor.a = 1.0;
9598
+
9599
+ }
9600
+
9601
+ `
9602
+
9603
+ } );
9604
+
9605
+ this.setValues( parameters );
9606
+
9607
+ }
9608
+
9609
+ }
9610
+
9358
9611
  // core
9359
9612
 
9360
- export { BlurredEnvMapGenerator, DenoiseMaterial, DynamicPathTracingSceneGenerator, EquirectCamera, FogVolumeMaterial, GradientEquirectTexture, PathTracingRenderer, PathTracingSceneGenerator, PathTracingSceneWorker, PhysicalCamera, PhysicalPathTracingMaterial, PhysicalSpotLight, ProceduralEquirectTexture, ShapedAreaLight, WebGLPathTracer };
9613
+ export { AmbientOcclusionMaterial, BlurredEnvMapGenerator, DenoiseMaterial, DynamicPathTracingSceneGenerator, EquirectCamera, FogVolumeMaterial, GradientEquirectTexture, PathTracingRenderer, PathTracingSceneGenerator, PathTracingSceneWorker, PhysicalCamera, PhysicalPathTracingMaterial, PhysicalSpotLight, ProceduralEquirectTexture, ShapedAreaLight, WebGLPathTracer };
9361
9614
  //# sourceMappingURL=index.module.js.map