three-gpu-pathtracer 0.0.3 → 0.0.4
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/LICENSE +21 -21
- package/README.md +678 -660
- package/build/index.module.js +3190 -2980
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +3193 -2983
- package/build/index.umd.cjs.map +1 -1
- package/package.json +2 -2
- package/src/core/DynamicPathTracingSceneGenerator.js +106 -106
- package/src/core/MaterialReducer.js +256 -256
- package/src/core/PathTracingRenderer.js +237 -233
- package/src/core/PathTracingSceneGenerator.js +52 -52
- package/src/core/PhysicalCamera.js +28 -28
- package/src/index.js +25 -25
- package/src/materials/AlphaDisplayMaterial.js +48 -48
- package/src/materials/AmbientOcclusionMaterial.js +197 -197
- package/src/materials/BlendMaterial.js +67 -67
- package/src/materials/LambertPathTracingMaterial.js +285 -285
- package/src/materials/MaterialBase.js +56 -56
- package/src/materials/PhysicalPathTracingMaterial.js +684 -632
- package/src/shader/shaderGGXFunctions.js +108 -107
- package/src/shader/shaderMaterialSampling.js +345 -340
- package/src/shader/shaderStructs.js +46 -7
- package/src/shader/shaderUtils.js +246 -228
- package/src/uniforms/EquirectHdrInfoUniform.js +263 -263
- package/src/uniforms/MaterialsTexture.js +251 -173
- package/src/uniforms/PhysicalCameraUniform.js +36 -36
- package/src/uniforms/RenderTarget2DArray.js +17 -4
- package/src/utils/BlurredEnvMapGenerator.js +113 -113
- package/src/utils/GeometryPreparationUtils.js +194 -194
- package/src/utils/UVUnwrapper.js +101 -101
- package/src/workers/PathTracingSceneWorker.js +40 -40
|
@@ -1,173 +1,251 @@
|
|
|
1
|
-
import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, FrontSide, BackSide, DoubleSide } from 'three';
|
|
2
|
-
|
|
3
|
-
const MATERIAL_PIXELS =
|
|
4
|
-
const MATERIAL_STRIDE =
|
|
5
|
-
|
|
6
|
-
export class MaterialsTexture extends DataTexture {
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
|
|
10
|
-
super( new Float32Array( 4 ), 1, 1 );
|
|
11
|
-
|
|
12
|
-
this.format = RGBAFormat;
|
|
13
|
-
this.type = FloatType;
|
|
14
|
-
this.wrapS = ClampToEdgeWrapping;
|
|
15
|
-
this.wrapT = ClampToEdgeWrapping;
|
|
16
|
-
this.generateMipmaps = false;
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
1
|
+
import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, FrontSide, BackSide, DoubleSide } from 'three';
|
|
2
|
+
|
|
3
|
+
const MATERIAL_PIXELS = 19;
|
|
4
|
+
const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
|
|
5
|
+
|
|
6
|
+
export class MaterialsTexture extends DataTexture {
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
|
|
10
|
+
super( new Float32Array( 4 ), 1, 1 );
|
|
11
|
+
|
|
12
|
+
this.format = RGBAFormat;
|
|
13
|
+
this.type = FloatType;
|
|
14
|
+
this.wrapS = ClampToEdgeWrapping;
|
|
15
|
+
this.wrapT = ClampToEdgeWrapping;
|
|
16
|
+
this.generateMipmaps = false;
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
setCastShadow( materialIndex, cast ) {
|
|
21
|
+
|
|
22
|
+
// invert the shadow value so we default to "true" when initializing a material
|
|
23
|
+
const array = this.image.data;
|
|
24
|
+
const index = materialIndex * MATERIAL_STRIDE + 6 * 4 + 0;
|
|
25
|
+
array[ index ] = ! cast ? 1 : 0;
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getCastShadow( materialIndex ) {
|
|
30
|
+
|
|
31
|
+
const array = this.image.data;
|
|
32
|
+
const index = materialIndex * MATERIAL_STRIDE + 6 * 4 + 0;
|
|
33
|
+
return ! Boolean( array[ index ] );
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setSide( materialIndex, side ) {
|
|
38
|
+
|
|
39
|
+
const array = this.image.data;
|
|
40
|
+
const index = materialIndex * MATERIAL_STRIDE + 5 * 4 + 2;
|
|
41
|
+
switch ( side ) {
|
|
42
|
+
|
|
43
|
+
case FrontSide:
|
|
44
|
+
array[ index ] = 1;
|
|
45
|
+
break;
|
|
46
|
+
case BackSide:
|
|
47
|
+
array[ index ] = - 1;
|
|
48
|
+
break;
|
|
49
|
+
case DoubleSide:
|
|
50
|
+
array[ index ] = 0;
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getSide( materialIndex ) {
|
|
58
|
+
|
|
59
|
+
const array = this.image.data;
|
|
60
|
+
const index = materialIndex * MATERIAL_STRIDE + 5 * 4 + 2;
|
|
61
|
+
switch ( array[ index ] ) {
|
|
62
|
+
|
|
63
|
+
case 0:
|
|
64
|
+
return DoubleSide;
|
|
65
|
+
case 1:
|
|
66
|
+
return FrontSide;
|
|
67
|
+
case - 1:
|
|
68
|
+
return BackSide;
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return 0;
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
setMatte( materialIndex, matte ) {
|
|
77
|
+
|
|
78
|
+
const array = this.image.data;
|
|
79
|
+
const index = materialIndex * MATERIAL_STRIDE + 5 * 4 + 3;
|
|
80
|
+
array[ index ] = matte ? 1 : 0;
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getMatte( materialIndex ) {
|
|
85
|
+
|
|
86
|
+
const array = this.image.data;
|
|
87
|
+
const index = materialIndex * MATERIAL_STRIDE + 5 * 4 + 3;
|
|
88
|
+
return Boolean( array[ index ] );
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
updateFrom( materials, textures ) {
|
|
93
|
+
|
|
94
|
+
function getTexture( material, key, def = - 1 ) {
|
|
95
|
+
|
|
96
|
+
return key in material ? textures.indexOf( material[ key ] ) : def;
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getField( material, key, def ) {
|
|
101
|
+
|
|
102
|
+
return key in material ? material[ key ] : def;
|
|
103
|
+
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
*
|
|
108
|
+
* @param {Object} material
|
|
109
|
+
* @param {string} textureKey
|
|
110
|
+
* @param {Float32Array} array
|
|
111
|
+
* @param {number} offset
|
|
112
|
+
* @returns {8} number of floats occupied by texture transform matrix
|
|
113
|
+
*/
|
|
114
|
+
function writeTextureMatrixToArray( material, textureKey, array, offset ) {
|
|
115
|
+
|
|
116
|
+
// check if texture exists
|
|
117
|
+
if ( material[ textureKey ] && material[ textureKey ].isTexture ) {
|
|
118
|
+
|
|
119
|
+
const elements = material[ textureKey ].matrix.elements;
|
|
120
|
+
|
|
121
|
+
let i = 0;
|
|
122
|
+
|
|
123
|
+
// first row
|
|
124
|
+
array[ offset + i ++ ] = elements[ 0 ];
|
|
125
|
+
array[ offset + i ++ ] = elements[ 3 ];
|
|
126
|
+
array[ offset + i ++ ] = elements[ 6 ];
|
|
127
|
+
i ++;
|
|
128
|
+
|
|
129
|
+
// second row
|
|
130
|
+
array[ offset + i ++ ] = elements[ 1 ];
|
|
131
|
+
array[ offset + i ++ ] = elements[ 4 ];
|
|
132
|
+
array[ offset + i ++ ] = elements[ 7 ];
|
|
133
|
+
i ++;
|
|
134
|
+
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return 8;
|
|
138
|
+
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let index = 0;
|
|
142
|
+
const pixelCount = materials.length * MATERIAL_PIXELS;
|
|
143
|
+
const dimension = Math.ceil( Math.sqrt( pixelCount ) );
|
|
144
|
+
|
|
145
|
+
if ( this.image.width !== dimension ) {
|
|
146
|
+
|
|
147
|
+
this.dispose();
|
|
148
|
+
|
|
149
|
+
this.image.data = new Float32Array( dimension * dimension * 4 );
|
|
150
|
+
this.image.width = dimension;
|
|
151
|
+
this.image.height = dimension;
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const floatArray = this.image.data;
|
|
156
|
+
|
|
157
|
+
// on some devices (Google Pixel 6) the "floatBitsToInt" function does not work correctly so we
|
|
158
|
+
// can't encode texture ids that way.
|
|
159
|
+
// const intArray = new Int32Array( floatArray.buffer );
|
|
160
|
+
|
|
161
|
+
for ( let i = 0, l = materials.length; i < l; i ++ ) {
|
|
162
|
+
|
|
163
|
+
const m = materials[ i ];
|
|
164
|
+
|
|
165
|
+
// color
|
|
166
|
+
floatArray[ index ++ ] = m.color.r;
|
|
167
|
+
floatArray[ index ++ ] = m.color.g;
|
|
168
|
+
floatArray[ index ++ ] = m.color.b;
|
|
169
|
+
floatArray[ index ++ ] = getTexture( m, 'map' );
|
|
170
|
+
|
|
171
|
+
// metalness & roughness
|
|
172
|
+
floatArray[ index ++ ] = getField( m, 'metalness', 0.0 );
|
|
173
|
+
floatArray[ index ++ ] = textures.indexOf( m.metalnessMap );
|
|
174
|
+
floatArray[ index ++ ] = getField( m, 'roughness', 0.0 );
|
|
175
|
+
floatArray[ index ++ ] = textures.indexOf( m.roughnessMap );
|
|
176
|
+
|
|
177
|
+
// transmission & emissiveIntensity
|
|
178
|
+
floatArray[ index ++ ] = getField( m, 'ior', 1.0 );
|
|
179
|
+
floatArray[ index ++ ] = getField( m, 'transmission', 0.0 );
|
|
180
|
+
floatArray[ index ++ ] = getTexture( m, 'transmissionMap' );
|
|
181
|
+
floatArray[ index ++ ] = getField( m, 'emissiveIntensity', 0.0 );
|
|
182
|
+
|
|
183
|
+
// emission
|
|
184
|
+
if ( 'emissive' in m ) {
|
|
185
|
+
|
|
186
|
+
floatArray[ index ++ ] = m.emissive.r;
|
|
187
|
+
floatArray[ index ++ ] = m.emissive.g;
|
|
188
|
+
floatArray[ index ++ ] = m.emissive.b;
|
|
189
|
+
|
|
190
|
+
} else {
|
|
191
|
+
|
|
192
|
+
floatArray[ index ++ ] = 0.0;
|
|
193
|
+
floatArray[ index ++ ] = 0.0;
|
|
194
|
+
floatArray[ index ++ ] = 0.0;
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
floatArray[ index ++ ] = getTexture( m, 'emissiveMap' );
|
|
199
|
+
|
|
200
|
+
// normals
|
|
201
|
+
floatArray[ index ++ ] = getTexture( m, 'normalMap' );
|
|
202
|
+
if ( 'normalScale' in m ) {
|
|
203
|
+
|
|
204
|
+
floatArray[ index ++ ] = m.normalScale.x;
|
|
205
|
+
floatArray[ index ++ ] = m.normalScale.y;
|
|
206
|
+
|
|
207
|
+
} else {
|
|
208
|
+
|
|
209
|
+
floatArray[ index ++ ] = 1;
|
|
210
|
+
floatArray[ index ++ ] = 1;
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
floatArray[ index ++ ] = getTexture( m, 'alphaMap' );
|
|
215
|
+
|
|
216
|
+
// side & matte
|
|
217
|
+
floatArray[ index ++ ] = m.opacity;
|
|
218
|
+
floatArray[ index ++ ] = m.alphaTest;
|
|
219
|
+
index ++; // side
|
|
220
|
+
index ++; // matte
|
|
221
|
+
|
|
222
|
+
index ++; // shadow
|
|
223
|
+
index ++;
|
|
224
|
+
index ++;
|
|
225
|
+
index ++;
|
|
226
|
+
|
|
227
|
+
// map transform
|
|
228
|
+
index += writeTextureMatrixToArray( m, 'map', floatArray, index );
|
|
229
|
+
|
|
230
|
+
// metalnessMap transform
|
|
231
|
+
index += writeTextureMatrixToArray( m, 'metalnessMap', floatArray, index );
|
|
232
|
+
|
|
233
|
+
// roughnessMap transform
|
|
234
|
+
index += writeTextureMatrixToArray( m, 'roughnessMap', floatArray, index );
|
|
235
|
+
|
|
236
|
+
// transmissionMap transform
|
|
237
|
+
index += writeTextureMatrixToArray( m, 'transmissionMap', floatArray, index );
|
|
238
|
+
|
|
239
|
+
// emissiveMap transform
|
|
240
|
+
index += writeTextureMatrixToArray( m, 'emissiveMap', floatArray, index );
|
|
241
|
+
|
|
242
|
+
// normalMap transform
|
|
243
|
+
index += writeTextureMatrixToArray( m, 'normalMap', floatArray, index );
|
|
244
|
+
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
this.needsUpdate = true;
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
}
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { PhysicalCamera } from '../core/PhysicalCamera.js';
|
|
2
|
-
export class PhysicalCameraUniform {
|
|
3
|
-
|
|
4
|
-
constructor() {
|
|
5
|
-
|
|
6
|
-
this.bokehSize = 0;
|
|
7
|
-
this.apertureBlades = 0;
|
|
8
|
-
this.apertureRotation = 0;
|
|
9
|
-
this.focusDistance = 10;
|
|
10
|
-
this.anamorphicRatio = 1;
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
updateFrom( camera ) {
|
|
15
|
-
|
|
16
|
-
if ( camera instanceof PhysicalCamera ) {
|
|
17
|
-
|
|
18
|
-
this.bokehSize = camera.bokehSize;
|
|
19
|
-
this.apertureBlades = camera.apertureBlades;
|
|
20
|
-
this.apertureRotation = camera.apertureRotation;
|
|
21
|
-
this.focusDistance = camera.focusDistance;
|
|
22
|
-
this.anamorphicRatio = camera.anamorphicRatio;
|
|
23
|
-
|
|
24
|
-
} else {
|
|
25
|
-
|
|
26
|
-
this.bokehSize = 0;
|
|
27
|
-
this.apertureRotation = 0;
|
|
28
|
-
this.apertureBlades = 0;
|
|
29
|
-
this.focusDistance = 10;
|
|
30
|
-
this.anamorphicRatio = 1;
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
}
|
|
1
|
+
import { PhysicalCamera } from '../core/PhysicalCamera.js';
|
|
2
|
+
export class PhysicalCameraUniform {
|
|
3
|
+
|
|
4
|
+
constructor() {
|
|
5
|
+
|
|
6
|
+
this.bokehSize = 0;
|
|
7
|
+
this.apertureBlades = 0;
|
|
8
|
+
this.apertureRotation = 0;
|
|
9
|
+
this.focusDistance = 10;
|
|
10
|
+
this.anamorphicRatio = 1;
|
|
11
|
+
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
updateFrom( camera ) {
|
|
15
|
+
|
|
16
|
+
if ( camera instanceof PhysicalCamera ) {
|
|
17
|
+
|
|
18
|
+
this.bokehSize = camera.bokehSize;
|
|
19
|
+
this.apertureBlades = camera.apertureBlades;
|
|
20
|
+
this.apertureRotation = camera.apertureRotation;
|
|
21
|
+
this.focusDistance = camera.focusDistance;
|
|
22
|
+
this.anamorphicRatio = camera.anamorphicRatio;
|
|
23
|
+
|
|
24
|
+
} else {
|
|
25
|
+
|
|
26
|
+
this.bokehSize = 0;
|
|
27
|
+
this.apertureRotation = 0;
|
|
28
|
+
this.apertureBlades = 0;
|
|
29
|
+
this.focusDistance = 10;
|
|
30
|
+
this.anamorphicRatio = 1;
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -44,6 +44,7 @@ export class RenderTarget2DArray extends WebGLArrayRenderTarget {
|
|
|
44
44
|
renderer.getClearColor( prevColor );
|
|
45
45
|
|
|
46
46
|
// resize the render target and ensure we don't have an empty texture
|
|
47
|
+
// render target depth must be >= 1 to avoid unbound texture error on android devices
|
|
47
48
|
const depth = textures.length || 1;
|
|
48
49
|
this.setSize( width, height, depth );
|
|
49
50
|
renderer.setClearColor( 0, 0 );
|
|
@@ -54,11 +55,23 @@ export class RenderTarget2DArray extends WebGLArrayRenderTarget {
|
|
|
54
55
|
for ( let i = 0, l = depth; i < l; i ++ ) {
|
|
55
56
|
|
|
56
57
|
const texture = textures[ i ];
|
|
57
|
-
|
|
58
|
-
fsQuad.material.transparent = true;
|
|
58
|
+
if ( texture ) {
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
// revert to default texture transform before rendering
|
|
61
|
+
texture.matrixAutoUpdate = false;
|
|
62
|
+
texture.matrix.identity();
|
|
63
|
+
|
|
64
|
+
fsQuad.material.map = texture;
|
|
65
|
+
fsQuad.material.transparent = true;
|
|
66
|
+
|
|
67
|
+
renderer.setRenderTarget( this, i );
|
|
68
|
+
fsQuad.render( renderer );
|
|
69
|
+
|
|
70
|
+
// restore custom texture transform
|
|
71
|
+
texture.updateMatrix();
|
|
72
|
+
texture.matrixAutoUpdate = true;
|
|
73
|
+
|
|
74
|
+
}
|
|
62
75
|
|
|
63
76
|
}
|
|
64
77
|
|