rayzee 7.7.0 → 7.9.0
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 +1 -1
- package/dist/assets/{BVHSubtreeWorker-D9GImjGj.js → BVHSubtreeWorker-sNzvxn66.js} +2 -2
- package/dist/assets/{BVHSubtreeWorker-D9GImjGj.js.map → BVHSubtreeWorker-sNzvxn66.js.map} +1 -1
- package/dist/assets/{BVHWorker-CNJ0UBQz.js → BVHWorker-CiVdFrwe.js} +2 -2
- package/dist/assets/{BVHWorker-CNJ0UBQz.js.map → BVHWorker-CiVdFrwe.js.map} +1 -1
- package/dist/rayzee.es.js +2057 -2035
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +55 -55
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/EngineDefaults.js +45 -1
- package/src/EngineEvents.js +1 -0
- package/src/Passes/OIDNDenoiser.js +25 -1
- package/src/PathTracerApp.js +36 -0
- package/src/Processor/AssetLoader.js +3 -0
- package/src/Processor/GeometryExtractor.js +35 -9
- package/src/Processor/PackedRayBuffer.js +15 -1
- package/src/Processor/QueueManager.js +13 -1
- package/src/Processor/SceneProcessor.js +176 -113
- package/src/Processor/ShaderBuilder.js +6 -24
- package/src/Processor/TextureCreator.js +16 -32
- package/src/Processor/Workers/BVHWorker.js +6 -1
- package/src/Stages/EdgeFilter.js +4 -3
- package/src/Stages/MotionVector.js +4 -4
- package/src/Stages/NormalDepth.js +20 -30
- package/src/Stages/PathTracer.js +20 -40
- package/src/TSL/DebugKernel.js +0 -2
- package/src/TSL/Debugger.js +1 -8
- package/src/TSL/Displacement.js +10 -10
- package/src/TSL/GenerateKernel.js +5 -1
- package/src/TSL/LightsDirect.js +8 -9
- package/src/TSL/LightsIndirect.js +15 -9
- package/src/TSL/LightsSampling.js +9 -19
- package/src/TSL/Random.js +11 -1
- package/src/TSL/ShadeKernel.js +1 -6
- package/src/TSL/TextureSampling.js +155 -34
- package/src/managers/EnvironmentManager.js +11 -0
- package/src/managers/MaterialDataManager.js +71 -39
- package/src/managers/RenderTargetManager.js +0 -522
|
@@ -9,7 +9,8 @@ import { GeometryExtractor } from './GeometryExtractor.js';
|
|
|
9
9
|
import { EmissiveTriangleBuilder } from './EmissiveTriangleBuilder.js';
|
|
10
10
|
import { updateLoading } from '../Processor/utils.js';
|
|
11
11
|
import { BuildTimer } from './BuildTimer.js';
|
|
12
|
-
import {
|
|
12
|
+
import { SRGBColorSpace } from 'three';
|
|
13
|
+
import { TRIANGLE_DATA_LAYOUT, TEXTURE_CONSTANTS, getTextureBucketId, packTextureIndex } from '../EngineDefaults.js';
|
|
13
14
|
import { fetchAsWorker } from './Workers/fetchAsWorker.js';
|
|
14
15
|
import BVH_WORKER_URL from './Workers/BVHWorker.js?worker&url';
|
|
15
16
|
import BVH_REFIT_WORKER_URL from './Workers/BVHRefitWorker.js?worker&url';
|
|
@@ -79,14 +80,13 @@ export class SceneProcessor {
|
|
|
79
80
|
this._rebuildGeneration = 0; // Monotonic counter to discard stale background rebuilds
|
|
80
81
|
this._pendingRebuilds = new Map(); // meshIndex → worker
|
|
81
82
|
|
|
82
|
-
// Initialize texture references
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
this.
|
|
88
|
-
this.
|
|
89
|
-
this.displacementTextures = null;
|
|
83
|
+
// Initialize texture references.
|
|
84
|
+
// Material maps are packed into consolidated size-bucketed arrays (see _bucketTextures):
|
|
85
|
+
// srgbBucketTextures[K] — albedo + emissive (SRGBColorSpace)
|
|
86
|
+
// linearBucketTextures[K] — normal/bump/roughness/metalness/displacement
|
|
87
|
+
// A material's per-map index encodes (bucket, layer) via packTextureIndex.
|
|
88
|
+
this.srgbBucketTextures = null;
|
|
89
|
+
this.linearBucketTextures = null;
|
|
90
90
|
this.emissiveTriangleData = null;
|
|
91
91
|
this.emissiveTriangleCount = 0;
|
|
92
92
|
this.lightBVHNodeData = null;
|
|
@@ -422,7 +422,13 @@ export class SceneProcessor {
|
|
|
422
422
|
enabled: this.bvhBuilder.enableReinsertionOptimization,
|
|
423
423
|
batchSizeRatio: this.bvhBuilder.reinsertionBatchSizeRatio,
|
|
424
424
|
maxIterations: this.bvhBuilder.reinsertionMaxIterations
|
|
425
|
-
}
|
|
425
|
+
},
|
|
426
|
+
// BVH build params — previously omitted, so the pool path built at the
|
|
427
|
+
// BVHBuilder default (leaf 8) instead of the configured value.
|
|
428
|
+
maxLeafSize: this.bvhBuilder.maxLeafSize,
|
|
429
|
+
numBins: this.bvhBuilder.numBins,
|
|
430
|
+
maxBins: this.bvhBuilder.maxBins,
|
|
431
|
+
minBins: this.bvhBuilder.minBins,
|
|
426
432
|
};
|
|
427
433
|
|
|
428
434
|
const totalTasks = poolTasks.length + parallelTasks.length;
|
|
@@ -630,6 +636,10 @@ export class SceneProcessor {
|
|
|
630
636
|
sharedReorderBuffer: null,
|
|
631
637
|
treeletOptimization: treeletOpts,
|
|
632
638
|
reinsertionOptimization: opts.reinsertionOptimization,
|
|
639
|
+
maxLeafSize: opts.maxLeafSize,
|
|
640
|
+
numBins: opts.numBins,
|
|
641
|
+
maxBins: opts.maxBins,
|
|
642
|
+
minBins: opts.minBins,
|
|
633
643
|
}, [ meshTriData.buffer ] );
|
|
634
644
|
|
|
635
645
|
};
|
|
@@ -762,40 +772,45 @@ export class SceneProcessor {
|
|
|
762
772
|
|
|
763
773
|
try {
|
|
764
774
|
|
|
765
|
-
//
|
|
775
|
+
// Group the extractor's per-type arrays into consolidated colorSpace×size-bucket
|
|
776
|
+
// pools, and rewrite each material's per-map index to the packed (bucket, layer)
|
|
777
|
+
// form. Must run BEFORE createMaterialRawData (which reads mat.map etc.).
|
|
778
|
+
const { srgbLists, linearLists, remap } = this._bucketTextures();
|
|
779
|
+
this._remapMaterialTextureIndices( remap );
|
|
780
|
+
|
|
781
|
+
// Material raw data for storage buffers (sync, ~1-5ms) — now holds packed indices.
|
|
766
782
|
if ( this.materials?.length ) {
|
|
767
783
|
|
|
768
784
|
this.materialData = this.textureCreator.createMaterialRawData( this.materials );
|
|
769
785
|
|
|
770
786
|
}
|
|
771
787
|
|
|
772
|
-
//
|
|
773
|
-
//
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
} )
|
|
794
|
-
)
|
|
795
|
-
);
|
|
788
|
+
// One DataArrayTexture per non-empty bucket. The sRGB pool (albedo + emissive — both
|
|
789
|
+
// authored in sRGB per glTF) carries SRGBColorSpace so the GPU decodes sRGB→linear
|
|
790
|
+
// before lighting; the linear pool (normal/roughness/metalness/bump/displacement —
|
|
791
|
+
// data textures) stays linear. Applied consistently across load AND rebuildMaterials
|
|
792
|
+
// (the prior model-load path omitted this, leaving albedo un-decoded / too bright).
|
|
793
|
+
const buildBucket = ( list, srgb ) => list.length === 0
|
|
794
|
+
? Promise.resolve( null )
|
|
795
|
+
: this.textureCreator.createTexturesToDataTexture( list ).then( tex => {
|
|
796
|
+
|
|
797
|
+
if ( tex && srgb ) tex.colorSpace = SRGBColorSpace;
|
|
798
|
+
return tex;
|
|
799
|
+
|
|
800
|
+
} );
|
|
801
|
+
|
|
802
|
+
const [ srgbTextures, linearTextures ] = await Promise.all( [
|
|
803
|
+
Promise.all( srgbLists.map( list => buildBucket( list, true ) ) ),
|
|
804
|
+
Promise.all( linearLists.map( list => buildBucket( list, false ) ) ),
|
|
805
|
+
] );
|
|
806
|
+
|
|
807
|
+
this.srgbBucketTextures = srgbTextures;
|
|
808
|
+
this.linearBucketTextures = linearTextures;
|
|
796
809
|
|
|
797
810
|
this._log( 'Material textures complete', {
|
|
798
811
|
materialData: !! this.materialData,
|
|
812
|
+
srgbBuckets: srgbTextures.map( t => ( t ? `${t.image.width}x${t.image.height}x${t.image.depth}` : '-' ) ).join( ',' ),
|
|
813
|
+
linearBuckets: linearTextures.map( t => ( t ? `${t.image.width}x${t.image.height}x${t.image.depth}` : '-' ) ).join( ',' ),
|
|
799
814
|
} );
|
|
800
815
|
|
|
801
816
|
} catch ( error ) {
|
|
@@ -807,6 +822,96 @@ export class SceneProcessor {
|
|
|
807
822
|
|
|
808
823
|
}
|
|
809
824
|
|
|
825
|
+
/**
|
|
826
|
+
* Group the extractor's seven per-type texture arrays into two consolidated colorSpace
|
|
827
|
+
* pools (sRGB: albedo+emissive; linear: normal/bump/roughness/metalness/displacement),
|
|
828
|
+
* each split into MATERIAL_BUCKET_COUNT longest-edge size buckets. Textures are deduped
|
|
829
|
+
* across types within a (pool, bucket) so a shared image (e.g. ORM) costs one layer.
|
|
830
|
+
* @returns {{ srgbLists: Array<Array>, linearLists: Array<Array>, remap: Object }}
|
|
831
|
+
* bucket lists + per-type remap arrays (old per-type layer → packed bucket index).
|
|
832
|
+
* @private
|
|
833
|
+
*/
|
|
834
|
+
_bucketTextures() {
|
|
835
|
+
|
|
836
|
+
const cap = this.config.maxTextureSize;
|
|
837
|
+
const K = TEXTURE_CONSTANTS.MATERIAL_BUCKET_COUNT;
|
|
838
|
+
const STRIDE = TEXTURE_CONSTANTS.BUCKET_LAYER_STRIDE;
|
|
839
|
+
|
|
840
|
+
const srgbLists = Array.from( { length: K }, () => [] );
|
|
841
|
+
const linearLists = Array.from( { length: K }, () => [] );
|
|
842
|
+
const srgbDedup = Array.from( { length: K }, () => new Map() );
|
|
843
|
+
const linearDedup = Array.from( { length: K }, () => new Map() );
|
|
844
|
+
|
|
845
|
+
// Persistent uuid → packed maps so runtime material edits (updateMaterial) can re-pack
|
|
846
|
+
// a texture's index against the CURRENT bucket layout instead of the stale per-type index.
|
|
847
|
+
this._srgbTexPacked = new Map();
|
|
848
|
+
this._linearTexPacked = new Map();
|
|
849
|
+
|
|
850
|
+
// Assign one texture to its (bucket, layer) within a pool; dedup by source uuid.
|
|
851
|
+
const assign = ( tex, lists, dedup, flat ) => {
|
|
852
|
+
|
|
853
|
+
if ( ! tex || ! tex.image ) return - 1;
|
|
854
|
+
const bucket = getTextureBucketId( tex.image.width, tex.image.height, cap, K );
|
|
855
|
+
const uuid = tex.source?.uuid ?? tex.uuid;
|
|
856
|
+
const seen = dedup[ bucket ].get( uuid );
|
|
857
|
+
if ( seen !== undefined ) return packTextureIndex( bucket, seen );
|
|
858
|
+
if ( lists[ bucket ].length >= STRIDE ) {
|
|
859
|
+
|
|
860
|
+
console.warn( `[SceneProcessor] Texture bucket ${bucket} full (${STRIDE}); dropping a map.` );
|
|
861
|
+
return - 1;
|
|
862
|
+
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
lists[ bucket ].push( tex );
|
|
866
|
+
const layer = lists[ bucket ].length - 1;
|
|
867
|
+
dedup[ bucket ].set( uuid, layer );
|
|
868
|
+
const packed = packTextureIndex( bucket, layer );
|
|
869
|
+
flat.set( uuid, packed );
|
|
870
|
+
return packed;
|
|
871
|
+
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
// Per-type arrays hold unique textures indexed by the layer the extractor assigned
|
|
875
|
+
// (= array position), so remap[type][oldLayer] = packed index.
|
|
876
|
+
const remapType = ( arr, lists, dedup, flat ) => ( arr || [] ).map( tex => assign( tex, lists, dedup, flat ) );
|
|
877
|
+
|
|
878
|
+
const remap = {
|
|
879
|
+
albedo: remapType( this.maps, srgbLists, srgbDedup, this._srgbTexPacked ),
|
|
880
|
+
emissive: remapType( this.emissiveMaps, srgbLists, srgbDedup, this._srgbTexPacked ),
|
|
881
|
+
normal: remapType( this.normalMaps, linearLists, linearDedup, this._linearTexPacked ),
|
|
882
|
+
bump: remapType( this.bumpMaps, linearLists, linearDedup, this._linearTexPacked ),
|
|
883
|
+
roughness: remapType( this.roughnessMaps, linearLists, linearDedup, this._linearTexPacked ),
|
|
884
|
+
metalness: remapType( this.metalnessMaps, linearLists, linearDedup, this._linearTexPacked ),
|
|
885
|
+
displacement: remapType( this.displacementMaps, linearLists, linearDedup, this._linearTexPacked ),
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
return { srgbLists, linearLists, remap };
|
|
889
|
+
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Rewrite each material's per-map index from the extractor's per-type layer to the
|
|
894
|
+
* packed (bucket, layer) index. Idempotency is NOT guaranteed — call exactly once per
|
|
895
|
+
* extraction (materials are freshly extracted on each process/rebuild).
|
|
896
|
+
* @private
|
|
897
|
+
*/
|
|
898
|
+
_remapMaterialTextureIndices( remap ) {
|
|
899
|
+
|
|
900
|
+
const fix = ( v, table ) => ( v >= 0 && v < table.length ? table[ v ] : - 1 );
|
|
901
|
+
for ( const mat of this.materials ) {
|
|
902
|
+
|
|
903
|
+
mat.map = fix( mat.map, remap.albedo );
|
|
904
|
+
mat.emissiveMap = fix( mat.emissiveMap, remap.emissive );
|
|
905
|
+
mat.normalMap = fix( mat.normalMap, remap.normal );
|
|
906
|
+
mat.bumpMap = fix( mat.bumpMap, remap.bump );
|
|
907
|
+
mat.roughnessMap = fix( mat.roughnessMap, remap.roughness );
|
|
908
|
+
mat.metalnessMap = fix( mat.metalnessMap, remap.metalness );
|
|
909
|
+
mat.displacementMap = fix( mat.displacementMap, remap.displacement );
|
|
910
|
+
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
}
|
|
914
|
+
|
|
810
915
|
/**
|
|
811
916
|
* Extract emissive triangles and build Light BVH.
|
|
812
917
|
* MUST run after BVH reordering — emissive data stores triangle indices
|
|
@@ -905,27 +1010,42 @@ export class SceneProcessor {
|
|
|
905
1010
|
*/
|
|
906
1011
|
_disposeTextures() {
|
|
907
1012
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1013
|
+
this._disposeBucketTextures();
|
|
1014
|
+
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Dispose the consolidated bucket arrays (srgb/linear), each an Array<K> of
|
|
1019
|
+
* DataArrayTexture | null.
|
|
1020
|
+
* @private
|
|
1021
|
+
*/
|
|
1022
|
+
_disposeBucketTextures() {
|
|
912
1023
|
|
|
913
|
-
|
|
914
|
-
textureProps.forEach( prop => {
|
|
1024
|
+
for ( const prop of [ 'srgbBucketTextures', 'linearBucketTextures' ] ) {
|
|
915
1025
|
|
|
916
|
-
|
|
1026
|
+
const arr = this[ prop ];
|
|
1027
|
+
if ( ! arr ) continue;
|
|
1028
|
+
for ( const tex of arr ) {
|
|
917
1029
|
|
|
918
|
-
if (
|
|
1030
|
+
if ( tex && typeof tex.dispose === 'function' ) {
|
|
919
1031
|
|
|
920
|
-
|
|
1032
|
+
try {
|
|
921
1033
|
|
|
922
|
-
|
|
1034
|
+
tex.dispose();
|
|
1035
|
+
|
|
1036
|
+
} catch ( error ) {
|
|
923
1037
|
|
|
924
|
-
|
|
1038
|
+
console.warn( `[SceneProcessor] Error disposing ${prop}:`, error );
|
|
1039
|
+
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
}
|
|
925
1043
|
|
|
926
1044
|
}
|
|
927
1045
|
|
|
928
|
-
|
|
1046
|
+
this[ prop ] = null;
|
|
1047
|
+
|
|
1048
|
+
}
|
|
929
1049
|
|
|
930
1050
|
}
|
|
931
1051
|
|
|
@@ -969,34 +1089,9 @@ export class SceneProcessor {
|
|
|
969
1089
|
this.displacementMaps = extractedData.displacementMaps;
|
|
970
1090
|
this.sceneFeatures = extractedData.sceneFeatures; // Update material feature flags
|
|
971
1091
|
|
|
972
|
-
//
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
triangles: this.triangleData, // Reuse existing triangle data
|
|
976
|
-
maps: this.maps,
|
|
977
|
-
normalMaps: this.normalMaps,
|
|
978
|
-
bumpMaps: this.bumpMaps,
|
|
979
|
-
roughnessMaps: this.roughnessMaps,
|
|
980
|
-
metalnessMaps: this.metalnessMaps,
|
|
981
|
-
emissiveMaps: this.emissiveMaps,
|
|
982
|
-
displacementMaps: this.displacementMaps,
|
|
983
|
-
bvhRoot: this.bvhRoot // Reuse existing BVH
|
|
984
|
-
};
|
|
985
|
-
|
|
986
|
-
// Create only material and texture-related textures
|
|
987
|
-
const textures = await this.textureCreator.createMaterialTextures( params );
|
|
988
|
-
|
|
989
|
-
// Regenerate raw material data for storage buffers
|
|
990
|
-
this.materialData = this.textureCreator.createMaterialRawData( this.materials );
|
|
991
|
-
|
|
992
|
-
// Update texture references (keep triangle and BVH data unchanged)
|
|
993
|
-
this.albedoTextures = textures.albedoTexture;
|
|
994
|
-
this.normalTextures = textures.normalTexture;
|
|
995
|
-
this.bumpTextures = textures.bumpTexture;
|
|
996
|
-
this.roughnessTextures = textures.roughnessTexture;
|
|
997
|
-
this.metalnessTextures = textures.metalnessTexture;
|
|
998
|
-
this.emissiveTextures = textures.emissiveTexture;
|
|
999
|
-
this.displacementTextures = textures.displacementTexture;
|
|
1092
|
+
// Bucket textures, remap material indices, regenerate raw material data, and
|
|
1093
|
+
// build the consolidated bucket arrays — same path as the initial build.
|
|
1094
|
+
await this._createMaterialTextures();
|
|
1000
1095
|
|
|
1001
1096
|
const duration = performance.now() - startTime;
|
|
1002
1097
|
this._log( `Material rebuild complete (${duration.toFixed( 2 )}ms)`, {
|
|
@@ -1026,37 +1121,7 @@ export class SceneProcessor {
|
|
|
1026
1121
|
*/
|
|
1027
1122
|
_disposeMaterialTextures() {
|
|
1028
1123
|
|
|
1029
|
-
|
|
1030
|
-
'albedoTextures', 'normalTextures',
|
|
1031
|
-
'bumpTextures', 'roughnessTextures', 'metalnessTextures', 'emissiveTextures',
|
|
1032
|
-
'displacementTextures'
|
|
1033
|
-
];
|
|
1034
|
-
|
|
1035
|
-
materialTextureProps.forEach( prop => {
|
|
1036
|
-
|
|
1037
|
-
if ( this[ prop ] ) {
|
|
1038
|
-
|
|
1039
|
-
try {
|
|
1040
|
-
|
|
1041
|
-
if ( typeof this[ prop ].dispose === 'function' ) {
|
|
1042
|
-
|
|
1043
|
-
this[ prop ].dispose();
|
|
1044
|
-
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
} catch ( error ) {
|
|
1048
|
-
|
|
1049
|
-
console.warn( `[SceneProcessor] Error disposing ${prop}:`, error );
|
|
1050
|
-
|
|
1051
|
-
} finally {
|
|
1052
|
-
|
|
1053
|
-
this[ prop ] = null;
|
|
1054
|
-
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
} );
|
|
1124
|
+
this._disposeBucketTextures();
|
|
1060
1125
|
|
|
1061
1126
|
// Clear texture creator cache to prevent stale references
|
|
1062
1127
|
if ( this.textureCreator && this.textureCreator.textureCache ) {
|
|
@@ -1407,14 +1472,12 @@ export class SceneProcessor {
|
|
|
1407
1472
|
}
|
|
1408
1473
|
|
|
1409
1474
|
pathTracer.materialData.setMaterialTextures( {
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
bumpMaps: this.bumpTextures,
|
|
1413
|
-
roughnessMaps: this.roughnessTextures,
|
|
1414
|
-
metalnessMaps: this.metalnessTextures,
|
|
1415
|
-
emissiveMaps: this.emissiveTextures,
|
|
1416
|
-
displacementMaps: this.displacementTextures,
|
|
1475
|
+
srgbBuckets: this.srgbBucketTextures,
|
|
1476
|
+
linearBuckets: this.linearBucketTextures,
|
|
1417
1477
|
} );
|
|
1478
|
+
// Hand the uuid→packed maps to materialData so runtime edits (updateMaterial) can
|
|
1479
|
+
// re-pack a texture's index against this scene's bucket layout.
|
|
1480
|
+
pathTracer.materialData.setTexturePackMaps?.( this._srgbTexPacked, this._linearTexPacked );
|
|
1418
1481
|
|
|
1419
1482
|
if ( this.emissiveTriangleData ) {
|
|
1420
1483
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { texture } from 'three/tsl';
|
|
11
11
|
import { LinearFilter, DataArrayTexture } from 'three';
|
|
12
|
-
import {
|
|
12
|
+
import { setAlphaShadowsUniform } from '../TSL/LightsDirect.js';
|
|
13
13
|
import { setGoboMapsTexture, setIESProfilesTexture } from '../TSL/LightsCore.js';
|
|
14
14
|
|
|
15
15
|
export class ShaderBuilder {
|
|
@@ -30,7 +30,6 @@ export class ShaderBuilder {
|
|
|
30
30
|
const nodes = this._sceneTextureNodes;
|
|
31
31
|
|
|
32
32
|
const env = stage.environment;
|
|
33
|
-
const mat = stage.materialData;
|
|
34
33
|
|
|
35
34
|
if ( env.environmentTexture && nodes.envTex ) {
|
|
36
35
|
|
|
@@ -38,13 +37,8 @@ export class ShaderBuilder {
|
|
|
38
37
|
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if ( mat.bumpMaps && nodes.bumpMapsTex ) nodes.bumpMapsTex.value = mat.bumpMaps;
|
|
44
|
-
if ( mat.metalnessMaps && nodes.metalnessMapsTex ) nodes.metalnessMapsTex.value = mat.metalnessMaps;
|
|
45
|
-
if ( mat.roughnessMaps && nodes.roughnessMapsTex ) nodes.roughnessMapsTex.value = mat.roughnessMaps;
|
|
46
|
-
if ( mat.emissiveMaps && nodes.emissiveMapsTex ) nodes.emissiveMapsTex.value = mat.emissiveMaps;
|
|
47
|
-
if ( mat.displacementMaps && nodes.displacementMapsTex ) nodes.displacementMapsTex.value = mat.displacementMaps;
|
|
40
|
+
// Material bucket arrays are owned by PathTracer's independent wavefront nodes
|
|
41
|
+
// (_refreshWfTextureNodes); nothing to swap here.
|
|
48
42
|
if ( stage.goboMaps && nodes.goboMapsTex ) nodes.goboMapsTex.value = stage.goboMaps;
|
|
49
43
|
if ( stage.iesProfiles && nodes.iesProfilesTex ) nodes.iesProfilesTex.value = stage.iesProfiles;
|
|
50
44
|
|
|
@@ -116,14 +110,9 @@ export class ShaderBuilder {
|
|
|
116
110
|
|
|
117
111
|
};
|
|
118
112
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const bumpMapsTex = mat.bumpMaps ? texture( mat.bumpMaps ) : createArrayPlaceholder();
|
|
123
|
-
const metalnessMapsTex = mat.metalnessMaps ? texture( mat.metalnessMaps ) : createArrayPlaceholder();
|
|
124
|
-
const roughnessMapsTex = mat.roughnessMaps ? texture( mat.roughnessMaps ) : createArrayPlaceholder();
|
|
125
|
-
const emissiveMapsTex = mat.emissiveMaps ? texture( mat.emissiveMaps ) : createArrayPlaceholder();
|
|
126
|
-
const displacementMapsTex = mat.displacementMaps ? texture( mat.displacementMaps ) : createArrayPlaceholder();
|
|
113
|
+
// Material map arrays (consolidated size buckets) are owned by PathTracer's
|
|
114
|
+
// independent wavefront nodes + setMaterialBucketTextures/setShadowAlbedoMaps —
|
|
115
|
+
// see PathTracer._buildWavefrontKernels. Nothing material-map related is bound here.
|
|
127
116
|
|
|
128
117
|
// Spot light gobo array — placeholder until GoboManager populates it.
|
|
129
118
|
const goboMapsTex = stage.goboMaps ? texture( stage.goboMaps ) : createArrayPlaceholder();
|
|
@@ -133,16 +122,9 @@ export class ShaderBuilder {
|
|
|
133
122
|
const iesProfilesTex = stage.iesProfiles ? texture( stage.iesProfiles ) : createArrayPlaceholder();
|
|
134
123
|
setIESProfilesTexture( iesProfilesTex );
|
|
135
124
|
|
|
136
|
-
// Set albedo texture array for alpha-aware shadow rays (module-level in LightsDirect.js).
|
|
137
|
-
// Always pass the texture node (real or placeholder) so alpha-cutout code is emitted
|
|
138
|
-
// into the shader at graph construction time. Runtime albedoMapIndex >= 0 guards sampling.
|
|
139
|
-
setShadowAlbedoMaps( albedoMapsTex );
|
|
140
|
-
|
|
141
125
|
const result = {
|
|
142
126
|
triStorage, bvhStorage, matStorage, lightBufferStorage,
|
|
143
127
|
envTex,
|
|
144
|
-
albedoMapsTex, normalMapsTex, bumpMapsTex,
|
|
145
|
-
metalnessMapsTex, roughnessMapsTex, emissiveMapsTex, displacementMapsTex,
|
|
146
128
|
goboMapsTex, iesProfilesTex,
|
|
147
129
|
};
|
|
148
130
|
|
|
@@ -537,9 +537,6 @@ export class TextureCreator {
|
|
|
537
537
|
case 'worker-direct':
|
|
538
538
|
result = await this.processWithWorkerDirect( normalized );
|
|
539
539
|
break;
|
|
540
|
-
case 'worker-chunked':
|
|
541
|
-
result = await this.processWithWorkerChunked( normalized, strategy.chunkSize );
|
|
542
|
-
break;
|
|
543
540
|
case 'main-batch':
|
|
544
541
|
result = await this.processOnMainThreadBatch( normalized, strategy.batchSize );
|
|
545
542
|
break;
|
|
@@ -587,10 +584,10 @@ export class TextureCreator {
|
|
|
587
584
|
|
|
588
585
|
if ( this.capabilities.workers && estimatedMemory > MEMORY_CONSTANTS.MAX_TEXTURE_MEMORY ) {
|
|
589
586
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
};
|
|
587
|
+
// Very large texture set: stream on the main thread (GC-yielding, builds the
|
|
588
|
+
// full array correctly). The former 'worker-chunked' path combined its chunks
|
|
589
|
+
// by returning only the first, silently dropping the rest — removed.
|
|
590
|
+
return { method: 'main-streaming' };
|
|
594
591
|
|
|
595
592
|
} else if ( this.capabilities.workers && totalPixels > 2097152 ) {
|
|
596
593
|
|
|
@@ -710,8 +707,18 @@ export class TextureCreator {
|
|
|
710
707
|
|
|
711
708
|
try {
|
|
712
709
|
|
|
713
|
-
// Option 1: Direct ImageBitmap transfer (when supported)
|
|
714
|
-
|
|
710
|
+
// Option 1: Direct ImageBitmap transfer (when supported). Covers HTMLImageElement
|
|
711
|
+
// AND ImageBitmap (what GLTFLoader's ImageBitmapLoader produces) and canvases — the
|
|
712
|
+
// worker extracts pixels on its OffscreenCanvas, so this keeps the full-res
|
|
713
|
+
// getImageData off the main thread (Option 2 blocks it per texture).
|
|
714
|
+
const img = texture.image;
|
|
715
|
+
const canDirect = typeof createImageBitmap !== 'undefined' && (
|
|
716
|
+
img instanceof HTMLImageElement
|
|
717
|
+
|| ( typeof ImageBitmap !== 'undefined' && img instanceof ImageBitmap )
|
|
718
|
+
|| ( typeof HTMLCanvasElement !== 'undefined' && img instanceof HTMLCanvasElement )
|
|
719
|
+
|| ( typeof OffscreenCanvas !== 'undefined' && img instanceof OffscreenCanvas )
|
|
720
|
+
);
|
|
721
|
+
if ( canDirect ) {
|
|
715
722
|
|
|
716
723
|
const bitmap = await createImageBitmap( texture.image, {
|
|
717
724
|
imageOrientation: flipY ? 'flipY' : 'none',
|
|
@@ -760,21 +767,6 @@ export class TextureCreator {
|
|
|
760
767
|
|
|
761
768
|
}
|
|
762
769
|
|
|
763
|
-
async processWithWorkerChunked( textures, chunkSize ) {
|
|
764
|
-
|
|
765
|
-
const results = [];
|
|
766
|
-
for ( let i = 0; i < textures.length; i += chunkSize ) {
|
|
767
|
-
|
|
768
|
-
const chunk = textures.slice( i, i + chunkSize );
|
|
769
|
-
const chunkResult = await this.processWithWorkerDirect( chunk );
|
|
770
|
-
results.push( chunkResult );
|
|
771
|
-
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
return this.combineTextureResults( results );
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
|
|
778
770
|
async processOnMainThreadBatch( textures, batchSize ) {
|
|
779
771
|
|
|
780
772
|
const validTextures = textures.filter( tex => tex?.image );
|
|
@@ -1451,14 +1443,6 @@ export class TextureCreator {
|
|
|
1451
1443
|
|
|
1452
1444
|
}
|
|
1453
1445
|
|
|
1454
|
-
combineTextureResults( results ) {
|
|
1455
|
-
|
|
1456
|
-
// Combine multiple texture array results into one
|
|
1457
|
-
// This is a simplified implementation - you may need more sophisticated merging
|
|
1458
|
-
return results[ 0 ]; // For now, return first result
|
|
1459
|
-
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
1446
|
dispose() {
|
|
1463
1447
|
|
|
1464
1448
|
this.canvasPool.dispose();
|
|
@@ -184,8 +184,13 @@ function handleAssemble( data ) {
|
|
|
184
184
|
|
|
185
185
|
function handleFullBuild( data ) {
|
|
186
186
|
|
|
187
|
-
const { triangleData, triangleByteOffset, triangleByteLength, depth, reportProgress, treeletOptimization, reinsertionOptimization, sharedReorderBuffer } = data;
|
|
187
|
+
const { triangleData, triangleByteOffset, triangleByteLength, depth, reportProgress, treeletOptimization, reinsertionOptimization, sharedReorderBuffer, maxLeafSize, numBins, maxBins, minBins } = data;
|
|
188
188
|
const builder = new BVHBuilder();
|
|
189
|
+
// Honor the build params forwarded from SceneProcessor (previously ignored → default leaf 8).
|
|
190
|
+
if ( maxLeafSize !== undefined ) builder.maxLeafSize = maxLeafSize;
|
|
191
|
+
if ( numBins !== undefined ) builder.numBins = numBins;
|
|
192
|
+
if ( maxBins !== undefined ) builder.maxBins = maxBins;
|
|
193
|
+
if ( minBins !== undefined ) builder.minBins = minBins;
|
|
189
194
|
|
|
190
195
|
try {
|
|
191
196
|
|
package/src/Stages/EdgeFilter.js
CHANGED
|
@@ -105,10 +105,11 @@ export class EdgeFilter extends RenderStage {
|
|
|
105
105
|
const center = textureLoad( inputTex, coord ).xyz;
|
|
106
106
|
const centerLum = dot( center, REC709_LUMINANCE_COEFFICIENTS );
|
|
107
107
|
|
|
108
|
-
// NormalDepth writes (0,0,0,
|
|
108
|
+
// NormalDepth writes (0,0,0, 65504) for miss rays. Decoded normal
|
|
109
109
|
// (-1,-1,-1) is non-unit and explodes pow(dot, phi); use the depth
|
|
110
|
-
// sentinel as a 0/1 hit flag and zero out cross-kind weights.
|
|
111
|
-
|
|
110
|
+
// sentinel as a 0/1 hit flag and zero out cross-kind weights. Threshold
|
|
111
|
+
// sits below the 65504 sentinel (and above any real depth).
|
|
112
|
+
const MISS_THRESHOLD = 6e4;
|
|
112
113
|
const centerND = textureLoad( ndTex, coord );
|
|
113
114
|
const centerNormal = centerND.xyz.mul( 2.0 ).sub( 1.0 );
|
|
114
115
|
const centerDepth = centerND.w;
|
|
@@ -172,8 +172,8 @@ export class MotionVector extends RenderStage {
|
|
|
172
172
|
|
|
173
173
|
const result = vec4( 0.0, 0.0, linearDepth, 1.0 ).toVar();
|
|
174
174
|
|
|
175
|
-
// Sky / background (depth >=
|
|
176
|
-
If( linearDepth.lessThan( float(
|
|
175
|
+
// Sky / background (depth >= 65504 sentinel) — no motion
|
|
176
|
+
If( linearDepth.lessThan( float( 6e4 ) ), () => {
|
|
177
177
|
|
|
178
178
|
// Pixel coordinate → NDC
|
|
179
179
|
// Negate Y to match PathTracer convention
|
|
@@ -275,8 +275,8 @@ export class MotionVector extends RenderStage {
|
|
|
275
275
|
|
|
276
276
|
const result = vec4( 0.0, 0.0, 0.0, 0.0 ).toVar();
|
|
277
277
|
|
|
278
|
-
// Skip first frame and sky
|
|
279
|
-
If( isFirstFrameU.lessThan( 0.5 ).and( linearDepth.lessThan( float(
|
|
278
|
+
// Skip first frame and sky (depth >= 65504 sentinel)
|
|
279
|
+
If( isFirstFrameU.lessThan( 0.5 ).and( linearDepth.lessThan( float( 6e4 ) ) ), () => {
|
|
280
280
|
|
|
281
281
|
// Pixel coordinate → NDC
|
|
282
282
|
// Negate Y to match PathTracer convention
|