rayzee 9.4.2 → 9.5.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 +223 -21
- package/dist/ActiveColor-YvuQq44O.js +13 -0
- package/dist/ArchiveImporter-xuUJiklP.js +4301 -0
- package/dist/AssetConfig-DSEntE65.js +30 -0
- package/dist/BidirectionalIntegrator-C5PKjJoT.js +934 -0
- package/dist/ColorManagement-CheBCPaW.js +1488 -0
- package/dist/EngineDefaults-DH3bI5t-.js +844 -0
- package/dist/EngineEvents-Ci8dVWCP.js +73 -0
- package/dist/EngineIssues-CIZnXHsF.js +72 -0
- package/dist/FileFormats-sPGJeCRc.js +102 -0
- package/dist/Logger-BnHghprG.js +97 -0
- package/dist/{NeuralRetouch-vkdXXyK2.js → NeuralRetouch-CW11yLZ_.js} +8 -6
- package/dist/{NeuralSuperRes-FVqRJKQV.js → NeuralSuperRes-BekaecYg.js} +55 -120
- package/dist/PathTracer-Ccl9KOuF.js +29729 -0
- package/dist/PhysicalSky-Dv2PMFGW.js +1219 -0
- package/dist/RayzeeRenderer-BQxnzCTD.js +3542 -0
- package/dist/SolarLimb-ken-JbDK.js +721 -0
- package/dist/ToneMapGPU-BHi5JzIq.js +177 -0
- package/dist/ViewTransforms-D0rTLBsX.js +255 -0
- package/dist/WorkingMatrix-C6y233hT.js +27 -0
- package/dist/ZipReader-gDSWr0I5.js +98 -0
- package/dist/addons/archives.es.js +3 -0
- package/dist/addons/bidirectional.es.js +2 -0
- package/dist/addons/color.es.js +3 -0
- package/dist/addons/formats.es.js +2 -0
- package/dist/addons/physical-sky.es.js +2 -0
- package/dist/addons/storage.es.js +3 -0
- package/dist/archiveFormats-BZw7TiDp.js +75 -0
- package/dist/identity-DrQsGT2o.js +39 -0
- package/dist/openStorage-DwcBRUj7.js +820 -0
- package/dist/rayzee-core.es.js +12 -0
- package/dist/rayzee.es.js +2266 -44079
- package/dist/rayzee.umd.js +485 -473
- package/dist/sceneCachePolicy-BmwYOYDu.js +183 -0
- package/dist/shared-BGBcSxBQ.js +17 -0
- package/package.json +23 -2
- package/src/Color/ActiveColor.js +34 -0
- package/src/Color/BasicColor.js +147 -0
- package/src/Color/ColorManagement.js +7 -31
- package/src/EngineDefaults.js +22 -8
- package/src/EngineEvents.js +2 -0
- package/src/EngineIssues.js +1 -0
- package/src/PathTracerApp.js +617 -4016
- package/src/Pipeline/PipelineContext.js +0 -4
- package/src/Platform.js +36 -0
- package/src/Processor/ArchiveCache.js +1 -1
- package/src/Processor/ArchiveImporter.js +1259 -0
- package/src/Processor/AssetLoader.js +322 -1746
- package/src/Processor/AtmosphereModel.js +1 -2
- package/src/Processor/BVHBuilder.js +4 -95
- package/src/Processor/EnvironmentExactTable.js +187 -0
- package/src/Processor/EquirectHDRInfo.js +30 -223
- package/src/Processor/FileFormats.js +116 -0
- package/src/Processor/GLTFDecoders.js +85 -0
- package/src/Processor/GLTFDiffuseTransmission.js +63 -0
- package/src/Processor/GeometryExtractor.js +12 -1
- package/src/Processor/IESParser.js +47 -35
- package/src/Processor/KernelManager.js +35 -2
- package/src/Processor/MaterialPacking.js +8 -7
- package/src/Processor/PBRT/PBRTMaterials.js +129 -41
- package/src/Processor/PBRT/PBRTParser.js +30 -17
- package/src/Processor/PBRT/PBRTSceneBuilder.js +548 -37
- package/src/Processor/PBRT/PBRTTextureBake.js +154 -0
- package/src/Processor/PBRT/PFM.js +59 -0
- package/src/Processor/PackedRayBuffer.js +116 -9
- package/src/Processor/ParallelBVHBuilder.js +3 -6
- package/src/Processor/PhysicalSky.js +5 -4
- package/src/Processor/PlatformImageLoader.js +50 -6
- package/src/Processor/QueueManager.js +12 -3
- package/src/Processor/ReinsertionOptimizer.js +2 -2
- package/src/Processor/SceneProcessor.js +15 -55
- package/src/Processor/ShaderBuilder.js +6 -16
- package/src/Processor/SolarLimb.js +3 -0
- package/src/Processor/TextureCreator.js +1 -1
- package/src/Processor/Workers/BVHSubtreeWorker.js +1 -34
- package/src/Processor/Workers/BVHWorker.js +5 -18
- package/src/Processor/Workers/CDFWorker.js +6 -183
- package/src/Processor/archiveFormats.js +7 -0
- package/src/Processor/utils.js +2 -1
- package/src/RayzeeRenderer.js +3902 -0
- package/src/RenderSettings.js +49 -41
- package/src/Stages/ASVGF.js +5 -7
- package/src/Stages/AutoExposure.js +3 -12
- package/src/Stages/Compositor.js +8 -23
- package/src/Stages/NRD.js +9 -2
- package/src/Stages/NormalDepth.js +9 -6
- package/src/Stages/PathTracer.js +254 -38
- package/src/Stages/PathTracerStage.js +11 -16
- package/src/Storage/BLASCache.js +1 -1
- package/src/Storage/CDFCache.js +18 -17
- package/src/Storage/DownloadCache.js +1 -1
- package/src/Storage/SceneGraphCodec.js +46 -3
- package/src/Storage/SpillStore.js +1 -1
- package/src/Storage/StorageManager.js +2 -4
- package/src/Storage/areas.js +4 -0
- package/src/TSL/BVHTraversal.js +62 -24
- package/src/TSL/Bidirectional.js +204 -0
- package/src/TSL/BidirectionalLamps.js +132 -0
- package/src/TSL/Clearcoat.js +15 -6
- package/src/TSL/Common.js +19 -14
- package/src/TSL/ConnectKernel.js +147 -0
- package/src/TSL/Debugger.js +1 -1
- package/src/TSL/Displacement.js +4 -3
- package/src/TSL/EmissiveSampling.js +64 -17
- package/src/TSL/Environment.js +77 -106
- package/src/TSL/EnvironmentCDF.js +85 -39
- package/src/TSL/ExtendKernel.js +8 -3
- package/src/TSL/FinalWriteKernel.js +4 -4
- package/src/TSL/GenerateKernel.js +18 -4
- package/src/TSL/HitFacet.js +35 -5
- package/src/TSL/LightBVHSampling.js +40 -9
- package/src/TSL/LightGenerateKernel.js +293 -0
- package/src/TSL/LightGuide.js +198 -0
- package/src/TSL/LightSplatKernel.js +165 -0
- package/src/TSL/LightsCore.js +13 -38
- package/src/TSL/LightsDirect.js +28 -29
- package/src/TSL/LightsIndirect.js +3 -1
- package/src/TSL/LightsSampling.js +90 -38
- package/src/TSL/MaterialEvaluation.js +113 -31
- package/src/TSL/MaterialProperties.js +44 -17
- package/src/TSL/MaterialTransmission.js +52 -47
- package/src/TSL/MergeKernel.js +218 -0
- package/src/TSL/PathTracerCore.js +65 -29
- package/src/TSL/Random.js +4 -0
- package/src/TSL/SceneResources.js +51 -0
- package/src/TSL/ShadeKernel.js +881 -103
- package/src/TSL/Struct.js +10 -0
- package/src/TSL/Sun.js +1 -1
- package/src/TSL/TextureSampling.js +65 -60
- package/src/addons/archives.js +14 -0
- package/src/addons/bidirectional.js +13 -0
- package/src/addons/color.js +32 -0
- package/src/addons/formats.js +16 -0
- package/src/addons/physicalSky.js +14 -0
- package/src/addons/storage.js +19 -0
- package/src/core.js +35 -0
- package/src/index.js +3 -1
- package/src/integrators/BidirectionalIntegrator.js +832 -0
- package/src/managers/EnvironmentManager.js +85 -33
- package/src/managers/MaterialDataManager.js +42 -0
- package/src/managers/UniformManager.js +0 -1
- package/dist/ToneMapGPU-DKQM1pMd.js +0 -552
- package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
- package/src/Processor/TreeletOptimizer.js +0 -574
|
@@ -116,14 +116,6 @@ export class SceneProcessor {
|
|
|
116
116
|
enableTextureCache: true,
|
|
117
117
|
maxConcurrentTextureTasks: Math.min( hardwareThreads(), 6 ),
|
|
118
118
|
maxSceneBytes: MAX_SCENE_BYTES,
|
|
119
|
-
// Treelet optimization configuration
|
|
120
|
-
// Keep: `_buildBVH` sends `enabled: value !== false`, so undefined re-enables treelets.
|
|
121
|
-
enableTreeletOptimization: false,
|
|
122
|
-
treeletSize: 7, // 7 nodes gives 315 topologies for optimal enumeration
|
|
123
|
-
treeletOptimizationPasses: 1,
|
|
124
|
-
treeletMinImprovement: 0.01, // Minimum SAH improvement threshold
|
|
125
|
-
// Above this triangle count the builder drops treelets to size 3.
|
|
126
|
-
treeletComplexityThreshold: 50000,
|
|
127
119
|
// Store the per-mesh BVHs of a scene whose build took at least this long (needs a sceneKey).
|
|
128
120
|
sceneCache: true,
|
|
129
121
|
sceneCacheMinBuildMs: SCENE_CACHE_MIN_BUILD_MS,
|
|
@@ -152,6 +144,8 @@ export class SceneProcessor {
|
|
|
152
144
|
this.iridescenceThicknessMaps = [];
|
|
153
145
|
this.specularIntensityMaps = [];
|
|
154
146
|
this.specularColorMaps = [];
|
|
147
|
+
this.diffuseTransmissionMaps = [];
|
|
148
|
+
this.diffuseTransmissionColorMaps = [];
|
|
155
149
|
this.directionalLights = [];
|
|
156
150
|
this.cameras = [];
|
|
157
151
|
this.spheres = [];
|
|
@@ -235,15 +229,6 @@ export class SceneProcessor {
|
|
|
235
229
|
this.bvhBuilder = new BVHBuilder();
|
|
236
230
|
this.bvhBuilder.maxLeafSize = this.config.maxLeafSize;
|
|
237
231
|
|
|
238
|
-
// Configure treelet optimization
|
|
239
|
-
this.bvhBuilder.setTreeletConfig( {
|
|
240
|
-
enabled: this.config.enableTreeletOptimization,
|
|
241
|
-
size: this.config.treeletSize,
|
|
242
|
-
passes: this.config.treeletOptimizationPasses,
|
|
243
|
-
minImprovement: this.config.treeletMinImprovement,
|
|
244
|
-
complexityThreshold: this.config.treeletComplexityThreshold
|
|
245
|
-
} );
|
|
246
|
-
|
|
247
232
|
// Create and configure texture creator
|
|
248
233
|
this.textureCreator = new TextureCreator( { maxTextureSize: this.config.maxTextureSize, issues: this.config.issues } );
|
|
249
234
|
// The optimized TextureCreator will auto-detect capabilities and select optimal methods
|
|
@@ -877,6 +862,8 @@ export class SceneProcessor {
|
|
|
877
862
|
this.iridescenceThicknessMaps = extractedData.iridescenceThicknessMaps;
|
|
878
863
|
this.specularIntensityMaps = extractedData.specularIntensityMaps;
|
|
879
864
|
this.specularColorMaps = extractedData.specularColorMaps;
|
|
865
|
+
this.diffuseTransmissionMaps = extractedData.diffuseTransmissionMaps ?? [];
|
|
866
|
+
this.diffuseTransmissionColorMaps = extractedData.diffuseTransmissionColorMaps ?? [];
|
|
880
867
|
this.directionalLights = extractedData.directionalLights;
|
|
881
868
|
this.cameras = extractedData.cameras;
|
|
882
869
|
|
|
@@ -1032,7 +1019,7 @@ export class SceneProcessor {
|
|
|
1032
1019
|
}
|
|
1033
1020
|
|
|
1034
1021
|
// Store all results, summing per-mesh split stats for one aggregate BVH line
|
|
1035
|
-
const blasStats = { sah: 0, objMed: 0, spatMed: 0, failed: 0
|
|
1022
|
+
const blasStats = { sah: 0, objMed: 0, spatMed: 0, failed: 0 };
|
|
1036
1023
|
|
|
1037
1024
|
for ( const { m, range, result } of [ ...poolResults, ...parallelResults ] ) {
|
|
1038
1025
|
|
|
@@ -1043,8 +1030,6 @@ export class SceneProcessor {
|
|
|
1043
1030
|
blasStats.objMed += st.objectMedianSplits ?? 0;
|
|
1044
1031
|
blasStats.spatMed += st.spatialMedianSplits ?? 0;
|
|
1045
1032
|
blasStats.failed += st.failedSplits ?? 0;
|
|
1046
|
-
blasStats.treeletsImproved += st.treeletsImproved ?? 0;
|
|
1047
|
-
blasStats.treeletsProcessed += st.treeletsProcessed ?? 0;
|
|
1048
1033
|
this.performanceMetrics.blasWorkerTime += st.totalBuildTime ?? 0;
|
|
1049
1034
|
|
|
1050
1035
|
}
|
|
@@ -1190,7 +1175,6 @@ export class SceneProcessor {
|
|
|
1190
1175
|
`${fmt.n( table.setCount )} BLASes + TLAS`,
|
|
1191
1176
|
`${fmt.n( this.bvh.recordCount )} nodes`,
|
|
1192
1177
|
`SAH ${fmt.n( blasStats.sah )} · objMed ${blasStats.objMed} · spatMed ${blasStats.spatMed} · failed ${blasStats.failed}`,
|
|
1193
|
-
blasStats.treeletsProcessed ? `treelets ${blasStats.treeletsImproved}/${blasStats.treeletsProcessed} improved` : null,
|
|
1194
1178
|
fmt.ms( duration ),
|
|
1195
1179
|
] ) );
|
|
1196
1180
|
|
|
@@ -1218,13 +1202,6 @@ export class SceneProcessor {
|
|
|
1218
1202
|
|
|
1219
1203
|
return {
|
|
1220
1204
|
depth: this.config.bvhDepth,
|
|
1221
|
-
treeletOptimization: {
|
|
1222
|
-
enabled: this.config.enableTreeletOptimization !== false,
|
|
1223
|
-
size: this.config.treeletSize,
|
|
1224
|
-
passes: this.config.treeletOptimizationPasses,
|
|
1225
|
-
minImprovement: this.config.treeletMinImprovement,
|
|
1226
|
-
complexityThreshold: this.config.treeletComplexityThreshold
|
|
1227
|
-
},
|
|
1228
1205
|
reinsertionOptimization: {
|
|
1229
1206
|
enabled: this.bvhBuilder.enableReinsertionOptimization,
|
|
1230
1207
|
batchSizeRatio: this.bvhBuilder.reinsertionBatchSizeRatio,
|
|
@@ -1702,7 +1679,7 @@ export class SceneProcessor {
|
|
|
1702
1679
|
* Each mesh is dispatched to an available BVHWorker; at most poolSize workers run concurrently.
|
|
1703
1680
|
*
|
|
1704
1681
|
* @param {Array<{m: number, range: {start: number, count: number}}>} tasks
|
|
1705
|
-
* @param {Object} opts - Worker build options (depth,
|
|
1682
|
+
* @param {Object} opts - Worker build options (depth, reinsertionOptimization)
|
|
1706
1683
|
* @param {Function} onProgress - Called with (completedCount) as builds finish
|
|
1707
1684
|
* @returns {Promise<Array<{m, range, result}>>}
|
|
1708
1685
|
* @private
|
|
@@ -1766,11 +1743,7 @@ export class SceneProcessor {
|
|
|
1766
1743
|
|
|
1767
1744
|
const meshTriData = this.triangles.copyOf( range.start, range.count );
|
|
1768
1745
|
|
|
1769
|
-
// Disable treelet for tiny meshes
|
|
1770
1746
|
const triCount = range.count;
|
|
1771
|
-
const treeletOpts = triCount <= 500
|
|
1772
|
-
? { ...opts.treeletOptimization, enabled: false }
|
|
1773
|
-
: opts.treeletOptimization;
|
|
1774
1747
|
|
|
1775
1748
|
worker._currentTask = { m, range };
|
|
1776
1749
|
worker.postMessage( {
|
|
@@ -1781,7 +1754,6 @@ export class SceneProcessor {
|
|
|
1781
1754
|
depth: opts.depth,
|
|
1782
1755
|
reportProgress: false,
|
|
1783
1756
|
sharedReorderBuffer: null,
|
|
1784
|
-
treeletOptimization: treeletOpts,
|
|
1785
1757
|
reinsertionOptimization: opts.reinsertionOptimization,
|
|
1786
1758
|
maxLeafSize: opts.maxLeafSize,
|
|
1787
1759
|
foldLeaves: opts.foldLeaves,
|
|
@@ -1824,7 +1796,7 @@ export class SceneProcessor {
|
|
|
1824
1796
|
const result = {
|
|
1825
1797
|
bvhData: data.bvhData,
|
|
1826
1798
|
originalToBvh: data.originalToBvh || null,
|
|
1827
|
-
splitStats: data.
|
|
1799
|
+
splitStats: data.splitStats || null,
|
|
1828
1800
|
};
|
|
1829
1801
|
onResult?.( m, range, result );
|
|
1830
1802
|
results.push( { m, range, result } );
|
|
@@ -2041,11 +2013,12 @@ export class SceneProcessor {
|
|
|
2041
2013
|
|
|
2042
2014
|
};
|
|
2043
2015
|
|
|
2044
|
-
const srgbTypes = [ this.maps, this.emissiveMaps, this.sheenColorMaps, this.specularColorMaps ];
|
|
2016
|
+
const srgbTypes = [ this.maps, this.emissiveMaps, this.sheenColorMaps, this.specularColorMaps, this.diffuseTransmissionColorMaps ];
|
|
2045
2017
|
const linearTypes = [
|
|
2046
2018
|
this.normalMaps, this.bumpMaps, this.roughnessMaps, this.metalnessMaps, this.displacementMaps,
|
|
2047
2019
|
this.anisotropyMaps, this.transmissionMaps, this.clearcoatMaps, this.clearcoatRoughnessMaps,
|
|
2048
2020
|
this.sheenRoughnessMaps, this.iridescenceMaps, this.iridescenceThicknessMaps, this.specularIntensityMaps,
|
|
2021
|
+
this.diffuseTransmissionMaps,
|
|
2049
2022
|
];
|
|
2050
2023
|
|
|
2051
2024
|
const srgbShapes = planTextureBuckets( poolSizes( srgbTypes ), cap, K );
|
|
@@ -2136,6 +2109,8 @@ export class SceneProcessor {
|
|
|
2136
2109
|
iridescenceThickness: remapType( this.iridescenceThicknessMaps, linearLists, linearDedup, this._linearTexPacked, linearShapes ),
|
|
2137
2110
|
specularIntensity: remapType( this.specularIntensityMaps, linearLists, linearDedup, this._linearTexPacked, linearShapes ),
|
|
2138
2111
|
specularColor: remapType( this.specularColorMaps, srgbLists, srgbDedup, this._srgbTexPacked, srgbShapes ),
|
|
2112
|
+
diffuseTransmission: remapType( this.diffuseTransmissionMaps, linearLists, linearDedup, this._linearTexPacked, linearShapes ),
|
|
2113
|
+
diffuseTransmissionColor: remapType( this.diffuseTransmissionColorMaps, srgbLists, srgbDedup, this._srgbTexPacked, srgbShapes ),
|
|
2139
2114
|
};
|
|
2140
2115
|
|
|
2141
2116
|
return { srgbLists, linearLists, remap };
|
|
@@ -2170,6 +2145,8 @@ export class SceneProcessor {
|
|
|
2170
2145
|
mat.iridescenceThicknessMap = fix( mat.iridescenceThicknessMap, remap.iridescenceThickness );
|
|
2171
2146
|
mat.specularIntensityMap = fix( mat.specularIntensityMap, remap.specularIntensity );
|
|
2172
2147
|
mat.specularColorMap = fix( mat.specularColorMap, remap.specularColor );
|
|
2148
|
+
mat.diffuseTransmissionMap = fix( mat.diffuseTransmissionMap, remap.diffuseTransmission );
|
|
2149
|
+
mat.diffuseTransmissionColorMap = fix( mat.diffuseTransmissionColorMap, remap.diffuseTransmissionColor );
|
|
2173
2150
|
|
|
2174
2151
|
}
|
|
2175
2152
|
|
|
@@ -2265,6 +2242,8 @@ export class SceneProcessor {
|
|
|
2265
2242
|
this.iridescenceThicknessMaps = [];
|
|
2266
2243
|
this.specularIntensityMaps = [];
|
|
2267
2244
|
this.specularColorMaps = [];
|
|
2245
|
+
this.diffuseTransmissionMaps = [];
|
|
2246
|
+
this.diffuseTransmissionColorMaps = [];
|
|
2268
2247
|
this.directionalLights = [];
|
|
2269
2248
|
this.cameras = [];
|
|
2270
2249
|
this.spheres = [];
|
|
@@ -2477,15 +2456,6 @@ export class SceneProcessor {
|
|
|
2477
2456
|
|
|
2478
2457
|
this.bvhBuilder.maxLeafSize = this.config.maxLeafSize;
|
|
2479
2458
|
|
|
2480
|
-
// Update treelet optimization configuration
|
|
2481
|
-
this.bvhBuilder.setTreeletConfig( {
|
|
2482
|
-
enabled: this.config.enableTreeletOptimization,
|
|
2483
|
-
size: this.config.treeletSize,
|
|
2484
|
-
passes: this.config.treeletOptimizationPasses,
|
|
2485
|
-
minImprovement: this.config.treeletMinImprovement,
|
|
2486
|
-
complexityThreshold: this.config.treeletComplexityThreshold
|
|
2487
|
-
} );
|
|
2488
|
-
|
|
2489
2459
|
}
|
|
2490
2460
|
|
|
2491
2461
|
// Note: TextureCreator auto-configures based on capabilities
|
|
@@ -3688,9 +3658,6 @@ export class SceneProcessor {
|
|
|
3688
3658
|
|
|
3689
3659
|
};
|
|
3690
3660
|
|
|
3691
|
-
// Disable treelet for tiny meshes
|
|
3692
|
-
const treeletEnabled = entry.triCount > 500;
|
|
3693
|
-
|
|
3694
3661
|
worker.postMessage( {
|
|
3695
3662
|
triangleData: meshTriData.buffer,
|
|
3696
3663
|
triangleByteOffset: meshTriData.byteOffset,
|
|
@@ -3706,13 +3673,6 @@ export class SceneProcessor {
|
|
|
3706
3673
|
minBins: this.bvhBuilder.minBins,
|
|
3707
3674
|
reportProgress: false,
|
|
3708
3675
|
sharedReorderBuffer: null,
|
|
3709
|
-
treeletOptimization: {
|
|
3710
|
-
enabled: treeletEnabled,
|
|
3711
|
-
size: this.config.treeletSize,
|
|
3712
|
-
passes: this.config.treeletOptimizationPasses,
|
|
3713
|
-
minImprovement: this.config.treeletMinImprovement,
|
|
3714
|
-
complexityThreshold: this.config.treeletComplexityThreshold
|
|
3715
|
-
},
|
|
3716
3676
|
reinsertionOptimization: {
|
|
3717
3677
|
enabled: this.bvhBuilder.enableReinsertionOptimization,
|
|
3718
3678
|
batchSizeRatio: this.bvhBuilder.reinsertionBatchSizeRatio,
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ShaderBuilder.js — shared scene texture-node factory for the path tracer.
|
|
3
3
|
*
|
|
4
|
-
* Creates the texture/storage nodes the wavefront kernels read (environment,
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* .value mutation to preserve compiled shader-graph references.
|
|
4
|
+
* Creates the texture/storage nodes the wavefront kernels read (environment, previous-frame MRT,
|
|
5
|
+
* adaptive-sampling, gobo/IES). Nodes are created once and updated in-place via .value mutation to
|
|
6
|
+
* preserve compiled shader-graph references.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import { texture } from 'three/tsl';
|
|
11
10
|
import { LinearFilter, DataArrayTexture } from 'three';
|
|
12
|
-
import { setAlphaShadowsUniform } from '../TSL/LightsDirect.js';
|
|
13
|
-
import { setGoboMapsTexture, setIESProfilesTexture } from '../TSL/LightsCore.js';
|
|
14
11
|
import { createLogger } from '../utils/Logger.js';
|
|
15
12
|
|
|
16
13
|
const log = createLogger( 'shader' );
|
|
@@ -81,8 +78,7 @@ export class ShaderBuilder {
|
|
|
81
78
|
|
|
82
79
|
}
|
|
83
80
|
|
|
84
|
-
// Creates the shared scene texture nodes (env,
|
|
85
|
-
// + configures the module-level shadow/alpha/gobo/IES shader state read by the wavefront kernels.
|
|
81
|
+
// Creates the shared scene texture nodes (env, prev-frame, adaptive, gobo, IES).
|
|
86
82
|
// Call from setupMaterial before the kernels are built.
|
|
87
83
|
createSceneTextureNodes( stage, storageTextures ) {
|
|
88
84
|
|
|
@@ -93,9 +89,6 @@ export class ShaderBuilder {
|
|
|
93
89
|
// TSL params; emissive reads offset by stage.emissiveVec4Offset.
|
|
94
90
|
const lightBufferStorage = stage.lightStorageNode;
|
|
95
91
|
|
|
96
|
-
// Set alpha-shadow uniform (module-level in LightsDirect.js, read at runtime)
|
|
97
|
-
setAlphaShadowsUniform( stage.uniforms.get( 'enableAlphaShadows' ) );
|
|
98
|
-
|
|
99
92
|
const envTex = texture( stage.environment.environmentTexture );
|
|
100
93
|
|
|
101
94
|
// Previous-frame texture nodes — initialized from readTarget textures
|
|
@@ -115,17 +108,14 @@ export class ShaderBuilder {
|
|
|
115
108
|
|
|
116
109
|
};
|
|
117
110
|
|
|
118
|
-
// Material map arrays (consolidated size buckets) are owned by PathTracer's
|
|
119
|
-
//
|
|
120
|
-
// see PathTracer._buildWavefrontKernels. Nothing material-map related is bound here.
|
|
111
|
+
// Material map arrays (consolidated size buckets) are owned by PathTracer's independent wavefront
|
|
112
|
+
// nodes, handed to its kernels as SceneResources — see PathTracer._buildWavefrontKernels.
|
|
121
113
|
|
|
122
114
|
// Spot light gobo array — placeholder until GoboManager populates it.
|
|
123
115
|
const goboMapsTex = stage.goboMaps ? texture( stage.goboMaps ) : createArrayPlaceholder();
|
|
124
|
-
setGoboMapsTexture( goboMapsTex );
|
|
125
116
|
|
|
126
117
|
// Spot light IES profiles array — placeholder until IESManager populates it.
|
|
127
118
|
const iesProfilesTex = stage.iesProfiles ? texture( stage.iesProfiles ) : createArrayPlaceholder();
|
|
128
|
-
setIESProfilesTexture( iesProfilesTex );
|
|
129
119
|
|
|
130
120
|
const result = {
|
|
131
121
|
triStorage, bvhStorage, matStorage, lightBufferStorage,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Hestroffer & Magnan 1998: I(µ)/I(1) = µ^α, α = −0.023 + 0.292 / λ[µm], at each primary's centroid. The core's sun
|
|
2
|
+
// (TSL/Sun.js) and the physical sky's disc average both read it.
|
|
3
|
+
export const LIMB_DARKENING_EXPONENT = [ 610, 550, 465 ].map( l => - 0.023 + 0.292 / ( l / 1000 ) );
|
|
@@ -6,7 +6,7 @@ import PackWorker from './Workers/PackWorker.js?worker&inline';
|
|
|
6
6
|
import { resampleRGBA8 } from './ResampleRGBA8.js';
|
|
7
7
|
import { ISSUE_CODES, EngineIssueError } from '../EngineIssues.js';
|
|
8
8
|
import { linearToSRGB } from './ToneMapCPU.js';
|
|
9
|
-
import { getActiveColorManagement } from '../Color/
|
|
9
|
+
import { getActiveColorManagement } from '../Color/ActiveColor.js';
|
|
10
10
|
import { createLogger } from '../utils/Logger.js';
|
|
11
11
|
import { createWorker, hardwareThreads, hasWorkers } from '../Platform.js';
|
|
12
12
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { BVHBuilder } from '../BVHBuilder.js';
|
|
2
|
-
import { TreeletOptimizer } from '../TreeletOptimizer.js';
|
|
3
2
|
import { ReinsertionOptimizer } from '../ReinsertionOptimizer.js';
|
|
4
3
|
|
|
5
4
|
self.onmessage = function ( e ) {
|
|
@@ -9,7 +8,6 @@ self.onmessage = function ( e ) {
|
|
|
9
8
|
sharedTriangleData, sharedCentroids, sharedBMin, sharedBMax, sharedIndices,
|
|
10
9
|
triangleCount,
|
|
11
10
|
maxLeafSize, numBins, maxBins, minBins,
|
|
12
|
-
treeletConfig,
|
|
13
11
|
reinsertionConfig,
|
|
14
12
|
reportProgress
|
|
15
13
|
} = e.data;
|
|
@@ -46,8 +44,7 @@ self.onmessage = function ( e ) {
|
|
|
46
44
|
builder.splitStats = {
|
|
47
45
|
sahSplits: 0, objectMedianSplits: 0, spatialMedianSplits: 0,
|
|
48
46
|
failedSplits: 0, avgBinsUsed: 0, totalSplitAttempts: 0,
|
|
49
|
-
mortonSortTime: 0, totalBuildTime: 0,
|
|
50
|
-
treeletsProcessed: 0, treeletsImproved: 0, averageSAHImprovement: 0,
|
|
47
|
+
mortonSortTime: 0, totalBuildTime: 0,
|
|
51
48
|
initTime: 0, sahBuildTime: 0, reorderTime: 0
|
|
52
49
|
};
|
|
53
50
|
|
|
@@ -70,36 +67,6 @@ self.onmessage = function ( e ) {
|
|
|
70
67
|
task.preMaxX, task.preMaxY, task.preMaxZ
|
|
71
68
|
);
|
|
72
69
|
|
|
73
|
-
// Treelet optimization on subtree
|
|
74
|
-
if ( treeletConfig && treeletConfig.enabled && ( task.end - task.start ) > 1000 ) {
|
|
75
|
-
|
|
76
|
-
const isLargeSubtree = ( task.end - task.start ) > 50000;
|
|
77
|
-
const adaptiveSize = isLargeSubtree ? 3 : ( treeletConfig.size || 5 );
|
|
78
|
-
const adaptiveMax = isLargeSubtree ? 10 : 20;
|
|
79
|
-
|
|
80
|
-
const optimizer = new TreeletOptimizer( builder.traversalCost, builder.intersectionCost );
|
|
81
|
-
optimizer.setTreeletSize( adaptiveSize );
|
|
82
|
-
optimizer.setMinImprovement( treeletConfig.minImprovement || 0.02 );
|
|
83
|
-
optimizer.setMaxTreelets( adaptiveMax );
|
|
84
|
-
|
|
85
|
-
const passes = treeletConfig.passes || 1;
|
|
86
|
-
for ( let pass = 0; pass < passes; pass ++ ) {
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
|
|
90
|
-
optimizer.optimizeBVH( root, null );
|
|
91
|
-
|
|
92
|
-
} catch ( err ) {
|
|
93
|
-
|
|
94
|
-
console.error( `[BVHSubtreeWorker] Treelet pass ${pass + 1} error:`, err );
|
|
95
|
-
break;
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
70
|
// Reinsertion optimization on subtree
|
|
104
71
|
if ( reinsertionConfig && reinsertionConfig.enabled && ( task.end - task.start ) > 1000 ) {
|
|
105
72
|
|
|
@@ -41,19 +41,13 @@ function handlePhase1( data ) {
|
|
|
41
41
|
sharedTriangleData, sharedCentroids, sharedBMin, sharedBMax,
|
|
42
42
|
sharedIndices, sharedMortonCodes,
|
|
43
43
|
triangleCount, depth, parallelDepth,
|
|
44
|
-
reportProgress
|
|
44
|
+
reportProgress
|
|
45
45
|
} = data;
|
|
46
46
|
|
|
47
47
|
try {
|
|
48
48
|
|
|
49
49
|
const builder = new BVHBuilder();
|
|
50
50
|
|
|
51
|
-
if ( treeletOptimization ) {
|
|
52
|
-
|
|
53
|
-
builder.setTreeletConfig( treeletOptimization );
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
51
|
const progressCallback = reportProgress ? ( progress ) => {
|
|
58
52
|
|
|
59
53
|
self.postMessage( { type: 'progress', progress } );
|
|
@@ -77,8 +71,7 @@ function handlePhase1( data ) {
|
|
|
77
71
|
builder.splitStats = {
|
|
78
72
|
sahSplits: 0, objectMedianSplits: 0, spatialMedianSplits: 0,
|
|
79
73
|
failedSplits: 0, avgBinsUsed: 0, totalSplitAttempts: 0,
|
|
80
|
-
mortonSortTime: 0, totalBuildTime: 0,
|
|
81
|
-
treeletsProcessed: 0, treeletsImproved: 0, averageSAHImprovement: 0,
|
|
74
|
+
mortonSortTime: 0, totalBuildTime: 0,
|
|
82
75
|
initTime: 0, sahBuildTime: 0, reorderTime: 0
|
|
83
76
|
};
|
|
84
77
|
|
|
@@ -193,7 +186,7 @@ function handleAssemble( data ) {
|
|
|
193
186
|
|
|
194
187
|
function handleFullBuild( data ) {
|
|
195
188
|
|
|
196
|
-
const { triangleData, triangleByteOffset, triangleByteLength, depth, reportProgress,
|
|
189
|
+
const { triangleData, triangleByteOffset, triangleByteLength, depth, reportProgress, reinsertionOptimization, sharedReorderBuffer, maxLeafSize, numBins, maxBins, minBins, foldLeaves: fold } = data;
|
|
197
190
|
const builder = new BVHBuilder();
|
|
198
191
|
// Honor the build params forwarded from SceneProcessor (previously ignored → default leaf 8).
|
|
199
192
|
if ( maxLeafSize !== undefined ) builder.maxLeafSize = maxLeafSize;
|
|
@@ -203,12 +196,6 @@ function handleFullBuild( data ) {
|
|
|
203
196
|
|
|
204
197
|
try {
|
|
205
198
|
|
|
206
|
-
if ( treeletOptimization ) {
|
|
207
|
-
|
|
208
|
-
builder.setTreeletConfig( treeletOptimization );
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
199
|
if ( reinsertionOptimization ) {
|
|
213
200
|
|
|
214
201
|
builder.setReinsertionConfig( reinsertionOptimization );
|
|
@@ -248,7 +235,7 @@ function handleFullBuild( data ) {
|
|
|
248
235
|
bvhData,
|
|
249
236
|
originalToBvh,
|
|
250
237
|
triangleCount: inputTriangles.length / FPT,
|
|
251
|
-
|
|
238
|
+
splitStats: builder.splitStats
|
|
252
239
|
}, transferables );
|
|
253
240
|
|
|
254
241
|
} else {
|
|
@@ -264,7 +251,7 @@ function handleFullBuild( data ) {
|
|
|
264
251
|
triangles: reordered,
|
|
265
252
|
originalToBvh,
|
|
266
253
|
triangleCount,
|
|
267
|
-
|
|
254
|
+
splitStats: builder.splitStats
|
|
268
255
|
}, transferables );
|
|
269
256
|
|
|
270
257
|
}
|
|
@@ -1,179 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web Worker for
|
|
3
|
-
* for importance sampling. Pure math — no Three.js dependencies.
|
|
2
|
+
* Web Worker for an environment map's sampling table (EnvironmentExactTable.js). Pure math — no Three.js dependencies.
|
|
4
3
|
*
|
|
5
4
|
* Input: { floatData: Float32Array, width, height }
|
|
6
|
-
* Output: {
|
|
5
|
+
* Output: { width, height } and the table
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
let lower = offset;
|
|
12
|
-
let upper = offset + count - 1;
|
|
13
|
-
|
|
14
|
-
while ( lower < upper ) {
|
|
15
|
-
|
|
16
|
-
const mid = ( lower + upper ) >> 1;
|
|
17
|
-
|
|
18
|
-
if ( array[ mid ] < targetValue ) {
|
|
19
|
-
|
|
20
|
-
lower = mid + 1;
|
|
21
|
-
|
|
22
|
-
} else {
|
|
23
|
-
|
|
24
|
-
upper = mid;
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return lower - offset;
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function buildCDF( floatData, width, height ) {
|
|
35
|
-
|
|
36
|
-
const numPixels = width * height;
|
|
37
|
-
|
|
38
|
-
// Pass 1: compute per-pixel luminance weighted by sin(theta) and raw total sum.
|
|
39
|
-
// sin(theta) compensates for the equirectangular projection: pixels near the poles
|
|
40
|
-
// cover less solid angle, so weighting by sin(theta) makes the CDF proportional to
|
|
41
|
-
// luminance per solid angle rather than luminance per pixel.
|
|
42
|
-
const pixelWeights = new Float32Array( numPixels );
|
|
43
|
-
let rawTotalSum = 0.0;
|
|
44
|
-
|
|
45
|
-
for ( let y = 0; y < height; y ++ ) {
|
|
46
|
-
|
|
47
|
-
const sinTheta = Math.sin( Math.PI * ( y + 0.5 ) / height );
|
|
48
|
-
|
|
49
|
-
for ( let x = 0; x < width; x ++ ) {
|
|
50
|
-
|
|
51
|
-
const i = y * width + x;
|
|
52
|
-
const r = floatData[ 4 * i ];
|
|
53
|
-
const g = floatData[ 4 * i + 1 ];
|
|
54
|
-
const b = floatData[ 4 * i + 2 ];
|
|
55
|
-
|
|
56
|
-
// Luminance (Rec. 709) weighted by solid angle factor
|
|
57
|
-
const w = ( 0.2126 * r + 0.7152 * g + 0.0722 * b ) * sinTheta;
|
|
58
|
-
pixelWeights[ i ] = w;
|
|
59
|
-
rawTotalSum += w;
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// MIS Compensation (Karlík et al. 2019, Eq. 14)
|
|
66
|
-
// With equal sample allocation (c_I = 0.5): delta = 2*(1 - 0.5)*meanWeight = meanWeight
|
|
67
|
-
// Subtracting mean sharpens the env map PDF, reducing oversampling
|
|
68
|
-
// of dim regions already well-covered by BSDF sampling.
|
|
69
|
-
const meanWeight = rawTotalSum / numPixels;
|
|
70
|
-
let compensatedTotalSum = 0.0;
|
|
71
|
-
|
|
72
|
-
for ( let i = 0; i < numPixels; i ++ ) {
|
|
73
|
-
|
|
74
|
-
pixelWeights[ i ] = Math.max( 0, pixelWeights[ i ] - meanWeight );
|
|
75
|
-
compensatedTotalSum += pixelWeights[ i ];
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Fall back to raw weights if compensation zeroed everything (uniform env map)
|
|
80
|
-
const useCompensation = compensatedTotalSum > 0;
|
|
81
|
-
const totalSumValue = useCompensation ? compensatedTotalSum : rawTotalSum;
|
|
82
|
-
const compensationDelta = useCompensation ? meanWeight : 0;
|
|
83
|
-
|
|
84
|
-
if ( ! useCompensation ) {
|
|
85
|
-
|
|
86
|
-
// Restore raw sin-weighted luminance
|
|
87
|
-
for ( let y = 0; y < height; y ++ ) {
|
|
88
|
-
|
|
89
|
-
const sinTheta = Math.sin( Math.PI * ( y + 0.5 ) / height );
|
|
90
|
-
|
|
91
|
-
for ( let x = 0; x < width; x ++ ) {
|
|
92
|
-
|
|
93
|
-
const i = y * width + x;
|
|
94
|
-
const r = floatData[ 4 * i ];
|
|
95
|
-
const g = floatData[ 4 * i + 1 ];
|
|
96
|
-
const b = floatData[ 4 * i + 2 ];
|
|
97
|
-
pixelWeights[ i ] = ( 0.2126 * r + 0.7152 * g + 0.0722 * b ) * sinTheta;
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Pass 2: build conditional and marginal CDFs from (compensated) weights
|
|
106
|
-
const cdfConditional = new Float32Array( numPixels );
|
|
107
|
-
const cdfMarginal = new Float32Array( height );
|
|
108
|
-
|
|
109
|
-
let cumulativeWeightMarginal = 0.0;
|
|
110
|
-
|
|
111
|
-
for ( let y = 0; y < height; y ++ ) {
|
|
112
|
-
|
|
113
|
-
let cumulativeRowWeight = 0.0;
|
|
114
|
-
for ( let x = 0; x < width; x ++ ) {
|
|
115
|
-
|
|
116
|
-
const i = y * width + x;
|
|
117
|
-
cumulativeRowWeight += pixelWeights[ i ];
|
|
118
|
-
cdfConditional[ i ] = cumulativeRowWeight;
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Normalize row CDF to [0, 1]
|
|
123
|
-
if ( cumulativeRowWeight !== 0 ) {
|
|
124
|
-
|
|
125
|
-
for ( let i = y * width, l = y * width + width; i < l; i ++ ) {
|
|
126
|
-
|
|
127
|
-
cdfConditional[ i ] /= cumulativeRowWeight;
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
cumulativeWeightMarginal += cumulativeRowWeight;
|
|
134
|
-
cdfMarginal[ y ] = cumulativeWeightMarginal;
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Normalize marginal CDF to [0, 1]
|
|
139
|
-
if ( cumulativeWeightMarginal !== 0 ) {
|
|
140
|
-
|
|
141
|
-
for ( let i = 0, l = cdfMarginal.length; i < l; i ++ ) {
|
|
142
|
-
|
|
143
|
-
cdfMarginal[ i ] /= cumulativeWeightMarginal;
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Invert marginal CDF
|
|
150
|
-
const marginalData = new Float32Array( height );
|
|
151
|
-
for ( let i = 0; i < height; i ++ ) {
|
|
152
|
-
|
|
153
|
-
const dist = ( i + 1 ) / height;
|
|
154
|
-
const row = binarySearchFindClosestIndexOf( cdfMarginal, dist, 0, height );
|
|
155
|
-
marginalData[ i ] = ( row + 0.5 ) / height;
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Invert conditional CDFs
|
|
160
|
-
const conditionalData = new Float32Array( width * height );
|
|
161
|
-
for ( let y = 0; y < height; y ++ ) {
|
|
162
|
-
|
|
163
|
-
for ( let x = 0; x < width; x ++ ) {
|
|
164
|
-
|
|
165
|
-
const i = y * width + x;
|
|
166
|
-
const dist = ( x + 1 ) / width;
|
|
167
|
-
const col = binarySearchFindClosestIndexOf( cdfConditional, dist, y * width, width );
|
|
168
|
-
conditionalData[ i ] = ( col + 0.5 ) / width;
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return { marginalData, conditionalData, totalSum: totalSumValue, compensationDelta };
|
|
175
|
-
|
|
176
|
-
}
|
|
8
|
+
import { buildExactEnvironmentTable } from '../EnvironmentExactTable.js';
|
|
177
9
|
|
|
178
10
|
self.onmessage = function ( e ) {
|
|
179
11
|
|
|
@@ -181,19 +13,10 @@ self.onmessage = function ( e ) {
|
|
|
181
13
|
|
|
182
14
|
try {
|
|
183
15
|
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
// Transfer arrays back zero-copy
|
|
16
|
+
const table = buildExactEnvironmentTable( floatData, width, height );
|
|
187
17
|
self.postMessage(
|
|
188
|
-
{
|
|
189
|
-
|
|
190
|
-
conditionalData: result.conditionalData,
|
|
191
|
-
totalSum: result.totalSum,
|
|
192
|
-
compensationDelta: result.compensationDelta,
|
|
193
|
-
width,
|
|
194
|
-
height,
|
|
195
|
-
},
|
|
196
|
-
[ result.marginalData.buffer, result.conditionalData.buffer ]
|
|
18
|
+
{ width, height, ...table },
|
|
19
|
+
[ table.exactConditional.buffer, table.exactMarginal.buffer, table.exactRowGuide.buffer, table.exactMarginalGuide.buffer ]
|
|
197
20
|
);
|
|
198
21
|
|
|
199
22
|
} catch ( error ) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** What the archive add-on reads, known before its code loads (rayzee/addons/archives; PathTracerApp loads it on first use). */
|
|
2
|
+
export const ARCHIVE_FORMATS = Object.freeze( {
|
|
3
|
+
'zip': { type: 'archive', name: 'ZIP Archive' },
|
|
4
|
+
'gz': { type: 'archive', name: 'Gzipped TAR Archive' },
|
|
5
|
+
'tgz': { type: 'archive', name: 'Gzipped TAR Archive' },
|
|
6
|
+
'tar': { type: 'archive', name: 'TAR Archive' },
|
|
7
|
+
} );
|
package/src/Processor/utils.js
CHANGED
|
@@ -63,7 +63,8 @@ export function disposeMaterialTextures( material ) {
|
|
|
63
63
|
const textures = [
|
|
64
64
|
'alphaMap', 'aoMap', 'bumpMap', 'clearcoatMap', 'clearcoatNormalMap', 'clearcoatRoughnessMap', 'displacementMap',
|
|
65
65
|
'emissiveMap', 'envMap', 'gradientMap', 'lightMap', 'map', 'metalnessMap', 'normalMap', 'roughnessMap', 'specularMap',
|
|
66
|
-
'sheenColorMap', 'sheenRoughnessMap', 'specularIntensityMap', 'specularColorMap', 'thicknessMap', 'transmissionMap'
|
|
66
|
+
'sheenColorMap', 'sheenRoughnessMap', 'specularIntensityMap', 'specularColorMap', 'thicknessMap', 'transmissionMap',
|
|
67
|
+
'diffuseTransmissionMap', 'diffuseTransmissionColorMap',
|
|
67
68
|
];
|
|
68
69
|
|
|
69
70
|
textures.forEach( texture => {
|