three-gpu-pathtracer 0.0.24 → 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 (73) hide show
  1. package/README.md +53 -530
  2. package/build/index.module.js +262 -50
  3. package/build/index.module.js.map +1 -1
  4. package/build/index.umd.cjs +261 -48
  5. package/build/index.umd.cjs.map +1 -1
  6. package/package.json +28 -11
  7. package/src/core/WebGLPathTracer.js +8 -0
  8. package/src/core/utils/sceneUpdateUtils.js +8 -12
  9. package/src/detectors/PrecisionMaterial.js +9 -9
  10. package/src/index.js +1 -0
  11. package/src/objects/PhysicalSpotLight.js +2 -0
  12. package/src/shader/bsdf/bsdf_functions.glsl.js +0 -1
  13. package/src/textures/BlueNoiseTexture.js +6 -6
  14. package/src/textures/ProceduralEquirectTexture.js +8 -7
  15. package/src/textures/turquinMetal.png +0 -0
  16. package/src/uniforms/EquirectHdrInfoUniform.js +9 -4
  17. package/src/uniforms/FloatAttributeTextureArray.js +11 -11
  18. package/src/uniforms/MaterialsTexture.js +9 -9
  19. package/src/webgpu/API.md +762 -0
  20. package/src/webgpu/AtlasTexture.js +471 -0
  21. package/src/webgpu/BlurredEnvMapGenerator.js +129 -0
  22. package/src/webgpu/EquirectBackgroundInfo.js +97 -0
  23. package/src/webgpu/EquirectHdrInfoNode.js +151 -0
  24. package/src/webgpu/LightsInfoNode.js +224 -0
  25. package/src/webgpu/MegaKernelPathTracer.js +277 -0
  26. package/src/webgpu/PathTracerBackend.js +216 -0
  27. package/src/webgpu/TurquinTexture.js +169 -0
  28. package/src/webgpu/WaveFrontPathTracer.js +586 -0
  29. package/src/webgpu/WebGPUPathTracer.js +1302 -0
  30. package/src/webgpu/compute/ComputeKernel.js +92 -0
  31. package/src/webgpu/compute/CopyBufferKernel.js +40 -0
  32. package/src/webgpu/compute/PathTracerMegaKernel.js +470 -0
  33. package/src/webgpu/compute/SampleDebugKernel.js +51 -0
  34. package/src/webgpu/compute/TallySampleCountsKernel.js +111 -0
  35. package/src/webgpu/compute/ZeroOutBufferKernel.js +35 -0
  36. package/src/webgpu/compute/ZeroOutKernel.js +31 -0
  37. package/src/webgpu/compute/wavefront/LogicKernel.js +349 -0
  38. package/src/webgpu/compute/wavefront/MaterialKernel.js +371 -0
  39. package/src/webgpu/compute/wavefront/PopulatePixelIndicesKernel.js +72 -0
  40. package/src/webgpu/compute/wavefront/QueueLengthToDispatchKernel.js +38 -0
  41. package/src/webgpu/compute/wavefront/ResetSlotsKernel.js +66 -0
  42. package/src/webgpu/compute/wavefront/TraceRayKernel.js +71 -0
  43. package/src/webgpu/compute/wavefront/TraceShadowRayKernel.js +67 -0
  44. package/src/webgpu/compute/wavefront/structs.js +155 -0
  45. package/src/webgpu/constants.js +62 -0
  46. package/src/webgpu/denoise/OIDNDenoiser.js +431 -0
  47. package/src/webgpu/index.d.ts +176 -0
  48. package/src/webgpu/index.js +11 -0
  49. package/src/webgpu/materials/GltfCompliantMaterial.js +608 -0
  50. package/src/webgpu/materials/GraphMaterial.js +331 -0
  51. package/src/webgpu/materials/PathtracingMaterial.js +89 -0
  52. package/src/webgpu/materials/RenderToScreenMaterial.js +150 -0
  53. package/src/webgpu/materials/debug/AtlasDebugMaterial.js +41 -0
  54. package/src/webgpu/materials/debug/SampleDensityMaterial.js +61 -0
  55. package/src/webgpu/nodes/PathtracerBVHComputeData.js +1037 -0
  56. package/src/webgpu/nodes/debugBounds.wgsl.js +228 -0
  57. package/src/webgpu/nodes/eon.wgsl.js +262 -0
  58. package/src/webgpu/nodes/ggx.wgsl.js +190 -0
  59. package/src/webgpu/nodes/lights.wgsl.js +203 -0
  60. package/src/webgpu/nodes/material.wgsl.js +990 -0
  61. package/src/webgpu/nodes/rand/bluedither.wgsl.js +92 -0
  62. package/src/webgpu/nodes/rand/pcg.wgsl.js +81 -0
  63. package/src/webgpu/nodes/rand/sobol.wgsl.js +287 -0
  64. package/src/webgpu/nodes/random.wgsl.js +20 -0
  65. package/src/webgpu/nodes/reset.wgsl.js +21 -0
  66. package/src/webgpu/nodes/sampling.wgsl.js +193 -0
  67. package/src/webgpu/nodes/sheen.wgsl.js +148 -0
  68. package/src/webgpu/nodes/structs.wgsl.js +272 -0
  69. package/src/webgpu/nodes/utils.wgsl.js +366 -0
  70. package/src/webgpu/shims/ArrayCameraShim.js +74 -0
  71. package/src/webgpu/shims/EquirectCameraShim.js +37 -0
  72. package/src/webgpu/shims/PhysicalCameraShim.js +151 -0
  73. package/src/webgpu/upscale/FSRUpscaler.js +108 -0
@@ -2248,6 +2248,12 @@
2248
2248
 
2249
2249
  }
2250
2250
 
2251
+ getPixelWeight( r, g, b ) {
2252
+
2253
+ return colorToLuminance( r, g, b );
2254
+
2255
+ }
2256
+
2251
2257
  dispose() {
2252
2258
 
2253
2259
  this.marginalWeights.dispose();
@@ -2288,10 +2294,9 @@
2288
2294
  const g = three.DataUtils.fromHalfFloat( data[ 4 * i + 1 ] );
2289
2295
  const b = three.DataUtils.fromHalfFloat( data[ 4 * i + 2 ] );
2290
2296
 
2291
- // the probability of the pixel being selected in this row is the
2292
- // scale of the luminance relative to the rest of the pixels.
2293
- // TODO: this should also account for the solid angle of the pixel when sampling
2294
- const weight = colorToLuminance( r, g, b );
2297
+ // the probability of the pixel being selected in its row is proportional
2298
+ // to its luminance relative to the other pixels.
2299
+ const weight = this.getPixelWeight( r, g, b, y, height );
2295
2300
  cumulativeRowWeight += weight;
2296
2301
  totalSumValue += weight;
2297
2302
 
@@ -2622,17 +2627,17 @@
2622
2627
  let maxValue = 1.0;
2623
2628
  switch ( fromArray.constructor ) {
2624
2629
 
2625
- case Uint8Array:
2626
- case Uint16Array:
2627
- case Uint32Array:
2628
- maxValue = 2 ** bpe - 1;
2629
- break;
2630
+ case Uint8Array:
2631
+ case Uint16Array:
2632
+ case Uint32Array:
2633
+ maxValue = 2 ** bpe - 1;
2634
+ break;
2630
2635
 
2631
- case Int8Array:
2632
- case Int16Array:
2633
- case Int32Array:
2634
- maxValue = 2 ** ( bpe - 1 ) - 1;
2635
- break;
2636
+ case Int8Array:
2637
+ case Int16Array:
2638
+ case Int32Array:
2639
+ maxValue = 2 ** ( bpe - 1 ) - 1;
2640
+ break;
2636
2641
 
2637
2642
  }
2638
2643
 
@@ -2883,20 +2888,16 @@
2883
2888
  function getLights( scene ) {
2884
2889
 
2885
2890
  const lights = [];
2886
- scene.traverse( c => {
2887
-
2888
- if ( c.visible ) {
2889
-
2890
- if (
2891
- c.isRectAreaLight ||
2892
- c.isSpotLight ||
2893
- c.isPointLight ||
2894
- c.isDirectionalLight
2895
- ) {
2891
+ scene.traverseVisible( c => {
2896
2892
 
2897
- lights.push( c );
2893
+ if (
2894
+ c.isRectAreaLight ||
2895
+ c.isSpotLight ||
2896
+ c.isPointLight ||
2897
+ c.isDirectionalLight
2898
+ ) {
2898
2899
 
2899
- }
2900
+ lights.push( c );
2900
2901
 
2901
2902
  }
2902
2903
 
@@ -3266,15 +3267,15 @@
3266
3267
 
3267
3268
  switch ( m.side ) {
3268
3269
 
3269
- case three.FrontSide:
3270
- floatArray[ index ++ ] = 1;
3271
- break;
3272
- case three.BackSide:
3273
- floatArray[ index ++ ] = - 1;
3274
- break;
3275
- case three.DoubleSide:
3276
- floatArray[ index ++ ] = 0;
3277
- break;
3270
+ case three.FrontSide:
3271
+ floatArray[ index ++ ] = 1;
3272
+ break;
3273
+ case three.BackSide:
3274
+ floatArray[ index ++ ] = - 1;
3275
+ break;
3276
+ case three.DoubleSide:
3277
+ floatArray[ index ++ ] = 0;
3278
+ break;
3278
3279
 
3279
3280
  }
3280
3281
 
@@ -4147,12 +4148,12 @@
4147
4148
 
4148
4149
  switch ( channels ) {
4149
4150
 
4150
- case 1:
4151
- return three.RedFormat;
4152
- case 2:
4153
- return three.RGFormat;
4154
- default:
4155
- return three.RGBAFormat;
4151
+ case 1:
4152
+ return three.RedFormat;
4153
+ case 2:
4154
+ return three.RGFormat;
4155
+ default:
4156
+ return three.RGBAFormat;
4156
4157
 
4157
4158
  }
4158
4159
 
@@ -5714,7 +5715,6 @@
5714
5715
  // See equation (1) in http://www.aconty.com/pdf/s2017_pbs_imageworks_sheen.pdf
5715
5716
  vec3 color = surf.sheenColor;
5716
5717
  color *= D * G / ( 4.0 * abs( cosThetaO * cosThetaI ) );
5717
- color *= wi.z;
5718
5718
 
5719
5719
  return color;
5720
5720
 
@@ -8195,8 +8195,8 @@ bool bvhIntersectFogVolumeHit(
8195
8195
  constructor( width = 512, height = 512 ) {
8196
8196
 
8197
8197
  super(
8198
- new Float32Array( width * height * 4 ),
8199
- width, height, three.RGBAFormat, three.FloatType, three.EquirectangularReflectionMapping,
8198
+ new Uint16Array( width * height * 4 ),
8199
+ width, height, three.RGBAFormat, three.HalfFloatType, three.EquirectangularReflectionMapping,
8200
8200
  three.RepeatWrapping, three.ClampToEdgeWrapping, three.LinearFilter, three.LinearFilter,
8201
8201
  );
8202
8202
 
@@ -8228,10 +8228,10 @@ bool bvhIntersectFogVolumeHit(
8228
8228
 
8229
8229
  const i = y * width + x;
8230
8230
  const i4 = 4 * i;
8231
- data[ i4 + 0 ] = ( _color.r );
8232
- data[ i4 + 1 ] = ( _color.g );
8233
- data[ i4 + 2 ] = ( _color.b );
8234
- data[ i4 + 3 ] = ( 1.0 );
8231
+ data[ i4 + 0 ] = three.DataUtils.toHalfFloat( _color.r );
8232
+ data[ i4 + 1 ] = three.DataUtils.toHalfFloat( _color.g );
8233
+ data[ i4 + 2 ] = three.DataUtils.toHalfFloat( _color.b );
8234
+ data[ i4 + 3 ] = three.DataUtils.toHalfFloat( 1.0 );
8235
8235
 
8236
8236
  }
8237
8237
 
@@ -8632,6 +8632,8 @@ bool bvhIntersectFogVolumeHit(
8632
8632
 
8633
8633
  constructor( renderer ) {
8634
8634
 
8635
+ console.warn( 'WebGLPathTracer: This class has been deprecated and will be removed in a future release. Use "WebGPUPathTracer" instead.' );
8636
+
8635
8637
  // members
8636
8638
  this._renderer = renderer;
8637
8639
  this._generator = new PathTracingSceneGenerator();
@@ -9054,6 +9056,12 @@ bool bvhIntersectFogVolumeHit(
9054
9056
 
9055
9057
  }
9056
9058
 
9059
+ getRenderTime() {
9060
+
9061
+ return this._clock.getElapsedTime() * 1e3;
9062
+
9063
+ }
9064
+
9057
9065
  }
9058
9066
 
9059
9067
  class EquirectCamera extends three.Camera {
@@ -9068,6 +9076,8 @@ bool bvhIntersectFogVolumeHit(
9068
9076
 
9069
9077
  }
9070
9078
 
9079
+ // TODO: this should extend IESSpotLight, but the class is only exported from "three/webgpu" and
9080
+ // the node library resolves light nodes by exact constructor so a subclass would not rasterize
9071
9081
  class PhysicalSpotLight extends three.SpotLight {
9072
9082
 
9073
9083
  constructor( ...args ) {
@@ -9398,8 +9408,211 @@ bool bvhIntersectFogVolumeHit(
9398
9408
 
9399
9409
  }
9400
9410
 
9411
+ class AmbientOcclusionMaterial extends MaterialBase {
9412
+
9413
+ get normalMap() {
9414
+
9415
+ return this.uniforms.normalMap.value;
9416
+
9417
+ }
9418
+
9419
+ set normalMap( v ) {
9420
+
9421
+ this.uniforms.normalMap.value = v;
9422
+ this.setDefine( 'USE_NORMALMAP', v ? null : '' );
9423
+
9424
+ }
9425
+
9426
+ get normalMapType() {
9427
+
9428
+ return three.TangentSpaceNormalMap;
9429
+
9430
+ }
9431
+
9432
+ set normalMapType( v ) {
9433
+
9434
+ if ( v !== three.TangentSpaceNormalMap ) {
9435
+
9436
+ throw new Error( 'AmbientOcclusionMaterial: Only tangent space normal map are supported' );
9437
+
9438
+ }
9439
+
9440
+ }
9441
+
9442
+ constructor( parameters ) {
9443
+
9444
+ super( {
9445
+
9446
+ defines: {
9447
+ SAMPLES: 10,
9448
+ MATERIAL_PIXELS: MATERIAL_PIXELS,
9449
+ },
9450
+
9451
+ uniforms: {
9452
+ bvh: { value: new threeMeshBvh.MeshBVHUniformStruct() },
9453
+ radius: { value: 1.0 },
9454
+ seed: { value: 0 },
9455
+
9456
+ normalMap: { value: null },
9457
+ normalScale: { value: new three.Vector2( 1, 1 ) },
9458
+ },
9459
+
9460
+ vertexShader: /* glsl */`
9461
+
9462
+ varying vec3 vNorm;
9463
+ varying vec3 vPos;
9464
+
9465
+ #if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
9466
+
9467
+ varying vec2 vUv;
9468
+ varying vec4 vTan;
9469
+
9470
+ #endif
9471
+
9472
+ void main() {
9473
+
9474
+ vec4 mvPosition = vec4( position, 1.0 );
9475
+ mvPosition = modelViewMatrix * mvPosition;
9476
+ gl_Position = projectionMatrix * mvPosition;
9477
+
9478
+ mat3 modelNormalMatrix = transpose( inverse( mat3( modelMatrix ) ) );
9479
+ vNorm = normalize( modelNormalMatrix * normal );
9480
+ vPos = ( modelMatrix * vec4( position, 1.0 ) ).xyz;
9481
+
9482
+ #if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
9483
+
9484
+ vUv = uv;
9485
+ vTan = tangent;
9486
+
9487
+ #endif
9488
+
9489
+ }
9490
+
9491
+ `,
9492
+
9493
+ fragmentShader: /* glsl */`
9494
+ #define RAY_OFFSET 1e-4
9495
+
9496
+ precision highp isampler2D;
9497
+ precision highp usampler2D;
9498
+ precision highp sampler2DArray;
9499
+ #include <common>
9500
+ #include <cube_uv_reflection_fragment>
9501
+
9502
+ // bvh
9503
+ ${ threeMeshBvh.BVHShaderGLSL.common_functions }
9504
+ ${ threeMeshBvh.BVHShaderGLSL.bvh_struct_definitions }
9505
+ ${ threeMeshBvh.BVHShaderGLSL.bvh_ray_functions }
9506
+
9507
+ // uniform structs
9508
+ ${ material_struct }
9509
+
9510
+ // rand
9511
+ ${ pcg_functions }
9512
+
9513
+ // common
9514
+ ${ shape_sampling_functions }
9515
+
9516
+ uniform BVH bvh;
9517
+ uniform int seed;
9518
+ uniform float radius;
9519
+
9520
+ varying vec3 vNorm;
9521
+ varying vec3 vPos;
9522
+
9523
+ #if defined(USE_NORMALMAP) && defined(USE_TANGENT)
9524
+
9525
+ uniform sampler2D normalMap;
9526
+ uniform vec2 normalScale;
9527
+ varying vec2 vUv;
9528
+ varying vec4 vTan;
9529
+
9530
+ #endif
9531
+
9532
+ void main() {
9533
+
9534
+ rng_initialize( gl_FragCoord.xy, seed );
9535
+
9536
+ // compute the flat face surface normal
9537
+ vec3 fdx = vec3( dFdx( vPos.x ), dFdx( vPos.y ), dFdx( vPos.z ) );
9538
+ vec3 fdy = vec3( dFdy( vPos.x ), dFdy( vPos.y ), dFdy( vPos.z ) );
9539
+ vec3 faceNormal = normalize( cross( fdx, fdy ) );
9540
+
9541
+ // find the max component to scale the offset to account for floating point error
9542
+ vec3 absPoint = abs( vPos );
9543
+ float maxPoint = max( absPoint.x, max( absPoint.y, absPoint.z ) );
9544
+ vec3 normal = vNorm;
9545
+
9546
+ #if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
9547
+
9548
+ // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate
9549
+ // resulting in NaNs and slow path tracing.
9550
+ if ( length( vTan.xyz ) > 0.0 ) {
9551
+
9552
+ vec2 uv = vUv;
9553
+ vec3 tangent = normalize( vTan.xyz );
9554
+ vec3 bitangent = normalize( cross( normal, tangent ) * vTan.w );
9555
+ mat3 vTBN = mat3( tangent, bitangent, normal );
9556
+
9557
+ vec3 texNormal = texture2D( normalMap, uv ).xyz * 2.0 - 1.0;
9558
+ texNormal.xy *= normalScale;
9559
+ normal = vTBN * texNormal;
9560
+
9561
+ }
9562
+
9563
+ #endif
9564
+
9565
+ normal *= gl_FrontFacing ? 1.0 : - 1.0;
9566
+
9567
+ vec3 rayOrigin = vPos + faceNormal * ( maxPoint + 1.0 ) * RAY_OFFSET;
9568
+ float accumulated = 0.0;
9569
+ for ( int i = 0; i < SAMPLES; i ++ ) {
9570
+
9571
+ // sample the cosine weighted hemisphere and discard the sample if it's below
9572
+ // the geometric surface
9573
+ vec3 rayDirection = sampleHemisphere( normalize( normal ), pcgRand4().xy );
9574
+
9575
+ // check if we hit the mesh and its within the specified radius
9576
+ float side = 1.0;
9577
+ float dist = 0.0;
9578
+ vec3 barycoord = vec3( 0.0 );
9579
+ vec3 outNormal = vec3( 0.0 );
9580
+ uvec4 faceIndices = uvec4( 0u );
9581
+
9582
+ // if the ray is above the geometry surface, and it doesn't hit another surface within the specified radius then
9583
+ // we consider it lit
9584
+ if (
9585
+ dot( rayDirection, faceNormal ) > 0.0 &&
9586
+ (
9587
+ ! bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, outNormal, barycoord, side, dist ) ||
9588
+ dist >= radius
9589
+ )
9590
+ ) {
9591
+
9592
+ accumulated += 1.0;
9593
+
9594
+ }
9595
+
9596
+ }
9597
+
9598
+ gl_FragColor.rgb = vec3( accumulated / float( SAMPLES ) );
9599
+ gl_FragColor.a = 1.0;
9600
+
9601
+ }
9602
+
9603
+ `
9604
+
9605
+ } );
9606
+
9607
+ this.setValues( parameters );
9608
+
9609
+ }
9610
+
9611
+ }
9612
+
9401
9613
  // core
9402
9614
 
9615
+ exports.AmbientOcclusionMaterial = AmbientOcclusionMaterial;
9403
9616
  exports.BlurredEnvMapGenerator = BlurredEnvMapGenerator;
9404
9617
  exports.DenoiseMaterial = DenoiseMaterial;
9405
9618
  exports.DynamicPathTracingSceneGenerator = DynamicPathTracingSceneGenerator;