three-gpu-pathtracer 0.0.22 → 0.0.24
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 +6 -4
- package/build/index.module.js +465 -57
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +464 -56
- package/build/index.umd.cjs.map +1 -1
- package/package.json +13 -13
- package/src/core/PathTracingRenderer.js +48 -1
- package/src/core/PathTracingSceneGenerator.js +21 -2
- package/src/core/WebGLPathTracer.js +68 -13
- package/src/core/utils/BakedGeometry.js +23 -0
- package/src/core/utils/BufferAttributeUtils.js +11 -3
- package/src/core/utils/MeshDiff.js +6 -13
- package/src/core/utils/StaticGeometryGenerator.js +18 -3
- package/src/core/utils/mergeGeometries.js +14 -1
- package/src/index.d.ts +2 -1
- package/src/materials/MaterialBase.js +11 -0
- package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +2 -1
- package/src/materials/pathtracing/glsl/attenuate_hit_function.glsl.js +2 -1
- package/src/materials/pathtracing/glsl/camera_util_functions.glsl.js +1 -1
- package/src/materials/pathtracing/glsl/get_surface_record_function.glsl.js +2 -1
- package/src/materials/surface/AmbientOcclusionMaterial.js +2 -0
- package/src/shader/bvh/inside_fog_volume_function.glsl.js +1 -1
- package/src/shader/structs/material_struct.glsl.js +3 -1
- package/src/uniforms/MaterialsTexture.js +4 -1
- package/src/uniforms/StratifiedSamplesTexture.js +55 -3
- package/src/uniforms/stratified/StratifiedSampler.js +19 -7
- package/src/uniforms/stratified/StratifiedSamplerCombined.js +14 -4
- package/src/utils/CubeToEquirectGenerator.js +159 -0
package/build/index.module.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BufferAttribute, BufferGeometry, Matrix4, Vector3, Vector4, Matrix3, MeshBasicMaterial, Mesh, ShaderMaterial, NoBlending, Vector2, WebGLRenderTarget, FloatType, RGBAFormat, NearestFilter, PerspectiveCamera, DataUtils, HalfFloatType, Source, DataTexture, LinearFilter, RepeatWrapping, RedFormat, ClampToEdgeWrapping, Quaternion, DataArrayTexture, DoubleSide, BackSide, FrontSide, Color, WebGLArrayRenderTarget, UnsignedByteType, NoToneMapping, RGFormat, NormalBlending, Spherical, EquirectangularReflectionMapping, Clock, Scene, AdditiveBlending, Camera, SpotLight, RectAreaLight, PMREMGenerator, MeshStandardMaterial } from 'three';
|
|
1
|
+
import { BufferAttribute, BufferGeometry, Matrix4, Vector3, Vector4, Matrix3, MeshBasicMaterial, Mesh, ShaderMaterial, NoBlending, Vector2, WebGLRenderTarget, FloatType, RGBAFormat, NearestFilter, PerspectiveCamera, DataUtils, HalfFloatType, Source, DataTexture, LinearFilter, RepeatWrapping, RedFormat, ClampToEdgeWrapping, Quaternion, DataArrayTexture, DoubleSide, BackSide, FrontSide, Color, WebGLArrayRenderTarget, UnsignedByteType, NoToneMapping, RGFormat, NormalBlending, Spherical, EquirectangularReflectionMapping, LinearMipMapLinearFilter, Clock, Scene, AdditiveBlending, Camera, SpotLight, RectAreaLight, PMREMGenerator, MeshStandardMaterial } from 'three';
|
|
2
2
|
import { SAH, MeshBVH, FloatVertexAttributeTexture, MeshBVHUniformStruct, UIntVertexAttributeTexture, BVHShaderGLSL } from 'three-mesh-bvh';
|
|
3
3
|
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
|
|
4
4
|
|
|
@@ -43,12 +43,18 @@ function createAttributeClone( attr, countOverride = null ) {
|
|
|
43
43
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// Confirms that the two provided attributes are compatible
|
|
46
|
+
// Confirms that the two provided attributes are compatible. Returns false if they are not.
|
|
47
47
|
function validateAttributes( attr1, attr2 ) {
|
|
48
48
|
|
|
49
49
|
if ( ! attr1 && ! attr2 ) {
|
|
50
50
|
|
|
51
|
-
return;
|
|
51
|
+
return true;
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if ( Boolean( attr1 ) !== Boolean( attr2 ) ) {
|
|
56
|
+
|
|
57
|
+
return false;
|
|
52
58
|
|
|
53
59
|
}
|
|
54
60
|
|
|
@@ -59,10 +65,12 @@ function validateAttributes( attr1, attr2 ) {
|
|
|
59
65
|
|
|
60
66
|
if ( ! sameCount || ! sameNormalized || ! sameType || ! sameItemSize ) {
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
return false;
|
|
63
69
|
|
|
64
70
|
}
|
|
65
71
|
|
|
72
|
+
return true;
|
|
73
|
+
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
function validateMergeability( geometries ) {
|
|
@@ -269,7 +277,20 @@ function mergeGeometries( geometries, options = {}, targetGeometry = new BufferG
|
|
|
269
277
|
const attr = geometry.getAttribute( key );
|
|
270
278
|
if ( ! skip ) {
|
|
271
279
|
|
|
272
|
-
|
|
280
|
+
if ( key === 'color' && targetAttribute.itemSize !== attr.itemSize ) {
|
|
281
|
+
|
|
282
|
+
// make sure the color attribute is aligned with itemSize 3 to 4
|
|
283
|
+
for ( let index = offset, l = attr.count; index < l; index ++ ) {
|
|
284
|
+
|
|
285
|
+
attr.setXYZW( index, targetAttribute.getX( index ), targetAttribute.getY( index ), targetAttribute.getZ( index ), 1.0 );
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
} else {
|
|
290
|
+
|
|
291
|
+
copyAttributeContents( attr, targetAttribute, offset );
|
|
292
|
+
|
|
293
|
+
}
|
|
273
294
|
|
|
274
295
|
}
|
|
275
296
|
|
|
@@ -430,29 +451,22 @@ function bufferToHash( buffer ) {
|
|
|
430
451
|
|
|
431
452
|
}
|
|
432
453
|
|
|
433
|
-
function attributeSort( a, b ) {
|
|
434
|
-
|
|
435
|
-
if ( a.uuid > b.uuid ) return 1;
|
|
436
|
-
if ( a.uuid < b.uuid ) return - 1;
|
|
437
|
-
return 0;
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
|
|
441
454
|
function getGeometryHash( geometry ) {
|
|
442
455
|
|
|
443
|
-
let hash =
|
|
456
|
+
let hash = geometry.uuid;
|
|
444
457
|
const attributes = Object.values( geometry.attributes );
|
|
445
458
|
if ( geometry.index ) {
|
|
446
459
|
|
|
447
460
|
attributes.push( geometry.index );
|
|
461
|
+
hash += `index|${ geometry.index.version }`;
|
|
448
462
|
|
|
449
463
|
}
|
|
450
464
|
|
|
451
|
-
|
|
465
|
+
const keys = Object.keys( attributes ).sort();
|
|
466
|
+
for ( const key of keys ) {
|
|
452
467
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
hash += `${ attr.uuid }_${ attr.version }|`;
|
|
468
|
+
const attr = attributes[ key ];
|
|
469
|
+
hash += `${ key }_${ attr.version }|`;
|
|
456
470
|
|
|
457
471
|
}
|
|
458
472
|
|
|
@@ -883,6 +897,28 @@ class BakedGeometry extends BufferGeometry {
|
|
|
883
897
|
|
|
884
898
|
}
|
|
885
899
|
|
|
900
|
+
// returns whether the passed mesh is compatible with this baked geometry
|
|
901
|
+
// such that it can be updated without resizing attributes
|
|
902
|
+
isCompatible( mesh, attributes ) {
|
|
903
|
+
|
|
904
|
+
const geometry = mesh.geometry;
|
|
905
|
+
for ( let i = 0; i < attributes.length; i ++ ) {
|
|
906
|
+
|
|
907
|
+
const key = attributes[ i ];
|
|
908
|
+
const attr1 = geometry.attributes[ key ];
|
|
909
|
+
const attr2 = this.attributes[ key ];
|
|
910
|
+
if ( attr1 && ! validateAttributes( attr1, attr2 ) ) {
|
|
911
|
+
|
|
912
|
+
return false;
|
|
913
|
+
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
return true;
|
|
919
|
+
|
|
920
|
+
}
|
|
921
|
+
|
|
886
922
|
updateFrom( mesh, options ) {
|
|
887
923
|
|
|
888
924
|
const diff = this._diff;
|
|
@@ -1072,15 +1108,24 @@ class StaticGeometryGenerator {
|
|
|
1072
1108
|
unusedMeshKeys.delete( meshKey );
|
|
1073
1109
|
|
|
1074
1110
|
// initialize the intermediate geometry
|
|
1075
|
-
if
|
|
1111
|
+
// if the mesh and source geometry have changed in such a way that they are no longer
|
|
1112
|
+
// compatible then regenerate the baked geometry from scratch
|
|
1113
|
+
let geom = _intermediateGeometry.get( meshKey );
|
|
1114
|
+
if ( ! geom || ! geom.isCompatible( mesh, this.attributes ) ) {
|
|
1115
|
+
|
|
1116
|
+
if ( geom ) {
|
|
1076
1117
|
|
|
1077
|
-
|
|
1118
|
+
geom.dispose();
|
|
1119
|
+
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
geom = new BakedGeometry();
|
|
1123
|
+
_intermediateGeometry.set( meshKey, geom );
|
|
1078
1124
|
|
|
1079
1125
|
}
|
|
1080
1126
|
|
|
1081
1127
|
// transform the geometry into the intermediate buffer geometry, saving whether
|
|
1082
1128
|
// or not it changed.
|
|
1083
|
-
const geom = _intermediateGeometry.get( meshKey );
|
|
1084
1129
|
if ( geom.updateFrom( mesh, convertOptions ) ) {
|
|
1085
1130
|
|
|
1086
1131
|
// TODO: provide option for only generating the set of attributes that are present
|
|
@@ -1132,6 +1177,12 @@ class StaticGeometryGenerator {
|
|
|
1132
1177
|
|
|
1133
1178
|
// get the list of geometries to merge
|
|
1134
1179
|
let forceUpdate = false;
|
|
1180
|
+
if ( meshes.length !== previousMergeInfo.length ) {
|
|
1181
|
+
|
|
1182
|
+
forceUpdate = true;
|
|
1183
|
+
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1135
1186
|
for ( let i = 0, l = meshes.length; i < l; i ++ ) {
|
|
1136
1187
|
|
|
1137
1188
|
const mesh = meshes[ i ];
|
|
@@ -1277,6 +1328,7 @@ class PathTracingSceneGenerator {
|
|
|
1277
1328
|
this._bvhWorker = null;
|
|
1278
1329
|
this._pendingGenerate = null;
|
|
1279
1330
|
this._buildAsync = false;
|
|
1331
|
+
this._materialUuids = null;
|
|
1280
1332
|
|
|
1281
1333
|
}
|
|
1282
1334
|
|
|
@@ -1358,12 +1410,29 @@ class PathTracingSceneGenerator {
|
|
|
1358
1410
|
// generate the geometry
|
|
1359
1411
|
const result = staticGeometryGenerator.generate( geometry );
|
|
1360
1412
|
const materials = result.materials;
|
|
1413
|
+
let needsMaterialIndexUpdate = result.changeType !== NO_CHANGE || this._materialUuids === null || this._materialUuids.length !== length;
|
|
1414
|
+
if ( ! needsMaterialIndexUpdate ) {
|
|
1415
|
+
|
|
1416
|
+
for ( let i = 0, length = materials.length; i < length; i ++ ) {
|
|
1417
|
+
|
|
1418
|
+
const material = materials[ i ];
|
|
1419
|
+
if ( material.uuid !== this._materialUuids[ i ] ) {
|
|
1420
|
+
|
|
1421
|
+
needsMaterialIndexUpdate = true;
|
|
1422
|
+
break;
|
|
1423
|
+
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1361
1430
|
const textures = getTextures$1( materials );
|
|
1362
1431
|
const { lights, iesTextures } = getLights$1( objects );
|
|
1363
|
-
|
|
1364
|
-
if ( result.changeType !== NO_CHANGE ) {
|
|
1432
|
+
if ( needsMaterialIndexUpdate ) {
|
|
1365
1433
|
|
|
1366
1434
|
updateMaterialIndexAttribute( geometry, materials, materials );
|
|
1435
|
+
this._materialUuids = materials.map( material => material.uuid );
|
|
1367
1436
|
|
|
1368
1437
|
}
|
|
1369
1438
|
|
|
@@ -1407,6 +1476,7 @@ class PathTracingSceneGenerator {
|
|
|
1407
1476
|
return {
|
|
1408
1477
|
bvhChanged: result.changeType !== NO_CHANGE,
|
|
1409
1478
|
bvh: this.bvh,
|
|
1479
|
+
needsMaterialIndexUpdate,
|
|
1410
1480
|
lights,
|
|
1411
1481
|
iesTextures,
|
|
1412
1482
|
geometry,
|
|
@@ -1443,6 +1513,17 @@ class PathTracingSceneWorker extends PathTracingSceneGenerator {
|
|
|
1443
1513
|
|
|
1444
1514
|
class MaterialBase extends ShaderMaterial {
|
|
1445
1515
|
|
|
1516
|
+
set needsUpdate( v ) {
|
|
1517
|
+
|
|
1518
|
+
super.needsUpdate = true;
|
|
1519
|
+
this.dispatchEvent( {
|
|
1520
|
+
|
|
1521
|
+
type: 'recompilation',
|
|
1522
|
+
|
|
1523
|
+
} );
|
|
1524
|
+
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1446
1527
|
constructor( shader ) {
|
|
1447
1528
|
|
|
1448
1529
|
super( shader );
|
|
@@ -2823,7 +2904,7 @@ function getLights( scene ) {
|
|
|
2823
2904
|
|
|
2824
2905
|
}
|
|
2825
2906
|
|
|
2826
|
-
const MATERIAL_PIXELS =
|
|
2907
|
+
const MATERIAL_PIXELS = 47;
|
|
2827
2908
|
const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
|
|
2828
2909
|
|
|
2829
2910
|
class MaterialFeatures {
|
|
@@ -3248,6 +3329,9 @@ class MaterialsTexture extends DataTexture {
|
|
|
3248
3329
|
// specularIntensityMap transform 43
|
|
3249
3330
|
index += writeTextureMatrixToArray( m, 'specularIntensityMap', floatArray, index );
|
|
3250
3331
|
|
|
3332
|
+
// alphaMap transform 45
|
|
3333
|
+
index += writeTextureMatrixToArray( m, 'alphaMap', floatArray, index );
|
|
3334
|
+
|
|
3251
3335
|
}
|
|
3252
3336
|
|
|
3253
3337
|
// check if the contents have changed
|
|
@@ -3443,11 +3527,11 @@ class CopyMaterial extends ShaderMaterial {
|
|
|
3443
3527
|
// - https://github.com/hoverinc/ray-tracing-renderer
|
|
3444
3528
|
// - http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Stratified_Sampling.html
|
|
3445
3529
|
|
|
3446
|
-
function shuffle( arr ) {
|
|
3530
|
+
function shuffle( arr, random = Math.random() ) {
|
|
3447
3531
|
|
|
3448
3532
|
for ( let i = arr.length - 1; i > 0; i -- ) {
|
|
3449
3533
|
|
|
3450
|
-
const j = Math.floor(
|
|
3534
|
+
const j = Math.floor( random() * ( i + 1 ) );
|
|
3451
3535
|
const x = arr[ i ];
|
|
3452
3536
|
arr[ i ] = arr[ j ];
|
|
3453
3537
|
arr[ j ] = x;
|
|
@@ -3462,7 +3546,7 @@ function shuffle( arr ) {
|
|
|
3462
3546
|
// dimensions : The number of dimensions to generate stratified values for
|
|
3463
3547
|
class StratifiedSampler {
|
|
3464
3548
|
|
|
3465
|
-
constructor( strataCount, dimensions ) {
|
|
3549
|
+
constructor( strataCount, dimensions, random = Math.random ) {
|
|
3466
3550
|
|
|
3467
3551
|
const l = strataCount ** dimensions;
|
|
3468
3552
|
const strata = new Uint16Array( l );
|
|
@@ -3479,7 +3563,19 @@ class StratifiedSampler {
|
|
|
3479
3563
|
|
|
3480
3564
|
this.strataCount = strataCount;
|
|
3481
3565
|
|
|
3482
|
-
this.
|
|
3566
|
+
this.reset = function () {
|
|
3567
|
+
|
|
3568
|
+
for ( let i = 0; i < l; i ++ ) {
|
|
3569
|
+
|
|
3570
|
+
strata[ i ] = i;
|
|
3571
|
+
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3574
|
+
index = 0;
|
|
3575
|
+
|
|
3576
|
+
};
|
|
3577
|
+
|
|
3578
|
+
this.reshuffle = function () {
|
|
3483
3579
|
|
|
3484
3580
|
index = 0;
|
|
3485
3581
|
|
|
@@ -3491,8 +3587,8 @@ class StratifiedSampler {
|
|
|
3491
3587
|
|
|
3492
3588
|
if ( index >= strata.length ) {
|
|
3493
3589
|
|
|
3494
|
-
shuffle( strata );
|
|
3495
|
-
this.
|
|
3590
|
+
shuffle( strata, random );
|
|
3591
|
+
this.reshuffle();
|
|
3496
3592
|
|
|
3497
3593
|
}
|
|
3498
3594
|
|
|
@@ -3500,7 +3596,7 @@ class StratifiedSampler {
|
|
|
3500
3596
|
|
|
3501
3597
|
for ( let i = 0; i < dimensions; i ++ ) {
|
|
3502
3598
|
|
|
3503
|
-
samples[ i ] = ( stratum % strataCount +
|
|
3599
|
+
samples[ i ] = ( stratum % strataCount + random() ) / strataCount;
|
|
3504
3600
|
stratum = Math.floor( stratum / strataCount );
|
|
3505
3601
|
|
|
3506
3602
|
}
|
|
@@ -3518,7 +3614,7 @@ class StratifiedSampler {
|
|
|
3518
3614
|
// Stratified set of data with each tuple stratified separately and combined
|
|
3519
3615
|
class StratifiedSamplerCombined {
|
|
3520
3616
|
|
|
3521
|
-
constructor( strataCount, listOfDimensions ) {
|
|
3617
|
+
constructor( strataCount, listOfDimensions, random = Math.random ) {
|
|
3522
3618
|
|
|
3523
3619
|
let totalDim = 0;
|
|
3524
3620
|
for ( const dim of listOfDimensions ) {
|
|
@@ -3532,7 +3628,7 @@ class StratifiedSamplerCombined {
|
|
|
3532
3628
|
let offset = 0;
|
|
3533
3629
|
for ( const dim of listOfDimensions ) {
|
|
3534
3630
|
|
|
3535
|
-
const sampler = new StratifiedSampler( strataCount, dim );
|
|
3631
|
+
const sampler = new StratifiedSampler( strataCount, dim, random );
|
|
3536
3632
|
sampler.samples = new Float32Array( combined.buffer, offset, sampler.samples.length );
|
|
3537
3633
|
offset += sampler.samples.length * 4;
|
|
3538
3634
|
strataObjs.push( sampler );
|
|
@@ -3555,11 +3651,21 @@ class StratifiedSamplerCombined {
|
|
|
3555
3651
|
|
|
3556
3652
|
};
|
|
3557
3653
|
|
|
3558
|
-
this.
|
|
3654
|
+
this.reshuffle = function () {
|
|
3559
3655
|
|
|
3560
3656
|
for ( const strata of strataObjs ) {
|
|
3561
3657
|
|
|
3562
|
-
strata.
|
|
3658
|
+
strata.reshuffle();
|
|
3659
|
+
|
|
3660
|
+
}
|
|
3661
|
+
|
|
3662
|
+
};
|
|
3663
|
+
|
|
3664
|
+
this.reset = function () {
|
|
3665
|
+
|
|
3666
|
+
for ( const strata of strataObjs ) {
|
|
3667
|
+
|
|
3668
|
+
strata.reset();
|
|
3563
3669
|
|
|
3564
3670
|
}
|
|
3565
3671
|
|
|
@@ -3569,6 +3675,36 @@ class StratifiedSamplerCombined {
|
|
|
3569
3675
|
|
|
3570
3676
|
}
|
|
3571
3677
|
|
|
3678
|
+
// https://stackoverflow.com/questions/424292/seedable-javascript-random-number-generator
|
|
3679
|
+
class RandomGenerator {
|
|
3680
|
+
|
|
3681
|
+
constructor( seed = 0 ) {
|
|
3682
|
+
|
|
3683
|
+
// LCG using GCC's constants
|
|
3684
|
+
this.m = 0x80000000; // 2**31;
|
|
3685
|
+
this.a = 1103515245;
|
|
3686
|
+
this.c = 12345;
|
|
3687
|
+
|
|
3688
|
+
this.seed = seed;
|
|
3689
|
+
|
|
3690
|
+
}
|
|
3691
|
+
|
|
3692
|
+
nextInt() {
|
|
3693
|
+
|
|
3694
|
+
this.seed = ( this.a * this.seed + this.c ) % this.m;
|
|
3695
|
+
return this.seed;
|
|
3696
|
+
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3699
|
+
nextFloat() {
|
|
3700
|
+
|
|
3701
|
+
// returns in range [0,1]
|
|
3702
|
+
return this.nextInt() / ( this.m - 1 );
|
|
3703
|
+
|
|
3704
|
+
}
|
|
3705
|
+
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3572
3708
|
class StratifiedSamplesTexture extends DataTexture {
|
|
3573
3709
|
|
|
3574
3710
|
constructor( count = 1, depth = 1, strata = 8 ) {
|
|
@@ -3579,22 +3715,37 @@ class StratifiedSamplesTexture extends DataTexture {
|
|
|
3579
3715
|
|
|
3580
3716
|
this.strata = strata;
|
|
3581
3717
|
this.sampler = null;
|
|
3718
|
+
this.generator = new RandomGenerator();
|
|
3719
|
+
this.stableNoise = false;
|
|
3720
|
+
this.random = () => {
|
|
3721
|
+
|
|
3722
|
+
if ( this.stableNoise ) {
|
|
3723
|
+
|
|
3724
|
+
return this.generator.nextFloat();
|
|
3725
|
+
|
|
3726
|
+
} else {
|
|
3727
|
+
|
|
3728
|
+
return Math.random();
|
|
3729
|
+
|
|
3730
|
+
}
|
|
3731
|
+
|
|
3732
|
+
};
|
|
3582
3733
|
|
|
3583
3734
|
this.init( count, depth, strata );
|
|
3584
3735
|
|
|
3585
3736
|
}
|
|
3586
3737
|
|
|
3587
|
-
init( count, depth, strata = this.strata ) {
|
|
3738
|
+
init( count = this.image.height, depth = this.image.width, strata = this.strata ) {
|
|
3588
3739
|
|
|
3589
3740
|
const { image } = this;
|
|
3590
|
-
if ( image.width === depth && image.height === count ) {
|
|
3741
|
+
if ( image.width === depth && image.height === count && this.sampler !== null ) {
|
|
3591
3742
|
|
|
3592
3743
|
return;
|
|
3593
3744
|
|
|
3594
3745
|
}
|
|
3595
3746
|
|
|
3596
3747
|
const dimensions = new Array( count * depth ).fill( 4 );
|
|
3597
|
-
const sampler = new StratifiedSamplerCombined( strata, dimensions );
|
|
3748
|
+
const sampler = new StratifiedSamplerCombined( strata, dimensions, this.random );
|
|
3598
3749
|
|
|
3599
3750
|
image.width = depth;
|
|
3600
3751
|
image.height = count;
|
|
@@ -3614,6 +3765,13 @@ class StratifiedSamplesTexture extends DataTexture {
|
|
|
3614
3765
|
|
|
3615
3766
|
}
|
|
3616
3767
|
|
|
3768
|
+
reset() {
|
|
3769
|
+
|
|
3770
|
+
this.sampler.reset();
|
|
3771
|
+
this.generator.seed = 0;
|
|
3772
|
+
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3617
3775
|
}
|
|
3618
3776
|
|
|
3619
3777
|
function shuffleArray( array, random = Math.random ) {
|
|
@@ -4253,6 +4411,7 @@ const material_struct = /* glsl */ `
|
|
|
4253
4411
|
mat3 iridescenceThicknessMapTransform;
|
|
4254
4412
|
mat3 specularColorMapTransform;
|
|
4255
4413
|
mat3 specularIntensityMapTransform;
|
|
4414
|
+
mat3 alphaMapTransform;
|
|
4256
4415
|
|
|
4257
4416
|
};
|
|
4258
4417
|
|
|
@@ -4273,7 +4432,7 @@ const material_struct = /* glsl */ `
|
|
|
4273
4432
|
|
|
4274
4433
|
Material readMaterialInfo( sampler2D tex, uint index ) {
|
|
4275
4434
|
|
|
4276
|
-
uint i = index *
|
|
4435
|
+
uint i = index * uint( MATERIAL_PIXELS );
|
|
4277
4436
|
|
|
4278
4437
|
vec4 s0 = texelFetch1D( tex, i + 0u );
|
|
4279
4438
|
vec4 s1 = texelFetch1D( tex, i + 1u );
|
|
@@ -4372,6 +4531,7 @@ const material_struct = /* glsl */ `
|
|
|
4372
4531
|
m.iridescenceThicknessMapTransform = m.iridescenceThicknessMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 24u );
|
|
4373
4532
|
m.specularColorMapTransform = m.specularColorMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 26u );
|
|
4374
4533
|
m.specularIntensityMapTransform = m.specularIntensityMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 28u );
|
|
4534
|
+
m.alphaMapTransform = m.alphaMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 30u );
|
|
4375
4535
|
|
|
4376
4536
|
return m;
|
|
4377
4537
|
|
|
@@ -6138,7 +6298,7 @@ const inside_fog_volume_function = /* glsl */`
|
|
|
6138
6298
|
// returns whether the given material is a fog material or not
|
|
6139
6299
|
bool isMaterialFogVolume( sampler2D materials, uint materialIndex ) {
|
|
6140
6300
|
|
|
6141
|
-
uint i = materialIndex *
|
|
6301
|
+
uint i = materialIndex * uint( MATERIAL_PIXELS );
|
|
6142
6302
|
vec4 s14 = texelFetch1D( materials, i + 14u );
|
|
6143
6303
|
return bool( int( s14.b ) & 4 );
|
|
6144
6304
|
|
|
@@ -6368,7 +6528,8 @@ const attenuate_hit_function = /* glsl */`
|
|
|
6368
6528
|
// alphaMap
|
|
6369
6529
|
if ( material.alphaMap != - 1 ) {
|
|
6370
6530
|
|
|
6371
|
-
|
|
6531
|
+
vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
|
|
6532
|
+
albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
|
|
6372
6533
|
|
|
6373
6534
|
}
|
|
6374
6535
|
|
|
@@ -6510,7 +6671,7 @@ const camera_util_functions = /* glsl */`
|
|
|
6510
6671
|
vec3 shapeUVW= rand3( 1 );
|
|
6511
6672
|
int blades = physicalCamera.apertureBlades;
|
|
6512
6673
|
float anamorphicRatio = physicalCamera.anamorphicRatio;
|
|
6513
|
-
vec2 apertureSample =
|
|
6674
|
+
vec2 apertureSample = sampleAperture( blades, shapeUVW );
|
|
6514
6675
|
apertureSample *= physicalCamera.bokehSize * 0.5 * 1e-3;
|
|
6515
6676
|
|
|
6516
6677
|
// rotate the aperture shape
|
|
@@ -6680,7 +6841,8 @@ const get_surface_record_function = /* glsl */`
|
|
|
6680
6841
|
// alphaMap
|
|
6681
6842
|
if ( material.alphaMap != - 1 ) {
|
|
6682
6843
|
|
|
6683
|
-
|
|
6844
|
+
vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
|
|
6845
|
+
albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
|
|
6684
6846
|
|
|
6685
6847
|
}
|
|
6686
6848
|
|
|
@@ -7095,6 +7257,7 @@ class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
7095
7257
|
ATTR_TANGENT: 1,
|
|
7096
7258
|
ATTR_UV: 2,
|
|
7097
7259
|
ATTR_COLOR: 3,
|
|
7260
|
+
MATERIAL_PIXELS: MATERIAL_PIXELS,
|
|
7098
7261
|
},
|
|
7099
7262
|
|
|
7100
7263
|
uniforms: {
|
|
@@ -7777,6 +7940,9 @@ class PathTracingRenderer {
|
|
|
7777
7940
|
|
|
7778
7941
|
set material( v ) {
|
|
7779
7942
|
|
|
7943
|
+
this._fsQuad.material.removeEventListener( 'recompilation', this._compileFunction );
|
|
7944
|
+
v.addEventListener( 'recompilation', this._compileFunction );
|
|
7945
|
+
|
|
7780
7946
|
this._fsQuad.material = v;
|
|
7781
7947
|
|
|
7782
7948
|
}
|
|
@@ -7813,6 +7979,12 @@ class PathTracingRenderer {
|
|
|
7813
7979
|
|
|
7814
7980
|
}
|
|
7815
7981
|
|
|
7982
|
+
get isCompiling() {
|
|
7983
|
+
|
|
7984
|
+
return Boolean( this._compilePromise );
|
|
7985
|
+
|
|
7986
|
+
}
|
|
7987
|
+
|
|
7816
7988
|
constructor( renderer ) {
|
|
7817
7989
|
|
|
7818
7990
|
this.camera = null;
|
|
@@ -7830,6 +8002,7 @@ class PathTracingRenderer {
|
|
|
7830
8002
|
this._blendQuad = new FullScreenQuad( new BlendMaterial() );
|
|
7831
8003
|
this._task = null;
|
|
7832
8004
|
this._currentTile = 0;
|
|
8005
|
+
this._compilePromise = null;
|
|
7833
8006
|
|
|
7834
8007
|
this._sobolTarget = new SobolNumberMapGenerator().generate( renderer );
|
|
7835
8008
|
|
|
@@ -7854,6 +8027,33 @@ class PathTracingRenderer {
|
|
|
7854
8027
|
} ),
|
|
7855
8028
|
];
|
|
7856
8029
|
|
|
8030
|
+
// function for listening to for triggered compilation so we can wait for compilation to finish
|
|
8031
|
+
// before starting to render
|
|
8032
|
+
this._compileFunction = () => {
|
|
8033
|
+
|
|
8034
|
+
const promise = this.compileMaterial( this._fsQuad._mesh );
|
|
8035
|
+
promise.then( () => {
|
|
8036
|
+
|
|
8037
|
+
if ( this._compilePromise === promise ) {
|
|
8038
|
+
|
|
8039
|
+
this._compilePromise = null;
|
|
8040
|
+
|
|
8041
|
+
}
|
|
8042
|
+
|
|
8043
|
+
} );
|
|
8044
|
+
|
|
8045
|
+
this._compilePromise = promise;
|
|
8046
|
+
|
|
8047
|
+
};
|
|
8048
|
+
|
|
8049
|
+
this.material.addEventListener( 'recompilation', this._compileFunction );
|
|
8050
|
+
|
|
8051
|
+
}
|
|
8052
|
+
|
|
8053
|
+
compileMaterial() {
|
|
8054
|
+
|
|
8055
|
+
return this._renderer.compileAsync( this._fsQuad._mesh );
|
|
8056
|
+
|
|
7857
8057
|
}
|
|
7858
8058
|
|
|
7859
8059
|
setCamera( camera ) {
|
|
@@ -7885,7 +8085,6 @@ class PathTracingRenderer {
|
|
|
7885
8085
|
material.setDefine( 'CAMERA_TYPE', cameraType );
|
|
7886
8086
|
|
|
7887
8087
|
this.camera = camera;
|
|
7888
|
-
// this.reset();
|
|
7889
8088
|
|
|
7890
8089
|
}
|
|
7891
8090
|
|
|
@@ -7952,9 +8151,11 @@ class PathTracingRenderer {
|
|
|
7952
8151
|
this.samples = 0;
|
|
7953
8152
|
this._task = null;
|
|
7954
8153
|
|
|
8154
|
+
this.material.stratifiedTexture.stableNoise = this.stableNoise;
|
|
7955
8155
|
if ( this.stableNoise ) {
|
|
7956
8156
|
|
|
7957
8157
|
this.material.seed = 0;
|
|
8158
|
+
this.material.stratifiedTexture.reset();
|
|
7958
8159
|
|
|
7959
8160
|
}
|
|
7960
8161
|
|
|
@@ -7962,6 +8163,15 @@ class PathTracingRenderer {
|
|
|
7962
8163
|
|
|
7963
8164
|
update() {
|
|
7964
8165
|
|
|
8166
|
+
// ensure we've updated our defines before rendering so we can ensure we
|
|
8167
|
+
// can wait for compilation to finish
|
|
8168
|
+
this.material.onBeforeRender();
|
|
8169
|
+
if ( this.isCompiling ) {
|
|
8170
|
+
|
|
8171
|
+
return;
|
|
8172
|
+
|
|
8173
|
+
}
|
|
8174
|
+
|
|
7965
8175
|
if ( ! this._task ) {
|
|
7966
8176
|
|
|
7967
8177
|
this._task = renderTask.call( this );
|
|
@@ -8181,6 +8391,150 @@ class ClampedInterpolationMaterial extends ShaderMaterial {
|
|
|
8181
8391
|
|
|
8182
8392
|
}
|
|
8183
8393
|
|
|
8394
|
+
class CubeToEquirectMaterial extends ShaderMaterial {
|
|
8395
|
+
|
|
8396
|
+
constructor() {
|
|
8397
|
+
|
|
8398
|
+
super( {
|
|
8399
|
+
|
|
8400
|
+
uniforms: {
|
|
8401
|
+
|
|
8402
|
+
envMap: { value: null },
|
|
8403
|
+
flipEnvMap: { value: - 1 },
|
|
8404
|
+
|
|
8405
|
+
},
|
|
8406
|
+
|
|
8407
|
+
vertexShader: /* glsl */`
|
|
8408
|
+
varying vec2 vUv;
|
|
8409
|
+
void main() {
|
|
8410
|
+
|
|
8411
|
+
vUv = uv;
|
|
8412
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
8413
|
+
|
|
8414
|
+
}`,
|
|
8415
|
+
|
|
8416
|
+
fragmentShader: /* glsl */`
|
|
8417
|
+
#define ENVMAP_TYPE_CUBE_UV
|
|
8418
|
+
|
|
8419
|
+
uniform samplerCube envMap;
|
|
8420
|
+
uniform float flipEnvMap;
|
|
8421
|
+
varying vec2 vUv;
|
|
8422
|
+
|
|
8423
|
+
#include <common>
|
|
8424
|
+
#include <cube_uv_reflection_fragment>
|
|
8425
|
+
|
|
8426
|
+
${ util_functions }
|
|
8427
|
+
|
|
8428
|
+
void main() {
|
|
8429
|
+
|
|
8430
|
+
vec3 rayDirection = equirectUvToDirection( vUv );
|
|
8431
|
+
rayDirection.x *= flipEnvMap;
|
|
8432
|
+
gl_FragColor = textureCube( envMap, rayDirection );
|
|
8433
|
+
|
|
8434
|
+
}`
|
|
8435
|
+
} );
|
|
8436
|
+
|
|
8437
|
+
this.depthWrite = false;
|
|
8438
|
+
this.depthTest = false;
|
|
8439
|
+
|
|
8440
|
+
}
|
|
8441
|
+
|
|
8442
|
+
}
|
|
8443
|
+
|
|
8444
|
+
class CubeToEquirectGenerator {
|
|
8445
|
+
|
|
8446
|
+
constructor( renderer ) {
|
|
8447
|
+
|
|
8448
|
+
this._renderer = renderer;
|
|
8449
|
+
this._quad = new FullScreenQuad( new CubeToEquirectMaterial() );
|
|
8450
|
+
|
|
8451
|
+
}
|
|
8452
|
+
|
|
8453
|
+
generate( source, width = null, height = null ) {
|
|
8454
|
+
|
|
8455
|
+
if ( ! source.isCubeTexture ) {
|
|
8456
|
+
|
|
8457
|
+
throw new Error( 'CubeToEquirectMaterial: Source can only be cube textures.' );
|
|
8458
|
+
|
|
8459
|
+
}
|
|
8460
|
+
|
|
8461
|
+
const image = source.images[ 0 ];
|
|
8462
|
+
const renderer = this._renderer;
|
|
8463
|
+
const quad = this._quad;
|
|
8464
|
+
|
|
8465
|
+
// determine the dimensions if not provided
|
|
8466
|
+
if ( width === null ) {
|
|
8467
|
+
|
|
8468
|
+
width = 4 * image.height;
|
|
8469
|
+
|
|
8470
|
+
}
|
|
8471
|
+
|
|
8472
|
+
if ( height === null ) {
|
|
8473
|
+
|
|
8474
|
+
height = 2 * image.height;
|
|
8475
|
+
|
|
8476
|
+
}
|
|
8477
|
+
|
|
8478
|
+
const target = new WebGLRenderTarget( width, height, {
|
|
8479
|
+
type: FloatType,
|
|
8480
|
+
colorSpace: image.colorSpace,
|
|
8481
|
+
} );
|
|
8482
|
+
|
|
8483
|
+
// prep the cube map data
|
|
8484
|
+
const imageHeight = image.height;
|
|
8485
|
+
const maxMip = Math.log2( imageHeight ) - 2;
|
|
8486
|
+
const texelHeight = 1.0 / imageHeight;
|
|
8487
|
+
const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) );
|
|
8488
|
+
|
|
8489
|
+
quad.material.defines.CUBEUV_MAX_MIP = `${ maxMip }.0`;
|
|
8490
|
+
quad.material.defines.CUBEUV_TEXEL_WIDTH = texelWidth;
|
|
8491
|
+
quad.material.defines.CUBEUV_TEXEL_HEIGHT = texelHeight;
|
|
8492
|
+
quad.material.uniforms.envMap.value = source;
|
|
8493
|
+
quad.material.uniforms.flipEnvMap.value = source.isRenderTargetTexture ? 1 : - 1;
|
|
8494
|
+
quad.material.needsUpdate = true;
|
|
8495
|
+
|
|
8496
|
+
// save state and render the contents
|
|
8497
|
+
const currentTarget = renderer.getRenderTarget();
|
|
8498
|
+
const currentAutoClear = renderer.autoClear;
|
|
8499
|
+
renderer.autoClear = true;
|
|
8500
|
+
renderer.setRenderTarget( target );
|
|
8501
|
+
quad.render( renderer );
|
|
8502
|
+
renderer.setRenderTarget( currentTarget );
|
|
8503
|
+
renderer.autoClear = currentAutoClear;
|
|
8504
|
+
|
|
8505
|
+
// read the data back
|
|
8506
|
+
const buffer = new Uint16Array( width * height * 4 );
|
|
8507
|
+
const readBuffer = new Float32Array( width * height * 4 );
|
|
8508
|
+
renderer.readRenderTargetPixels( target, 0, 0, width, height, readBuffer );
|
|
8509
|
+
target.dispose();
|
|
8510
|
+
|
|
8511
|
+
for ( let i = 0, l = readBuffer.length; i < l; i ++ ) {
|
|
8512
|
+
|
|
8513
|
+
buffer[ i ] = DataUtils.toHalfFloat( readBuffer[ i ] );
|
|
8514
|
+
|
|
8515
|
+
}
|
|
8516
|
+
|
|
8517
|
+
// produce the data texture
|
|
8518
|
+
const result = new DataTexture( buffer, width, height, RGBAFormat, HalfFloatType );
|
|
8519
|
+
result.minFilter = LinearMipMapLinearFilter;
|
|
8520
|
+
result.magFilter = LinearFilter;
|
|
8521
|
+
result.wrapS = RepeatWrapping;
|
|
8522
|
+
result.wrapT = RepeatWrapping;
|
|
8523
|
+
result.mapping = EquirectangularReflectionMapping;
|
|
8524
|
+
result.needsUpdate = true;
|
|
8525
|
+
|
|
8526
|
+
return result;
|
|
8527
|
+
|
|
8528
|
+
}
|
|
8529
|
+
|
|
8530
|
+
dispose() {
|
|
8531
|
+
|
|
8532
|
+
this._quad.dispose();
|
|
8533
|
+
|
|
8534
|
+
}
|
|
8535
|
+
|
|
8536
|
+
}
|
|
8537
|
+
|
|
8184
8538
|
function supportsFloatBlending( renderer ) {
|
|
8185
8539
|
|
|
8186
8540
|
return renderer.extensions.get( 'EXT_float_blend' );
|
|
@@ -8256,6 +8610,24 @@ class WebGLPathTracer {
|
|
|
8256
8610
|
|
|
8257
8611
|
}
|
|
8258
8612
|
|
|
8613
|
+
get stableNoise() {
|
|
8614
|
+
|
|
8615
|
+
return this._pathTracer.stableNoise;
|
|
8616
|
+
|
|
8617
|
+
}
|
|
8618
|
+
|
|
8619
|
+
set stableNoise( v ) {
|
|
8620
|
+
|
|
8621
|
+
this._pathTracer.stableNoise = v;
|
|
8622
|
+
|
|
8623
|
+
}
|
|
8624
|
+
|
|
8625
|
+
get isCompiling() {
|
|
8626
|
+
|
|
8627
|
+
return Boolean( this._pathTracer.isCompiling );
|
|
8628
|
+
|
|
8629
|
+
}
|
|
8630
|
+
|
|
8259
8631
|
constructor( renderer ) {
|
|
8260
8632
|
|
|
8261
8633
|
// members
|
|
@@ -8264,6 +8636,7 @@ class WebGLPathTracer {
|
|
|
8264
8636
|
this._pathTracer = new PathTracingRenderer( renderer );
|
|
8265
8637
|
this._queueReset = false;
|
|
8266
8638
|
this._clock = new Clock();
|
|
8639
|
+
this._compilePromise = null;
|
|
8267
8640
|
|
|
8268
8641
|
this._lowResPathTracer = new PathTracingRenderer( renderer );
|
|
8269
8642
|
this._lowResPathTracer.tiles.set( 1, 1 );
|
|
@@ -8276,6 +8649,10 @@ class WebGLPathTracer {
|
|
|
8276
8649
|
} ) );
|
|
8277
8650
|
this._materials = null;
|
|
8278
8651
|
|
|
8652
|
+
this._previousEnvironment = null;
|
|
8653
|
+
this._previousBackground = null;
|
|
8654
|
+
this._internalBackground = null;
|
|
8655
|
+
|
|
8279
8656
|
// options
|
|
8280
8657
|
this.renderDelay = 100;
|
|
8281
8658
|
this.minSamples = 5;
|
|
@@ -8404,6 +8781,13 @@ class WebGLPathTracer {
|
|
|
8404
8781
|
const scene = this.scene;
|
|
8405
8782
|
const material = this._pathTracer.material;
|
|
8406
8783
|
|
|
8784
|
+
if ( this._internalBackground ) {
|
|
8785
|
+
|
|
8786
|
+
this._internalBackground.dispose();
|
|
8787
|
+
this._internalBackground = null;
|
|
8788
|
+
|
|
8789
|
+
}
|
|
8790
|
+
|
|
8407
8791
|
// update scene background
|
|
8408
8792
|
material.backgroundBlur = scene.backgroundBlurriness;
|
|
8409
8793
|
material.backgroundIntensity = scene.backgroundIntensity ?? 1;
|
|
@@ -8431,6 +8815,17 @@ class WebGLPathTracer {
|
|
|
8431
8815
|
material.backgroundMap = colorBackground;
|
|
8432
8816
|
material.backgroundAlpha = 1;
|
|
8433
8817
|
|
|
8818
|
+
} else if ( scene.background.isCubeTexture ) {
|
|
8819
|
+
|
|
8820
|
+
if ( scene.background !== this._previousBackground ) {
|
|
8821
|
+
|
|
8822
|
+
const background = new CubeToEquirectGenerator( this._renderer ).generate( scene.background );
|
|
8823
|
+
this._internalBackground = background;
|
|
8824
|
+
material.backgroundMap = background;
|
|
8825
|
+
material.backgroundAlpha = 1;
|
|
8826
|
+
|
|
8827
|
+
}
|
|
8828
|
+
|
|
8434
8829
|
} else {
|
|
8435
8830
|
|
|
8436
8831
|
material.backgroundMap = scene.background;
|
|
@@ -8439,26 +8834,32 @@ class WebGLPathTracer {
|
|
|
8439
8834
|
}
|
|
8440
8835
|
|
|
8441
8836
|
// update scene environment
|
|
8442
|
-
material.environmentIntensity = scene.environmentIntensity ?? 1;
|
|
8837
|
+
material.environmentIntensity = scene.environment !== null ? ( scene.environmentIntensity ?? 1 ) : 0;
|
|
8443
8838
|
material.environmentRotation.makeRotationFromEuler( scene.environmentRotation ).invert();
|
|
8444
8839
|
if ( this._previousEnvironment !== scene.environment ) {
|
|
8445
8840
|
|
|
8446
|
-
if ( scene.environment ) {
|
|
8841
|
+
if ( scene.environment !== null ) {
|
|
8447
8842
|
|
|
8448
|
-
|
|
8449
|
-
// OES_texture_float_linear or OES_texture_half_float_linear. Requires changes to
|
|
8450
|
-
// the equirect uniform
|
|
8451
|
-
material.envMapInfo.updateFrom( scene.environment );
|
|
8843
|
+
if ( scene.environment.isCubeTexture ) {
|
|
8452
8844
|
|
|
8453
|
-
|
|
8845
|
+
const environment = new CubeToEquirectGenerator( this._renderer ).generate( scene.environment );
|
|
8846
|
+
material.envMapInfo.updateFrom( environment );
|
|
8847
|
+
|
|
8848
|
+
} else {
|
|
8849
|
+
|
|
8850
|
+
// TODO: Consider setting this to the highest supported bit depth by checking for
|
|
8851
|
+
// OES_texture_float_linear or OES_texture_half_float_linear. Requires changes to
|
|
8852
|
+
// the equirect uniform
|
|
8853
|
+
material.envMapInfo.updateFrom( scene.environment );
|
|
8454
8854
|
|
|
8455
|
-
|
|
8855
|
+
}
|
|
8456
8856
|
|
|
8457
8857
|
}
|
|
8458
8858
|
|
|
8459
8859
|
}
|
|
8460
8860
|
|
|
8461
8861
|
this._previousEnvironment = scene.environment;
|
|
8862
|
+
this._previousBackground = scene.background;
|
|
8462
8863
|
this.reset();
|
|
8463
8864
|
|
|
8464
8865
|
}
|
|
@@ -8470,6 +8871,7 @@ class WebGLPathTracer {
|
|
|
8470
8871
|
geometry,
|
|
8471
8872
|
bvh,
|
|
8472
8873
|
bvhChanged,
|
|
8874
|
+
needsMaterialIndexUpdate,
|
|
8473
8875
|
} = results;
|
|
8474
8876
|
|
|
8475
8877
|
this._materials = materials;
|
|
@@ -8487,6 +8889,10 @@ class WebGLPathTracer {
|
|
|
8487
8889
|
geometry.attributes.color,
|
|
8488
8890
|
);
|
|
8489
8891
|
|
|
8892
|
+
}
|
|
8893
|
+
|
|
8894
|
+
if ( needsMaterialIndexUpdate ) {
|
|
8895
|
+
|
|
8490
8896
|
material.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
|
|
8491
8897
|
|
|
8492
8898
|
}
|
|
@@ -8529,7 +8935,7 @@ class WebGLPathTracer {
|
|
|
8529
8935
|
// render the path tracing sample after enough time has passed
|
|
8530
8936
|
const delta = clock.getDelta() * 1e3;
|
|
8531
8937
|
const elapsedTime = clock.getElapsedTime() * 1e3;
|
|
8532
|
-
if ( ! this.pausePathTracing && this.enablePathTracing && this.renderDelay <= elapsedTime ) {
|
|
8938
|
+
if ( ! this.pausePathTracing && this.enablePathTracing && this.renderDelay <= elapsedTime && ! this.isCompiling ) {
|
|
8533
8939
|
|
|
8534
8940
|
pathTracer.update();
|
|
8535
8941
|
|
|
@@ -8562,7 +8968,7 @@ class WebGLPathTracer {
|
|
|
8562
8968
|
// render the fallback if we haven't rendered enough samples, are paused, or are occluded
|
|
8563
8969
|
if ( ! this.enablePathTracing || this.samples < minSamples || quad.material.opacity < 1 ) {
|
|
8564
8970
|
|
|
8565
|
-
if ( this.dynamicLowRes ) {
|
|
8971
|
+
if ( this.dynamicLowRes && ! this.isCompiling ) {
|
|
8566
8972
|
|
|
8567
8973
|
if ( lowResPathTracer.samples < 1 ) {
|
|
8568
8974
|
|
|
@@ -8577,7 +8983,9 @@ class WebGLPathTracer {
|
|
|
8577
8983
|
quad.render( renderer );
|
|
8578
8984
|
quad.material.opacity = currentOpacity;
|
|
8579
8985
|
|
|
8580
|
-
}
|
|
8986
|
+
}
|
|
8987
|
+
|
|
8988
|
+
if ( ! this.dynamicLowRes && this.rasterizeScene || this.dynamicLowRes && this.isCompiling ) {
|
|
8581
8989
|
|
|
8582
8990
|
this.rasterizeSceneCallback( this.scene, this.camera );
|
|
8583
8991
|
|
|
@@ -8615,8 +9023,8 @@ class WebGLPathTracer {
|
|
|
8615
9023
|
|
|
8616
9024
|
dispose() {
|
|
8617
9025
|
|
|
8618
|
-
this.
|
|
8619
|
-
this.
|
|
9026
|
+
this._quad.dispose();
|
|
9027
|
+
this._quad.material.dispose();
|
|
8620
9028
|
this._pathTracer.dispose();
|
|
8621
9029
|
|
|
8622
9030
|
}
|