three-gpu-pathtracer 0.0.20 → 0.0.21
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 +111 -464
- package/build/index.module.js +5691 -5312
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +5369 -5003
- package/build/index.umd.cjs.map +1 -1
- package/package.json +12 -6
- package/src/core/PathTracingRenderer.js +59 -46
- package/src/core/PathTracingSceneGenerator.js +245 -10
- package/src/core/WebGLPathTracer.js +472 -0
- package/src/core/utils/BakedGeometry.js +35 -0
- package/src/core/utils/BufferAttributeUtils.js +64 -0
- package/src/{utils → core/utils}/GeometryPreparationUtils.js +35 -35
- package/src/core/utils/MeshDiff.js +102 -0
- package/src/core/utils/StaticGeometryGenerator.js +285 -0
- package/src/core/utils/convertToStaticGeometry.js +344 -0
- package/src/core/utils/mergeGeometries.js +218 -0
- package/src/core/utils/sceneUpdateUtils.js +96 -0
- package/src/index.d.ts +274 -0
- package/src/index.js +4 -20
- package/src/materials/MaterialBase.js +4 -0
- package/src/materials/fullscreen/ClampedInterpolationMaterial.js +112 -0
- package/src/materials/fullscreen/DenoiseMaterial.js +4 -0
- package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +73 -76
- package/src/materials/pathtracing/glsl/{attenuateHit.glsl.js → attenuate_hit_function.glsl.js} +1 -1
- package/src/materials/pathtracing/glsl/{cameraUtils.glsl.js → camera_util_functions.glsl.js} +1 -1
- package/src/materials/pathtracing/glsl/{directLightContribution.glsl.js → direct_light_contribution_function.glsl.js} +1 -1
- package/src/materials/pathtracing/glsl/{getSurfaceRecord.glsl.js → get_surface_record_function.glsl.js} +1 -1
- package/src/materials/pathtracing/glsl/index.js +6 -0
- package/src/materials/pathtracing/glsl/{renderStructs.glsl.js → render_structs.glsl.js} +1 -1
- package/src/materials/pathtracing/glsl/{traceScene.glsl.js → trace_scene_function.glsl.js} +1 -3
- package/src/materials/surface/AmbientOcclusionMaterial.js +8 -8
- package/src/objects/PhysicalSpotLight.js +2 -2
- package/src/shader/bsdf/{bsdfSampling.glsl.js → bsdf_functions.glsl.js} +19 -72
- package/src/shader/bsdf/{fog.glsl.js → fog_functions.glsl.js} +1 -1
- package/src/shader/bsdf/{ggx.glsl.js → ggx_functions.glsl.js} +1 -1
- package/src/shader/bsdf/index.js +5 -0
- package/src/shader/bsdf/{iridescence.glsl.js → iridescence_functions.glsl.js} +1 -1
- package/src/shader/bsdf/{sheen.glsl.js → sheen_functions.glsl.js} +1 -1
- package/src/shader/bvh/index.js +2 -0
- package/src/shader/{structs/fogMaterialBvh.glsl.js → bvh/inside_fog_volume_function.glsl.js} +1 -1
- package/src/shader/{common/bvhAnyHit.glsl.js → bvh/ray_any_hit_function.glsl.js} +1 -1
- package/src/shader/common/{fresnel.glsl.js → fresnel_functions.glsl.js} +1 -1
- package/src/shader/common/index.js +5 -0
- package/src/shader/common/{math.glsl.js → math_functions.glsl.js} +1 -1
- package/src/shader/common/{intersectShapes.glsl.js → shape_intersection_functions.glsl.js} +1 -1
- package/src/shader/common/{arraySamplerTexelFetch.glsl.js → texture_sample_functions.glsl.js} +1 -1
- package/src/shader/common/{utils.glsl.js → util_functions.glsl.js} +1 -1
- package/src/shader/rand/index.js +3 -0
- package/src/shader/rand/pcg.glsl.js +1 -1
- package/src/shader/rand/sobol.glsl.js +4 -4
- package/src/shader/rand/{stratifiedTexture.glsl.js → stratified.glsl.js} +7 -2
- package/src/shader/sampling/{equirectSampling.glsl.js → equirect_sampling_functions.glsl.js} +1 -2
- package/src/shader/sampling/index.js +3 -0
- package/src/shader/sampling/{lightSampling.glsl.js → light_sampling_functions.glsl.js} +3 -3
- package/src/shader/sampling/{shapeSampling.glsl.js → shape_sampling_functions.glsl.js} +1 -1
- package/src/shader/structs/{cameraStruct.glsl.js → camera_struct.glsl.js} +1 -1
- package/src/shader/structs/{equirectStruct.glsl.js → equirect_struct.glsl.js} +1 -1
- package/src/shader/structs/index.js +5 -0
- package/src/shader/structs/{lightsStruct.glsl.js → lights_struct.glsl.js} +1 -1
- package/src/shader/structs/{materialStruct.glsl.js → material_struct.glsl.js} +2 -2
- package/src/shader/structs/surface_record_struct.glsl.js +63 -0
- package/src/uniforms/EquirectHdrInfoUniform.js +16 -11
- package/src/uniforms/LightsInfoUniformStruct.js +21 -10
- package/src/uniforms/MaterialsTexture.js +27 -86
- package/src/uniforms/RenderTarget2DArray.js +60 -20
- package/src/utils/BlurredEnvMapGenerator.js +12 -5
- package/src/utils/SobolNumberMapGenerator.js +3 -3
- package/src/utils/bufferToHash.js +22 -0
- package/src/core/DynamicPathTracingSceneGenerator.js +0 -164
- package/src/core/MaterialReducer.js +0 -256
- package/src/materials/pathtracing/LambertPathTracingMaterial.js +0 -297
- package/src/uniforms/IESProfilesTexture.js +0 -100
- package/src/uniforms/utils.js +0 -30
- package/src/utils/IESLoader.js +0 -327
- package/src/workers/PathTracingSceneWorker.js +0 -52
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "three-gpu-pathtracer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "Path tracing renderer and utilities for three.js built on top of three-mesh-bvh.",
|
|
5
5
|
"module": "src/index.js",
|
|
6
6
|
"main": "build/index.umd.cjs",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"types": "src/index.d.ts",
|
|
8
9
|
"sideEffects": false,
|
|
9
10
|
"files": [
|
|
10
11
|
"src/*",
|
|
@@ -30,24 +31,29 @@
|
|
|
30
31
|
],
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@lookingglass/webxr": "^0.3.1",
|
|
34
|
+
"@monogrid/gainmap-js": "^3.0.5",
|
|
35
|
+
"@types/node": "^20.12.7",
|
|
36
|
+
"@types/three": "^0.163.0",
|
|
37
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
33
38
|
"canvas-capture": "^2.0.5",
|
|
34
39
|
"eslint": "^7.32.0",
|
|
35
40
|
"eslint-config-mdcs": "^5.0.0",
|
|
36
41
|
"node-fetch": "^3.2.9",
|
|
37
|
-
"parcel": "^2.
|
|
42
|
+
"parcel": "^2.12.0",
|
|
38
43
|
"pixelmatch": "^5.3.0",
|
|
39
44
|
"pngjs": "^6.0.0",
|
|
40
45
|
"process": "^0.11.10",
|
|
41
46
|
"puppeteer": "^15.4.0",
|
|
42
47
|
"rollup": "^2.70.0",
|
|
43
48
|
"simple-git": "^3.10.0",
|
|
44
|
-
"three": "^0.
|
|
45
|
-
"three-mesh-bvh": "^0.7.
|
|
49
|
+
"three": "^0.163.0",
|
|
50
|
+
"three-mesh-bvh": "^0.7.4",
|
|
51
|
+
"typescript": "5.3.3",
|
|
46
52
|
"yargs": "^17.5.1"
|
|
47
53
|
},
|
|
48
54
|
"peerDependencies": {
|
|
49
55
|
"three": ">=0.151.0",
|
|
50
|
-
"three-mesh-bvh": ">=0.7.
|
|
56
|
+
"three-mesh-bvh": ">=0.7.4",
|
|
51
57
|
"xatlas-web": "^0.1.0"
|
|
52
58
|
},
|
|
53
59
|
"scripts": {
|
|
@@ -56,7 +62,7 @@
|
|
|
56
62
|
"update-screenshots": "node ./scripts/push-screenshots.js",
|
|
57
63
|
"screenshot-diff": "node ./scripts/regression-test.js",
|
|
58
64
|
"build": "rollup -c",
|
|
59
|
-
"lint": "eslint \"./src/**/*.{js,ts}\" \"./example/*.js\"",
|
|
65
|
+
"lint": "eslint \"./src/**/*.{js,ts}\" \"./example/*.js\" && tsc --noEmit",
|
|
60
66
|
"prepublishOnly": "npm run build"
|
|
61
67
|
},
|
|
62
68
|
"repository": {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { RGBAFormat, FloatType,
|
|
1
|
+
import { RGBAFormat, FloatType, Color, Vector2, WebGLRenderTarget, NoBlending, NormalBlending, Vector4, NearestFilter } from 'three';
|
|
2
2
|
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
|
|
3
3
|
import { BlendMaterial } from '../materials/fullscreen/BlendMaterial.js';
|
|
4
4
|
import { SobolNumberMapGenerator } from '../utils/SobolNumberMapGenerator.js';
|
|
5
|
+
import { PhysicalPathTracingMaterial } from '../materials/pathtracing/PhysicalPathTracingMaterial.js';
|
|
5
6
|
|
|
6
7
|
function* renderTask() {
|
|
7
8
|
|
|
@@ -14,7 +15,6 @@ function* renderTask() {
|
|
|
14
15
|
_sobolTarget,
|
|
15
16
|
_subframe,
|
|
16
17
|
alpha,
|
|
17
|
-
camera,
|
|
18
18
|
material,
|
|
19
19
|
} = this;
|
|
20
20
|
const _ogScissor = new Vector4();
|
|
@@ -27,13 +27,13 @@ function* renderTask() {
|
|
|
27
27
|
|
|
28
28
|
if ( alpha ) {
|
|
29
29
|
|
|
30
|
-
blendMaterial.opacity = this._opacityFactor / ( this.
|
|
30
|
+
blendMaterial.opacity = this._opacityFactor / ( this.samples + 1 );
|
|
31
31
|
material.blending = NoBlending;
|
|
32
32
|
material.opacity = 1;
|
|
33
33
|
|
|
34
34
|
} else {
|
|
35
35
|
|
|
36
|
-
material.opacity = this._opacityFactor / ( this.
|
|
36
|
+
material.opacity = this._opacityFactor / ( this.samples + 1 );
|
|
37
37
|
material.blending = NormalBlending;
|
|
38
38
|
|
|
39
39
|
}
|
|
@@ -64,30 +64,6 @@ function* renderTask() {
|
|
|
64
64
|
|
|
65
65
|
for ( let x = 0; x < tilesX; x ++ ) {
|
|
66
66
|
|
|
67
|
-
material.cameraWorldMatrix.copy( camera.matrixWorld );
|
|
68
|
-
material.invProjectionMatrix.copy( camera.projectionMatrixInverse );
|
|
69
|
-
|
|
70
|
-
// Perspective camera (default)
|
|
71
|
-
let cameraType = 0;
|
|
72
|
-
|
|
73
|
-
// An orthographic projection matrix will always have the bottom right element == 1
|
|
74
|
-
// And a perspective projection matrix will always have the bottom right element == 0
|
|
75
|
-
if ( camera.projectionMatrix.elements[ 15 ] > 0 ) {
|
|
76
|
-
|
|
77
|
-
// Orthographic
|
|
78
|
-
cameraType = 1;
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if ( camera.isEquirectCamera ) {
|
|
83
|
-
|
|
84
|
-
// Equirectangular
|
|
85
|
-
cameraType = 2;
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
material.setDefine( 'CAMERA_TYPE', cameraType );
|
|
90
|
-
|
|
91
67
|
// store og state
|
|
92
68
|
const ogRenderTarget = _renderer.getRenderTarget();
|
|
93
69
|
const ogAutoClear = _renderer.autoClear;
|
|
@@ -151,12 +127,12 @@ function* renderTask() {
|
|
|
151
127
|
|
|
152
128
|
}
|
|
153
129
|
|
|
154
|
-
this.
|
|
130
|
+
this.samples += ( 1 / totalTiles );
|
|
155
131
|
|
|
156
132
|
// round the samples value if we've finished the tiles
|
|
157
133
|
if ( x === tilesX - 1 && y === tilesY - 1 ) {
|
|
158
134
|
|
|
159
|
-
this.
|
|
135
|
+
this.samples = Math.round( this.samples );
|
|
160
136
|
|
|
161
137
|
}
|
|
162
138
|
|
|
@@ -219,52 +195,82 @@ export class PathTracingRenderer {
|
|
|
219
195
|
|
|
220
196
|
}
|
|
221
197
|
|
|
222
|
-
get samples() {
|
|
223
|
-
|
|
224
|
-
return this._samples;
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
198
|
constructor( renderer ) {
|
|
229
199
|
|
|
230
200
|
this.camera = null;
|
|
231
|
-
this.tiles = new Vector2(
|
|
201
|
+
this.tiles = new Vector2( 3, 3 );
|
|
232
202
|
|
|
233
203
|
this.stableNoise = false;
|
|
234
204
|
this.stableTiles = true;
|
|
235
205
|
|
|
236
|
-
this.
|
|
206
|
+
this.samples = 0;
|
|
237
207
|
this._subframe = new Vector4( 0, 0, 1, 1 );
|
|
238
208
|
this._opacityFactor = 1.0;
|
|
239
209
|
this._renderer = renderer;
|
|
240
210
|
this._alpha = false;
|
|
241
|
-
this._fsQuad = new FullScreenQuad(
|
|
211
|
+
this._fsQuad = new FullScreenQuad( new PhysicalPathTracingMaterial() );
|
|
242
212
|
this._blendQuad = new FullScreenQuad( new BlendMaterial() );
|
|
243
213
|
this._task = null;
|
|
244
214
|
this._currentTile = 0;
|
|
245
215
|
|
|
246
216
|
this._sobolTarget = new SobolNumberMapGenerator().generate( renderer );
|
|
247
217
|
|
|
248
|
-
// will be null if extension not supported
|
|
249
|
-
const floatLinearExtensionSupported = renderer.extensions.get( 'OES_texture_float_linear' );
|
|
250
|
-
|
|
251
218
|
this._primaryTarget = new WebGLRenderTarget( 1, 1, {
|
|
252
219
|
format: RGBAFormat,
|
|
253
|
-
type:
|
|
220
|
+
type: FloatType,
|
|
221
|
+
magFilter: NearestFilter,
|
|
222
|
+
minFilter: NearestFilter,
|
|
254
223
|
} );
|
|
255
224
|
this._blendTargets = [
|
|
256
225
|
new WebGLRenderTarget( 1, 1, {
|
|
257
226
|
format: RGBAFormat,
|
|
258
|
-
type:
|
|
227
|
+
type: FloatType,
|
|
228
|
+
magFilter: NearestFilter,
|
|
229
|
+
minFilter: NearestFilter,
|
|
259
230
|
} ),
|
|
260
231
|
new WebGLRenderTarget( 1, 1, {
|
|
261
232
|
format: RGBAFormat,
|
|
262
|
-
type:
|
|
233
|
+
type: FloatType,
|
|
234
|
+
magFilter: NearestFilter,
|
|
235
|
+
minFilter: NearestFilter,
|
|
263
236
|
} ),
|
|
264
237
|
];
|
|
265
238
|
|
|
266
239
|
}
|
|
267
240
|
|
|
241
|
+
setCamera( camera ) {
|
|
242
|
+
|
|
243
|
+
const { material } = this;
|
|
244
|
+
material.cameraWorldMatrix.copy( camera.matrixWorld );
|
|
245
|
+
material.invProjectionMatrix.copy( camera.projectionMatrixInverse );
|
|
246
|
+
material.physicalCamera.updateFrom( camera );
|
|
247
|
+
|
|
248
|
+
// Perspective camera (default)
|
|
249
|
+
let cameraType = 0;
|
|
250
|
+
|
|
251
|
+
// An orthographic projection matrix will always have the bottom right element == 1
|
|
252
|
+
// And a perspective projection matrix will always have the bottom right element == 0
|
|
253
|
+
if ( camera.projectionMatrix.elements[ 15 ] > 0 ) {
|
|
254
|
+
|
|
255
|
+
// Orthographic
|
|
256
|
+
cameraType = 1;
|
|
257
|
+
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if ( camera.isEquirectCamera ) {
|
|
261
|
+
|
|
262
|
+
// Equirectangular
|
|
263
|
+
cameraType = 2;
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
material.setDefine( 'CAMERA_TYPE', cameraType );
|
|
268
|
+
|
|
269
|
+
this.camera = camera;
|
|
270
|
+
// this.reset();
|
|
271
|
+
|
|
272
|
+
}
|
|
273
|
+
|
|
268
274
|
setSize( w, h ) {
|
|
269
275
|
|
|
270
276
|
w = Math.ceil( w );
|
|
@@ -283,6 +289,13 @@ export class PathTracingRenderer {
|
|
|
283
289
|
|
|
284
290
|
}
|
|
285
291
|
|
|
292
|
+
getSize( target ) {
|
|
293
|
+
|
|
294
|
+
target.x = this._primaryTarget.width;
|
|
295
|
+
target.y = this._primaryTarget.height;
|
|
296
|
+
|
|
297
|
+
}
|
|
298
|
+
|
|
286
299
|
dispose() {
|
|
287
300
|
|
|
288
301
|
this._primaryTarget.dispose();
|
|
@@ -318,7 +331,7 @@ export class PathTracingRenderer {
|
|
|
318
331
|
_renderer.setClearColor( ogClearColor, ogClearAlpha );
|
|
319
332
|
_renderer.setRenderTarget( ogRenderTarget );
|
|
320
333
|
|
|
321
|
-
this.
|
|
334
|
+
this.samples = 0;
|
|
322
335
|
this._task = null;
|
|
323
336
|
|
|
324
337
|
if ( this.stableNoise ) {
|
|
@@ -1,24 +1,259 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BufferGeometry } from 'three';
|
|
2
|
+
import { MeshBVH, SAH } from 'three-mesh-bvh';
|
|
3
|
+
import { StaticGeometryGenerator, NO_CHANGE, GEOMETRY_ADJUSTED, GEOMETRY_REBUILT } from './utils/StaticGeometryGenerator.js';
|
|
4
|
+
import { updateMaterialIndexAttribute } from './utils/GeometryPreparationUtils.js';
|
|
5
|
+
|
|
6
|
+
// collect the textures from the materials
|
|
7
|
+
function getTextures( materials ) {
|
|
8
|
+
|
|
9
|
+
const textureSet = new Set();
|
|
10
|
+
for ( let i = 0, l = materials.length; i < l; i ++ ) {
|
|
11
|
+
|
|
12
|
+
const material = materials[ i ];
|
|
13
|
+
for ( const key in material ) {
|
|
14
|
+
|
|
15
|
+
const value = material[ key ];
|
|
16
|
+
if ( value && value.isTexture ) {
|
|
17
|
+
|
|
18
|
+
textureSet.add( value );
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return Array.from( textureSet );
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// collect the lights in the scene
|
|
31
|
+
function getLights( objects ) {
|
|
32
|
+
|
|
33
|
+
const lights = [];
|
|
34
|
+
const iesSet = new Set();
|
|
35
|
+
for ( let i = 0, l = objects.length; i < l; i ++ ) {
|
|
36
|
+
|
|
37
|
+
objects[ i ].traverse( c => {
|
|
38
|
+
|
|
39
|
+
if ( c.visible ) {
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
c.isRectAreaLight ||
|
|
43
|
+
c.isSpotLight ||
|
|
44
|
+
c.isPointLight ||
|
|
45
|
+
c.isDirectionalLight
|
|
46
|
+
) {
|
|
47
|
+
|
|
48
|
+
lights.push( c );
|
|
49
|
+
|
|
50
|
+
if ( c.iesMap ) {
|
|
51
|
+
|
|
52
|
+
iesSet.add( c.iesMap );
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
} );
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const iesTextures = Array.from( iesSet ).sort( ( a, b ) => {
|
|
65
|
+
|
|
66
|
+
if ( a.uuid < b.uuid ) return 1;
|
|
67
|
+
if ( a.uuid > b.uuid ) return - 1;
|
|
68
|
+
return 0;
|
|
69
|
+
|
|
70
|
+
} );
|
|
71
|
+
|
|
72
|
+
return { lights, iesTextures };
|
|
73
|
+
|
|
74
|
+
}
|
|
2
75
|
|
|
3
76
|
export class PathTracingSceneGenerator {
|
|
4
77
|
|
|
5
|
-
|
|
78
|
+
get initialized() {
|
|
79
|
+
|
|
80
|
+
return Boolean( this.bvh );
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
constructor( objects ) {
|
|
85
|
+
|
|
86
|
+
// options
|
|
87
|
+
this.bvhOptions = {};
|
|
88
|
+
this.attributes = [ 'position', 'normal', 'tangent', 'color', 'uv', 'uv2' ];
|
|
89
|
+
this.generateBVH = true;
|
|
90
|
+
|
|
91
|
+
// state
|
|
92
|
+
this.bvh = null;
|
|
93
|
+
this.geometry = new BufferGeometry();
|
|
94
|
+
this.staticGeometryGenerator = new StaticGeometryGenerator( objects );
|
|
95
|
+
this._bvhWorker = null;
|
|
96
|
+
this._pendingGenerate = null;
|
|
97
|
+
this._buildAsync = false;
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setObjects( objects ) {
|
|
102
|
+
|
|
103
|
+
this.staticGeometryGenerator.setObjects( objects );
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
setBVHWorker( bvhWorker ) {
|
|
108
|
+
|
|
109
|
+
this._bvhWorker = bvhWorker;
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async generateAsync( onProgress = null ) {
|
|
114
|
+
|
|
115
|
+
if ( ! this._bvhWorker ) {
|
|
116
|
+
|
|
117
|
+
throw new Error( 'PathTracingSceneGenerator: "setBVHWorker" must be called before "generateAsync" can be called.' );
|
|
118
|
+
|
|
119
|
+
}
|
|
6
120
|
|
|
7
|
-
|
|
8
|
-
// TODO: remove this?
|
|
9
|
-
if ( Array.isArray( scene ) ) {
|
|
121
|
+
if ( this.bvh instanceof Promise ) {
|
|
10
122
|
|
|
11
|
-
|
|
123
|
+
// if a bvh is already being generated we can wait for that to finish
|
|
124
|
+
// and build another with the latest data while sharing the results.
|
|
125
|
+
if ( ! this._pendingGenerate ) {
|
|
126
|
+
|
|
127
|
+
this._pendingGenerate = new Promise( async () => {
|
|
128
|
+
|
|
129
|
+
await this.bvh;
|
|
130
|
+
this._pendingGenerate = null;
|
|
131
|
+
|
|
132
|
+
// TODO: support multiple callbacks queued?
|
|
133
|
+
return this.generateAsync( onProgress );
|
|
134
|
+
|
|
135
|
+
} );
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return this._pendingGenerate;
|
|
12
140
|
|
|
13
141
|
} else {
|
|
14
142
|
|
|
15
|
-
|
|
143
|
+
this._buildAsync = true;
|
|
144
|
+
const result = this.generate( onProgress );
|
|
145
|
+
this._buildAsync = false;
|
|
146
|
+
|
|
147
|
+
result.bvh = this.bvh = await result.bvh;
|
|
148
|
+
return result;
|
|
16
149
|
|
|
17
150
|
}
|
|
18
151
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
generate( onProgress = null ) {
|
|
155
|
+
|
|
156
|
+
const { staticGeometryGenerator, geometry, attributes } = this;
|
|
157
|
+
const objects = staticGeometryGenerator.objects;
|
|
158
|
+
staticGeometryGenerator.attributes = attributes;
|
|
159
|
+
|
|
160
|
+
// update the skeleton animations in case WebGLRenderer is not running
|
|
161
|
+
// to update it.
|
|
162
|
+
objects.forEach( o => {
|
|
163
|
+
|
|
164
|
+
o.traverse( c => {
|
|
165
|
+
|
|
166
|
+
if ( c.isSkinnedMesh && c.skeleton ) {
|
|
167
|
+
|
|
168
|
+
c.skeleton.update();
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
} );
|
|
173
|
+
|
|
174
|
+
} );
|
|
175
|
+
|
|
176
|
+
// generate the geometry
|
|
177
|
+
const result = staticGeometryGenerator.generate( geometry );
|
|
178
|
+
const materials = result.materials;
|
|
179
|
+
const textures = getTextures( materials );
|
|
180
|
+
const { lights, iesTextures } = getLights( objects );
|
|
181
|
+
|
|
182
|
+
if ( result.changeType !== NO_CHANGE ) {
|
|
183
|
+
|
|
184
|
+
updateMaterialIndexAttribute( geometry, materials, materials );
|
|
185
|
+
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// only generate a new bvh if the objects used have changed
|
|
189
|
+
if ( this.generateBVH ) {
|
|
190
|
+
|
|
191
|
+
if ( this.bvh instanceof Promise ) {
|
|
192
|
+
|
|
193
|
+
throw new Error( 'PathTracingSceneGenerator: BVH is already building asynchronously.' );
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if ( result.changeType === GEOMETRY_REBUILT ) {
|
|
198
|
+
|
|
199
|
+
const bvhOptions = {
|
|
200
|
+
strategy: SAH,
|
|
201
|
+
maxLeafTris: 1,
|
|
202
|
+
indirect: true,
|
|
203
|
+
onProgress,
|
|
204
|
+
...this.bvhOptions,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
if ( this._buildAsync ) {
|
|
208
|
+
|
|
209
|
+
this.bvh = this._bvhWorker.generate( geometry, bvhOptions );
|
|
210
|
+
|
|
211
|
+
} else {
|
|
212
|
+
|
|
213
|
+
this.bvh = new MeshBVH( geometry, bvhOptions );
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
} else if ( result.changeType === GEOMETRY_ADJUSTED ) {
|
|
218
|
+
|
|
219
|
+
this.bvh.refit();
|
|
220
|
+
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
bvhChanged: result.changeType !== NO_CHANGE,
|
|
227
|
+
bvh: this.bvh,
|
|
228
|
+
lights,
|
|
229
|
+
iesTextures,
|
|
230
|
+
geometry,
|
|
231
|
+
materials,
|
|
232
|
+
textures,
|
|
233
|
+
objects,
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export class DynamicPathTracingSceneGenerator extends PathTracingSceneGenerator {
|
|
241
|
+
|
|
242
|
+
constructor( ...args ) {
|
|
243
|
+
|
|
244
|
+
super( ...args );
|
|
245
|
+
console.warn( 'DynamicPathTracingSceneGenerator has been deprecated and renamed to "PathTracingSceneGenerator".' );
|
|
246
|
+
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export class PathTracingSceneWorker extends PathTracingSceneGenerator {
|
|
252
|
+
|
|
253
|
+
constructor( ...args ) {
|
|
254
|
+
|
|
255
|
+
super( ...args );
|
|
256
|
+
console.warn( 'PathTracingSceneWorker has been deprecated and renamed to "PathTracingSceneGenerator".' );
|
|
22
257
|
|
|
23
258
|
}
|
|
24
259
|
|