rayzee 10.0.0 → 11.1.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 +252 -44
- package/dist/ActiveColor-YvuQq44O.js +13 -0
- package/dist/ArchiveImporter-Hn35o6Z5.js +5145 -0
- package/dist/AssetConfig-DSEntE65.js +30 -0
- package/dist/BidirectionalIntegrator-CBw8hkeu.js +946 -0
- package/dist/BufferLayout-D_IBo2ci.js +150 -0
- package/dist/ColorManagement-oeEk7oSu.js +1488 -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-dDDGj9Av.js +97 -0
- package/dist/{NeuralRetouch-CYgkQY8Z.js → NeuralRetouch-BzNpiVHZ.js} +8 -6
- package/dist/{NeuralSuperRes-PkgDLQcD.js → NeuralSuperRes-Bk7bHg2B.js} +55 -120
- package/dist/PathTracer-72XufKAr.js +29976 -0
- package/dist/PhysicalSky-BgjdV88k.js +1219 -0
- package/dist/RayzeeRenderer-1QRO97eq.js +3551 -0
- package/dist/SolarLimb-CPaeZVwz.js +721 -0
- package/dist/ToneMapGPU-CjU3osDd.js +177 -0
- package/dist/ViewTransforms-CYN7bq2w.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-tnAoUL1j.js +94 -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 +2551 -44024
- package/dist/rayzee.umd.js +528 -487
- package/dist/sceneCachePolicy-C67jbci-.js +443 -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/Color/ViewTransforms.js +5 -1
- package/src/EngineDefaults.js +62 -1029
- package/src/EngineEvents.js +2 -0
- package/src/EngineIssues.js +2 -0
- package/src/Headless.js +6 -5
- package/src/Passes/AIUpscaler.js +58 -141
- package/src/Passes/OIDNDenoiser.js +92 -65
- package/src/Passes/OIDNTemporalHistory.js +1 -1
- package/src/PathTracerApp.js +620 -4026
- package/src/Pipeline/PipelineContext.js +0 -4
- package/src/Platform.js +36 -0
- package/src/Processor/ArchiveCache.js +20 -7
- package/src/Processor/ArchiveImporter.js +1265 -0
- package/src/Processor/ArchiveReader.js +22 -4
- package/src/Processor/AssetLoader.js +327 -1763
- package/src/Processor/AtmosphereModel.js +1 -2
- package/src/Processor/BVHBuilder.js +14 -126
- package/src/Processor/BVHLeafFold.js +4 -6
- package/src/Processor/BVHRefitter.js +67 -46
- package/src/Processor/BufferLayout.js +291 -0
- package/src/Processor/EmissiveTriangleBuilder.js +1 -1
- 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 +15 -5
- package/src/Processor/HostMemory.js +7 -1
- package/src/Processor/IESParser.js +47 -35
- package/src/Processor/InstanceTable.js +1 -1
- package/src/Processor/KernelManager.js +35 -2
- package/src/Processor/MaterialPacking.js +10 -8
- package/src/Processor/PBRT/PBRTMaterials.js +254 -42
- package/src/Processor/PBRT/PBRTParser.js +49 -19
- package/src/Processor/PBRT/PBRTScattering.js +93 -0
- package/src/Processor/PBRT/PBRTSceneBuilder.js +1050 -75
- package/src/Processor/PBRT/PBRTTextureBake.js +179 -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 +39 -5
- package/src/Processor/ReinsertionOptimizer.js +2 -2
- package/src/Processor/SceneMetadata.js +30 -5
- package/src/Processor/SceneProcessor.js +53 -62
- package/src/Processor/ShaderBuilder.js +6 -16
- package/src/Processor/SimpleSky.js +1 -62
- package/src/Processor/SolarLimb.js +3 -0
- package/src/Processor/SplitBLAS.js +1 -1
- package/src/Processor/StorageTexturePool.js +22 -1
- package/src/Processor/TLASBuilder.js +1 -3
- package/src/Processor/TextureBuckets.js +237 -0
- package/src/Processor/TextureCreator.js +181 -8
- package/src/Processor/ToneMapGPU.js +64 -15
- package/src/Processor/Workers/BVHRefitWorker.js +5 -2
- 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/Workers/TexturesWorker.js +103 -18
- package/src/Processor/archiveFormats.js +7 -0
- package/src/Processor/utils.js +2 -1
- package/src/RayzeeRenderer.js +3900 -0
- package/src/RenderSettings.js +68 -62
- package/src/Stages/ASVGF.js +13 -14
- package/src/Stages/AutoExposure.js +17 -17
- package/src/Stages/BilateralFilter.js +2 -1
- package/src/Stages/Compositor.js +8 -23
- package/src/Stages/DenoiserSettings.js +182 -0
- package/src/Stages/EdgeFilter.js +2 -1
- package/src/Stages/MotionVector.js +1 -1
- package/src/Stages/NRD.js +11 -5
- package/src/Stages/NormalDepth.js +12 -8
- package/src/Stages/PathTracer.js +336 -43
- package/src/Stages/PathTracerStage.js +69 -66
- package/src/Stages/Variance.js +1 -1
- 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 +45 -9
- package/src/Storage/areas.js +4 -0
- package/src/TSL/BVHTraversal.js +50 -25
- package/src/TSL/Bidirectional.js +208 -0
- package/src/TSL/BidirectionalLamps.js +132 -0
- package/src/TSL/Clearcoat.js +15 -6
- package/src/TSL/Common.js +20 -15
- package/src/TSL/ConnectKernel.js +167 -0
- package/src/TSL/Debugger.js +1 -1
- package/src/TSL/Displacement.js +4 -3
- package/src/TSL/EmissiveSampling.js +65 -18
- 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 +180 -0
- package/src/TSL/LightVisibility.js +111 -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 +239 -51
- 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 +224 -0
- package/src/TSL/PathTracerCore.js +65 -29
- package/src/TSL/Random.js +5 -1
- package/src/TSL/SceneResources.js +51 -0
- package/src/TSL/ShadeKernel.js +985 -101
- package/src/TSL/Struct.js +10 -0
- package/src/TSL/Sun.js +1 -1
- package/src/TSL/TextureSampling.js +66 -61
- 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 +31 -0
- package/src/index.js +13 -23
- package/src/integrators/BidirectionalIntegrator.js +838 -0
- package/src/managers/AnimationManager.js +88 -6
- package/src/managers/CameraManager.js +103 -46
- package/src/managers/DenoisingManager.js +14 -10
- package/src/managers/EnvironmentManager.js +125 -103
- package/src/managers/GoboManager.js +9 -0
- package/src/managers/MaterialDataManager.js +48 -37
- package/src/managers/UniformManager.js +32 -10
- package/dist/ToneMapGPU-B6XIe3DU.js +0 -544
- package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
- package/src/Processor/TreeletOptimizer.js +0 -574
|
@@ -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 ) {
|
|
@@ -1,16 +1,114 @@
|
|
|
1
|
+
import { TEXTURE_CONSTANTS, alignBucketWidth } from '../TextureBuckets.js';
|
|
2
|
+
|
|
1
3
|
let canvas, ctx;
|
|
2
4
|
|
|
3
5
|
// Memory limits and chunking configuration
|
|
4
6
|
const MEMORY_LIMITS = {
|
|
5
|
-
MAX_BYTES_PER_TEXTURE: 256 * 1024 * 1024, // 256MB per texture array
|
|
6
|
-
MAX_TEXTURE_DIMENSION: 8192, // Hardware ceiling (WebGPU maxTextureDimension2D guaranteed min); the per-scene maxTextureSize setting is the actual knob
|
|
7
7
|
CHUNK_SIZE: 8, // Optimized: Process textures in chunks of 8 for better memory locality
|
|
8
8
|
ADAPTIVE_CHUNK_SIZE: true, // Enable adaptive chunk sizing based on texture dimensions
|
|
9
9
|
MEMORY_SAFETY_FACTOR: 0.8 // Use only 80% of estimated available memory
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
let stream = null;
|
|
13
|
+
|
|
14
|
+
function handleStream( msg ) {
|
|
15
|
+
|
|
16
|
+
if ( msg.stream === 'begin' ) {
|
|
17
|
+
|
|
18
|
+
const { width, height, depth } = msg;
|
|
19
|
+
const target = new OffscreenCanvas( width, height );
|
|
20
|
+
const context = target.getContext( '2d', { willReadFrequently: true, alpha: true, desynchronized: true } );
|
|
21
|
+
stream = { width, height, depth, context, data: new Uint8Array( width * height * depth * 4 ) };
|
|
22
|
+
return;
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const { width, height, depth, context, data } = stream;
|
|
27
|
+
|
|
28
|
+
if ( msg.stream === 'layer' ) {
|
|
29
|
+
|
|
30
|
+
context.clearRect( 0, 0, width, height );
|
|
31
|
+
context.drawImage( msg.bitmap, 0, 0 );
|
|
32
|
+
msg.bitmap.close();
|
|
33
|
+
data.set( context.getImageData( 0, 0, width, height ).data, width * height * 4 * msg.index );
|
|
34
|
+
self.postMessage( { stream: 'ack', index: msg.index } );
|
|
35
|
+
return;
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
stream = null;
|
|
40
|
+
self.postMessage( { data: data.buffer, width, height, depth }, [ data.buffer ] );
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function processIntoShared( { shared, width, height, layers } ) {
|
|
45
|
+
|
|
46
|
+
if ( canvas.width !== width || canvas.height !== height ) {
|
|
47
|
+
|
|
48
|
+
canvas.width = width;
|
|
49
|
+
canvas.height = height;
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
ctx.imageSmoothingEnabled = true;
|
|
54
|
+
ctx.imageSmoothingQuality = 'high';
|
|
55
|
+
|
|
56
|
+
const data = new Uint8Array( shared );
|
|
57
|
+
const bytes = width * height * 4;
|
|
58
|
+
|
|
59
|
+
for ( const { index, texture } of layers ) {
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
|
|
63
|
+
await processSingleTextureOptimized( texture, data, index * bytes, width, height );
|
|
64
|
+
|
|
65
|
+
} catch ( error ) {
|
|
66
|
+
|
|
67
|
+
console.warn( `Failed to process texture ${index}:`, error );
|
|
68
|
+
data.fill( 0, index * bytes, ( index + 1 ) * bytes );
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
12
76
|
self.onmessage = async function ( e ) {
|
|
13
77
|
|
|
78
|
+
if ( e.data.shared ) {
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
|
|
82
|
+
if ( ! canvas ) initializeWorker( e.data.maxTextureSize );
|
|
83
|
+
await processIntoShared( e.data );
|
|
84
|
+
self.postMessage( { done: true } );
|
|
85
|
+
|
|
86
|
+
} catch ( error ) {
|
|
87
|
+
|
|
88
|
+
self.postMessage( { error: error.message } );
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return;
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if ( e.data.stream ) {
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
|
|
100
|
+
handleStream( e.data );
|
|
101
|
+
|
|
102
|
+
} catch ( error ) {
|
|
103
|
+
|
|
104
|
+
self.postMessage( { error: error.message } );
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return;
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
|
|
14
112
|
const { textures, maxTextureSize, method = 'direct-transfer' } = e.data;
|
|
15
113
|
|
|
16
114
|
try {
|
|
@@ -39,7 +137,7 @@ self.onmessage = async function ( e ) {
|
|
|
39
137
|
function initializeWorker( maxTextureSize ) {
|
|
40
138
|
|
|
41
139
|
// Initialize OffscreenCanvas with optimal settings
|
|
42
|
-
const size = Math.min( maxTextureSize,
|
|
140
|
+
const size = Math.min( maxTextureSize, TEXTURE_CONSTANTS.MAX_TEXTURE_SIZE );
|
|
43
141
|
canvas = new OffscreenCanvas( size, size );
|
|
44
142
|
ctx = canvas.getContext( '2d', {
|
|
45
143
|
willReadFrequently: true,
|
|
@@ -51,17 +149,6 @@ function initializeWorker( maxTextureSize ) {
|
|
|
51
149
|
|
|
52
150
|
async function processTextures( textures, maxTextureSize, method ) {
|
|
53
151
|
|
|
54
|
-
// Check if we need to use chunked processing
|
|
55
|
-
const dimensions = calculateOptimalDimensions( textures, maxTextureSize );
|
|
56
|
-
const estimatedBytes = dimensions.maxWidth * dimensions.maxHeight * textures.length * 4;
|
|
57
|
-
|
|
58
|
-
if ( estimatedBytes > MEMORY_LIMITS.MAX_BYTES_PER_TEXTURE ) {
|
|
59
|
-
|
|
60
|
-
console.log( `Large texture array detected (${( estimatedBytes / 1024 / 1024 ).toFixed( 2 )}MB), using chunked processing` );
|
|
61
|
-
return await processTexturesInChunks( textures, maxTextureSize, method );
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
152
|
switch ( method ) {
|
|
66
153
|
|
|
67
154
|
case 'direct-transfer':
|
|
@@ -620,7 +707,7 @@ function calculateOptimalDimensions( textures, maxTextureSize ) {
|
|
|
620
707
|
}
|
|
621
708
|
|
|
622
709
|
// Scale down proportionally only when the cap is exceeded; native res is kept below it.
|
|
623
|
-
const cap = Math.min( maxTextureSize,
|
|
710
|
+
const cap = Math.min( maxTextureSize, TEXTURE_CONSTANTS.MAX_TEXTURE_SIZE );
|
|
624
711
|
const longest = Math.max( maxWidth, maxHeight );
|
|
625
712
|
if ( longest > cap ) {
|
|
626
713
|
|
|
@@ -630,9 +717,7 @@ function calculateOptimalDimensions( textures, maxTextureSize ) {
|
|
|
630
717
|
|
|
631
718
|
}
|
|
632
719
|
|
|
633
|
-
|
|
634
|
-
// Mirrors alignBucketWidth in EngineDefaults (not importable from worker context).
|
|
635
|
-
maxWidth = Math.min( cap, Math.max( 4, Math.ceil( Math.max( 1, maxWidth ) / 64 ) * 64 ) );
|
|
720
|
+
maxWidth = alignBucketWidth( maxWidth, cap );
|
|
636
721
|
|
|
637
722
|
return { maxWidth, maxHeight: Math.max( 1, maxHeight ) };
|
|
638
723
|
|
|
@@ -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 => {
|