three-gpu-pathtracer 0.0.12 → 0.0.14

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 (58) hide show
  1. package/README.md +102 -7
  2. package/build/index.module.js +2891 -2065
  3. package/build/index.module.js.map +1 -1
  4. package/build/index.umd.cjs +2886 -2062
  5. package/build/index.umd.cjs.map +1 -1
  6. package/package.json +2 -1
  7. package/src/core/PathTracingRenderer.js +87 -16
  8. package/src/core/PathTracingSceneGenerator.js +1 -1
  9. package/src/core/QuiltPathTracingRenderer.js +223 -0
  10. package/src/index.js +5 -8
  11. package/src/materials/{GraphMaterial.js → debug/GraphMaterial.js} +1 -1
  12. package/src/materials/{AlphaDisplayMaterial.js → fullscreen/AlphaDisplayMaterial.js} +1 -1
  13. package/src/materials/{BlendMaterial.js → fullscreen/BlendMaterial.js} +1 -1
  14. package/src/materials/{DenoiseMaterial.js → fullscreen/DenoiseMaterial.js} +1 -1
  15. package/src/materials/{LambertPathTracingMaterial.js → pathtracing/LambertPathTracingMaterial.js} +18 -7
  16. package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +635 -0
  17. package/src/materials/pathtracing/glsl/attenuateHit.glsl.js +179 -0
  18. package/src/materials/pathtracing/glsl/cameraUtils.glsl.js +81 -0
  19. package/src/materials/pathtracing/glsl/getSurfaceRecord.glsl.js +317 -0
  20. package/src/materials/pathtracing/glsl/traceScene.glsl.js +54 -0
  21. package/src/materials/{AmbientOcclusionMaterial.js → surface/AmbientOcclusionMaterial.js} +16 -8
  22. package/src/materials/surface/FogVolumeMaterial.js +23 -0
  23. package/src/shader/bsdf/bsdfSampling.glsl.js +490 -0
  24. package/src/shader/bsdf/fog.glsl.js +23 -0
  25. package/src/shader/bsdf/ggx.glsl.js +102 -0
  26. package/src/shader/bsdf/iridescence.glsl.js +135 -0
  27. package/src/shader/bsdf/sheen.glsl.js +98 -0
  28. package/src/shader/{shaderLayerTexelFetchFunctions.js → common/arraySamplerTexelFetch.glsl.js} +1 -1
  29. package/src/shader/common/bvhAnyHit.glsl.js +76 -0
  30. package/src/shader/common/fresnel.glsl.js +98 -0
  31. package/src/shader/common/intersectShapes.glsl.js +62 -0
  32. package/src/shader/common/math.glsl.js +81 -0
  33. package/src/shader/common/utils.glsl.js +116 -0
  34. package/src/shader/{shaderRandFunctions.js → rand/pcg.glsl.js} +1 -1
  35. package/src/shader/{shaderSobolSampling.js → rand/sobol.glsl.js} +3 -3
  36. package/src/shader/sampling/equirectSampling.glsl.js +62 -0
  37. package/src/shader/sampling/lightSampling.glsl.js +223 -0
  38. package/src/shader/sampling/shapeSampling.glsl.js +86 -0
  39. package/src/shader/structs/cameraStruct.glsl.js +13 -0
  40. package/src/shader/structs/equirectStruct.glsl.js +14 -0
  41. package/src/shader/structs/fogMaterialBvh.glsl.js +62 -0
  42. package/src/shader/structs/lightsStruct.glsl.js +78 -0
  43. package/src/shader/{shaderStructs.js → structs/materialStruct.glsl.js} +5 -123
  44. package/src/uniforms/EquirectHdrInfoUniform.js +29 -11
  45. package/src/uniforms/LightsInfoUniformStruct.js +9 -4
  46. package/src/uniforms/MaterialsTexture.js +80 -3
  47. package/src/utils/BlurredEnvMapGenerator.js +2 -2
  48. package/src/utils/SobolNumberMapGenerator.js +3 -3
  49. package/src/utils/macroify.js +9 -0
  50. package/src/materials/PhysicalPathTracingMaterial.js +0 -982
  51. package/src/shader/shaderBvhAnyHit.js +0 -76
  52. package/src/shader/shaderEnvMapSampling.js +0 -58
  53. package/src/shader/shaderGGXFunctions.js +0 -100
  54. package/src/shader/shaderIridescenceFunctions.js +0 -130
  55. package/src/shader/shaderLightSampling.js +0 -229
  56. package/src/shader/shaderMaterialSampling.js +0 -506
  57. package/src/shader/shaderSheenFunctions.js +0 -98
  58. package/src/shader/shaderUtils.js +0 -361
@@ -1,16 +1,20 @@
1
- import { DataTexture, FloatType, RedFormat, LinearFilter, DataUtils, HalfFloatType, Source, RepeatWrapping } from 'three';
1
+ import { DataTexture, FloatType, RedFormat, LinearFilter, DataUtils, HalfFloatType, Source, RepeatWrapping, RGBAFormat } from 'three';
2
2
 
3
3
  function binarySearchFindClosestIndexOf( array, targetValue, offset = 0, count = array.length ) {
4
4
 
5
- let lower = 0;
6
- let upper = count - 1;
5
+ let lower = offset;
6
+ let upper = offset + count - 1;
7
+
7
8
  while ( lower < upper ) {
8
9
 
9
- const mid = ~ ~ ( 0.5 * upper + 0.5 * lower );
10
+ // calculate the midpoint for this iteration using a bitwise shift right operator to save 1 floating point multiplication
11
+ // and 1 truncation from the double tilde operator to improve performance
12
+ // this results in much better performance over using standard "~ ~ ( (lower + upper) ) / 2" to calculate the midpoint
13
+ const mid = ( lower + upper ) >> 1;
10
14
 
11
15
  // check if the middle array value is above or below the target and shift
12
16
  // which half of the array we're looking at
13
- if ( array[ offset + mid ] < targetValue ) {
17
+ if ( array[ mid ] < targetValue ) {
14
18
 
15
19
  lower = mid + 1;
16
20
 
@@ -22,7 +26,7 @@ function binarySearchFindClosestIndexOf( array, targetValue, offset = 0, count =
22
26
 
23
27
  }
24
28
 
25
- return lower;
29
+ return lower - offset;
26
30
 
27
31
  }
28
32
 
@@ -92,31 +96,45 @@ export class EquirectHdrInfoUniform {
92
96
 
93
97
  constructor() {
94
98
 
99
+ // Default to a white texture and associated weights so we don't
100
+ // just render black initially.
101
+ const whiteTex = new DataTexture( new Float32Array( [ 1, 1, 1, 1 ] ), 1, 1 );
102
+ whiteTex.type = FloatType;
103
+ whiteTex.format = RGBAFormat;
104
+ whiteTex.minFilter = LinearFilter;
105
+ whiteTex.magFilter = LinearFilter;
106
+ whiteTex.wrapS = RepeatWrapping;
107
+ whiteTex.wrapT = RepeatWrapping;
108
+ whiteTex.generateMipmaps = false;
109
+ whiteTex.needsUpdate = true;
110
+
95
111
  // Stores a map of [0, 1] value -> cumulative importance row & pdf
96
112
  // used to sampling a random value to a relevant row to sample from
97
- const marginalWeights = new DataTexture();
113
+ const marginalWeights = new DataTexture( new Float32Array( [ 0, 1 ] ), 1, 2 );
98
114
  marginalWeights.type = FloatType;
99
115
  marginalWeights.format = RedFormat;
100
116
  marginalWeights.minFilter = LinearFilter;
101
117
  marginalWeights.magFilter = LinearFilter;
102
118
  marginalWeights.generateMipmaps = false;
119
+ marginalWeights.needsUpdate = true;
103
120
 
104
121
  // Stores a map of [0, 1] value -> cumulative importance column & pdf
105
122
  // used to sampling a random value to a relevant pixel to sample from
106
- const conditionalWeights = new DataTexture();
123
+ const conditionalWeights = new DataTexture( new Float32Array( [ 0, 0, 1, 1 ] ), 2, 2 );
107
124
  conditionalWeights.type = FloatType;
108
125
  conditionalWeights.format = RedFormat;
109
126
  conditionalWeights.minFilter = LinearFilter;
110
127
  conditionalWeights.magFilter = LinearFilter;
111
128
  conditionalWeights.generateMipmaps = false;
129
+ conditionalWeights.needsUpdate = true;
112
130
 
131
+ this.map = whiteTex;
113
132
  this.marginalWeights = marginalWeights;
114
133
  this.conditionalWeights = conditionalWeights;
115
- this.map = null;
116
134
 
117
135
  // the total sum value is separated into two values to work around low precision
118
136
  // storage of floating values in structs
119
- this.totalSumWhole = 0;
137
+ this.totalSumWhole = 1;
120
138
  this.totalSumDecimal = 0;
121
139
 
122
140
  }
@@ -125,7 +143,7 @@ export class EquirectHdrInfoUniform {
125
143
 
126
144
  this.marginalWeights.dispose();
127
145
  this.conditionalWeights.dispose();
128
- if ( this.map ) this.map.dispose();
146
+ this.map.dispose();
129
147
 
130
148
  }
131
149
 
@@ -170,7 +170,10 @@ export class LightsInfoUniformStruct {
170
170
 
171
171
  } else if ( l.isPointLight ) {
172
172
 
173
- const worldPosition = l.getWorldPosition( u );
173
+ const worldPosition = u.setFromMatrixPosition( l.matrixWorld );
174
+
175
+ // sample 3
176
+ // u vector
174
177
  floatArray[ baseIndex + ( index ++ ) ] = worldPosition.x;
175
178
  floatArray[ baseIndex + ( index ++ ) ] = worldPosition.y;
176
179
  floatArray[ baseIndex + ( index ++ ) ] = worldPosition.z;
@@ -187,10 +190,12 @@ export class LightsInfoUniformStruct {
187
190
 
188
191
  } else if ( l.isDirectionalLight ) {
189
192
 
190
- const worldPosition = l.getWorldPosition( u );
191
- const targetPosition = l.target.getWorldPosition( v );
192
-
193
+ const worldPosition = u.setFromMatrixPosition( l.matrixWorld );
194
+ const targetPosition = v.setFromMatrixPosition( l.target.matrixWorld );
193
195
  target.subVectors( worldPosition, targetPosition ).normalize();
196
+
197
+ // sample 3
198
+ // u vector
194
199
  floatArray[ baseIndex + ( index ++ ) ] = target.x;
195
200
  floatArray[ baseIndex + ( index ++ ) ] = target.y;
196
201
  floatArray[ baseIndex + ( index ++ ) ] = target.z;
@@ -7,6 +7,42 @@ const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
7
7
  const MATTE_OFFSET = 14 * 4 + 0; // s14.r
8
8
  const SHADOW_OFFSET = 14 * 4 + 1; // s14.g
9
9
 
10
+ class MaterialFeatures {
11
+
12
+ constructor() {
13
+
14
+ this._features = {};
15
+
16
+ }
17
+
18
+ isUsed( feature ) {
19
+
20
+ return feature in this._features;
21
+
22
+ }
23
+
24
+ setUsed( feature, used = true ) {
25
+
26
+ if ( used === false ) {
27
+
28
+ delete this._features[ feature ];
29
+
30
+ } else {
31
+
32
+ this._features[ feature ] = true;
33
+
34
+ }
35
+
36
+ }
37
+
38
+ reset() {
39
+
40
+ this._features = {};
41
+
42
+ }
43
+
44
+ }
45
+
10
46
  export class MaterialsTexture extends DataTexture {
11
47
 
12
48
  constructor() {
@@ -19,6 +55,7 @@ export class MaterialsTexture extends DataTexture {
19
55
  this.wrapT = ClampToEdgeWrapping;
20
56
  this.generateMipmaps = false;
21
57
  this.threeCompatibilityTransforms = false;
58
+ this.features = new MaterialFeatures();
22
59
 
23
60
  }
24
61
 
@@ -148,7 +185,7 @@ export class MaterialsTexture extends DataTexture {
148
185
  let index = 0;
149
186
  const pixelCount = materials.length * MATERIAL_PIXELS;
150
187
  const dimension = Math.ceil( Math.sqrt( pixelCount ) );
151
- const { threeCompatibilityTransforms, image } = this;
188
+ const { threeCompatibilityTransforms, image, features } = this;
152
189
 
153
190
  // get the list of textures with unique sources
154
191
  const uniqueTextures = reduceTexturesToUniqueSources( textures );
@@ -175,10 +212,49 @@ export class MaterialsTexture extends DataTexture {
175
212
  // can't encode texture ids that way.
176
213
  // const intArray = new Int32Array( floatArray.buffer );
177
214
 
215
+ features.reset();
178
216
  for ( let i = 0, l = materials.length; i < l; i ++ ) {
179
217
 
180
218
  const m = materials[ i ];
181
219
 
220
+ if ( m.isFogVolumeMaterial ) {
221
+
222
+ features.setUsed( 'FOG' );
223
+
224
+ for ( let j = 0; j < MATERIAL_STRIDE; j ++ ) {
225
+
226
+ floatArray[ index + j ] = 0;
227
+
228
+ }
229
+
230
+ // sample 0 .rgb
231
+ floatArray[ index + 0 * 4 + 0 ] = m.color.r;
232
+ floatArray[ index + 0 * 4 + 1 ] = m.color.g;
233
+ floatArray[ index + 0 * 4 + 2 ] = m.color.b;
234
+
235
+ // sample 2 .a
236
+ floatArray[ index + 2 * 4 + 3 ] = getField( m, 'emissiveIntensity', 0.0 );
237
+
238
+ // sample 3 .rgb
239
+ floatArray[ index + 3 * 4 + 0 ] = m.emissive.r;
240
+ floatArray[ index + 3 * 4 + 1 ] = m.emissive.g;
241
+ floatArray[ index + 3 * 4 + 2 ] = m.emissive.b;
242
+
243
+ // sample 13 .g
244
+ // reusing opacity field
245
+ floatArray[ index + 13 * 4 + 1 ] = m.density;
246
+
247
+ // side
248
+ floatArray[ index + 13 * 4 + 3 ] = 0.0;
249
+
250
+ // sample 14 .b
251
+ floatArray[ index + 14 * 4 + 2 ] = 1 << 2;
252
+
253
+ index += MATERIAL_STRIDE;
254
+ continue;
255
+
256
+ }
257
+
182
258
  // sample 0
183
259
  // color
184
260
  floatArray[ index ++ ] = m.color.r;
@@ -257,7 +333,7 @@ export class MaterialsTexture extends DataTexture {
257
333
  }
258
334
 
259
335
  index ++;
260
- index ++;
336
+ floatArray[ index ++ ] = getField( m, 'sheen', 0.0 );
261
337
 
262
338
  // sample 7
263
339
  // sheen
@@ -285,7 +361,8 @@ export class MaterialsTexture extends DataTexture {
285
361
  floatArray[ index ++ ] = getTexture( m, 'iridescenceMap' );
286
362
  floatArray[ index ++ ] = getTexture( m, 'iridescenceThicknessMap' );
287
363
 
288
- floatArray[ index ++ ] = getField( m, 'iridescence', 0.0 ); // sample 9
364
+ // sample 9
365
+ floatArray[ index ++ ] = getField( m, 'iridescence', 0.0 );
289
366
  floatArray[ index ++ ] = getField( m, 'iridescenceIOR', 1.3 );
290
367
 
291
368
  const iridescenceThicknessRange = getField( m, 'iridescenceThicknessRange', [ 100, 400 ] );
@@ -1,7 +1,7 @@
1
1
  import { WebGLRenderTarget, RGBAFormat, FloatType, PMREMGenerator, DataTexture, EquirectangularReflectionMapping } from 'three';
2
2
  import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
3
3
  import { MaterialBase } from '../materials/MaterialBase.js';
4
- import { shaderUtils } from '../shader/shaderUtils.js';
4
+ import { utilsGLSL } from '../shader/common/utils.glsl.js';
5
5
 
6
6
  class PMREMCopyMaterial extends MaterialBase {
7
7
 
@@ -31,7 +31,7 @@ class PMREMCopyMaterial extends MaterialBase {
31
31
  #include <common>
32
32
  #include <cube_uv_reflection_fragment>
33
33
 
34
- ${ shaderUtils }
34
+ ${ utilsGLSL }
35
35
 
36
36
  uniform sampler2D envMap;
37
37
  uniform float blur;
@@ -1,7 +1,7 @@
1
1
  import { FloatType, NearestFilter, NoBlending, RGBAFormat, Vector2, WebGLRenderTarget } from 'three';
2
2
  import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
3
3
  import { MaterialBase } from '../materials/MaterialBase.js';
4
- import { shaderSobolCommon, shaderSobolGeneration } from '../shader/shaderSobolSampling.js';
4
+ import { sobolCommonGLSL, sobolGenerationGLSL } from '../shader/rand/sobol.glsl.js';
5
5
 
6
6
  class SobolNumbersMaterial extends MaterialBase {
7
7
 
@@ -30,8 +30,8 @@ class SobolNumbersMaterial extends MaterialBase {
30
30
 
31
31
  fragmentShader: /* glsl */`
32
32
 
33
- ${ shaderSobolCommon }
34
- ${ shaderSobolGeneration }
33
+ ${ sobolCommonGLSL }
34
+ ${ sobolGenerationGLSL }
35
35
 
36
36
  varying vec2 vUv;
37
37
  uniform vec2 resolution;
@@ -0,0 +1,9 @@
1
+ export function macroify( contents ) {
2
+
3
+ return contents
4
+ .trim()
5
+ .replace( /\/\/.*[\n\r]/g, '' )
6
+ .split( /[\n\r]+/ )
7
+ .join( '\\\n' ) + '\\\n';
8
+
9
+ }