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.
- package/README.md +102 -7
- package/build/index.module.js +2891 -2065
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +2886 -2062
- package/build/index.umd.cjs.map +1 -1
- package/package.json +2 -1
- package/src/core/PathTracingRenderer.js +87 -16
- package/src/core/PathTracingSceneGenerator.js +1 -1
- package/src/core/QuiltPathTracingRenderer.js +223 -0
- package/src/index.js +5 -8
- package/src/materials/{GraphMaterial.js → debug/GraphMaterial.js} +1 -1
- package/src/materials/{AlphaDisplayMaterial.js → fullscreen/AlphaDisplayMaterial.js} +1 -1
- package/src/materials/{BlendMaterial.js → fullscreen/BlendMaterial.js} +1 -1
- package/src/materials/{DenoiseMaterial.js → fullscreen/DenoiseMaterial.js} +1 -1
- package/src/materials/{LambertPathTracingMaterial.js → pathtracing/LambertPathTracingMaterial.js} +18 -7
- package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +635 -0
- package/src/materials/pathtracing/glsl/attenuateHit.glsl.js +179 -0
- package/src/materials/pathtracing/glsl/cameraUtils.glsl.js +81 -0
- package/src/materials/pathtracing/glsl/getSurfaceRecord.glsl.js +317 -0
- package/src/materials/pathtracing/glsl/traceScene.glsl.js +54 -0
- package/src/materials/{AmbientOcclusionMaterial.js → surface/AmbientOcclusionMaterial.js} +16 -8
- package/src/materials/surface/FogVolumeMaterial.js +23 -0
- package/src/shader/bsdf/bsdfSampling.glsl.js +490 -0
- package/src/shader/bsdf/fog.glsl.js +23 -0
- package/src/shader/bsdf/ggx.glsl.js +102 -0
- package/src/shader/bsdf/iridescence.glsl.js +135 -0
- package/src/shader/bsdf/sheen.glsl.js +98 -0
- package/src/shader/{shaderLayerTexelFetchFunctions.js → common/arraySamplerTexelFetch.glsl.js} +1 -1
- package/src/shader/common/bvhAnyHit.glsl.js +76 -0
- package/src/shader/common/fresnel.glsl.js +98 -0
- package/src/shader/common/intersectShapes.glsl.js +62 -0
- package/src/shader/common/math.glsl.js +81 -0
- package/src/shader/common/utils.glsl.js +116 -0
- package/src/shader/{shaderRandFunctions.js → rand/pcg.glsl.js} +1 -1
- package/src/shader/{shaderSobolSampling.js → rand/sobol.glsl.js} +3 -3
- package/src/shader/sampling/equirectSampling.glsl.js +62 -0
- package/src/shader/sampling/lightSampling.glsl.js +223 -0
- package/src/shader/sampling/shapeSampling.glsl.js +86 -0
- package/src/shader/structs/cameraStruct.glsl.js +13 -0
- package/src/shader/structs/equirectStruct.glsl.js +14 -0
- package/src/shader/structs/fogMaterialBvh.glsl.js +62 -0
- package/src/shader/structs/lightsStruct.glsl.js +78 -0
- package/src/shader/{shaderStructs.js → structs/materialStruct.glsl.js} +5 -123
- package/src/uniforms/EquirectHdrInfoUniform.js +29 -11
- package/src/uniforms/LightsInfoUniformStruct.js +9 -4
- package/src/uniforms/MaterialsTexture.js +80 -3
- package/src/utils/BlurredEnvMapGenerator.js +2 -2
- package/src/utils/SobolNumberMapGenerator.js +3 -3
- package/src/utils/macroify.js +9 -0
- package/src/materials/PhysicalPathTracingMaterial.js +0 -982
- package/src/shader/shaderBvhAnyHit.js +0 -76
- package/src/shader/shaderEnvMapSampling.js +0 -58
- package/src/shader/shaderGGXFunctions.js +0 -100
- package/src/shader/shaderIridescenceFunctions.js +0 -130
- package/src/shader/shaderLightSampling.js +0 -229
- package/src/shader/shaderMaterialSampling.js +0 -506
- package/src/shader/shaderSheenFunctions.js +0 -98
- 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 =
|
|
6
|
-
let upper = count - 1;
|
|
5
|
+
let lower = offset;
|
|
6
|
+
let upper = offset + count - 1;
|
|
7
|
+
|
|
7
8
|
while ( lower < upper ) {
|
|
8
9
|
|
|
9
|
-
|
|
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[
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
191
|
-
const targetPosition = l.target.
|
|
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
|
-
|
|
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 {
|
|
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
|
-
${
|
|
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 {
|
|
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
|
-
${
|
|
34
|
-
${
|
|
33
|
+
${ sobolCommonGLSL }
|
|
34
|
+
${ sobolGenerationGLSL }
|
|
35
35
|
|
|
36
36
|
varying vec2 vUv;
|
|
37
37
|
uniform vec2 resolution;
|