rayzee 10.0.0 → 11.0.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-BRQvLggb.js +4300 -0
- package/dist/AssetConfig-DSEntE65.js +30 -0
- package/dist/BidirectionalIntegrator-9lZQxFVH.js +934 -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-BCXylThH.js} +8 -6
- package/dist/{NeuralSuperRes-PkgDLQcD.js → NeuralSuperRes-sZAeS142.js} +55 -120
- package/dist/PathTracer-CQPW06Mm.js +29971 -0
- package/dist/PhysicalSky-BvqCw_dy.js +1219 -0
- package/dist/RayzeeRenderer-COpwotpU.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-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 +2551 -44024
- package/dist/rayzee.umd.js +528 -487
- package/dist/sceneCachePolicy-BSSsKY98.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 +1 -1
- package/src/Processor/ArchiveImporter.js +1259 -0
- 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 +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 +39 -5
- package/src/Processor/ReinsertionOptimizer.js +2 -2
- 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 +3899 -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 +338 -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 +204 -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 +147 -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 +165 -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 +218 -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 +964 -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 +833 -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,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* EnvironmentManager.js
|
|
3
|
-
* Manages HDRI loading, CDF importance sampling, procedural/
|
|
3
|
+
* Manages HDRI loading, CDF importance sampling, procedural/solid sky
|
|
4
4
|
* generation, and environment rotation for the path tracing pipeline.
|
|
5
5
|
*
|
|
6
6
|
* Storage buffer nodes are created once and never replaced — only .value
|
|
@@ -8,18 +8,38 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
-
RGBAFormat,
|
|
11
|
+
RGBAFormat, FloatType, LinearFilter, Vector2, Vector3, Color, Matrix4, DataTexture,
|
|
12
12
|
} from 'three';
|
|
13
13
|
import { EquirectHDRInfo } from '../Processor/EquirectHDRInfo.js';
|
|
14
|
-
import {
|
|
14
|
+
import { packExactTable } from '../Processor/EnvironmentExactTable.js';
|
|
15
15
|
import { SimpleSky } from '../Processor/SimpleSky.js';
|
|
16
16
|
import { convertLinearTriple } from '../Color/WorkingMatrix.js';
|
|
17
17
|
import { createLogger, fmt } from '../utils/Logger.js';
|
|
18
|
+
import { sunPosition, dayOfYearForMonth } from '../Processor/SunPosition.js';
|
|
19
|
+
import { getActiveColorManagement } from '../Color/ActiveColor.js';
|
|
20
|
+
import { loadCDF, saveCDF } from '../Storage/CDFCache.js';
|
|
21
|
+
import { ISSUE_CODES } from '../EngineIssues.js';
|
|
18
22
|
|
|
19
23
|
const log = createLogger( 'env' );
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
|
|
25
|
+
/** The default sun as a time of day (solar hours), month and latitude; north lies along −Z. */
|
|
26
|
+
export const DEFAULT_SUN_PATH = Object.freeze( { time: 10, month: 3, latitude: 40 } );
|
|
27
|
+
|
|
28
|
+
const DEFAULT_SUN = sunPosition( { hours: DEFAULT_SUN_PATH.time, dayOfYear: dayOfYearForMonth( DEFAULT_SUN_PATH.month ), latitude: DEFAULT_SUN_PATH.latitude } );
|
|
29
|
+
|
|
30
|
+
/** The skies an environment starts with: a solid colour, and the physical sky's Clear Day. */
|
|
31
|
+
export const SKY_DEFAULTS = Object.freeze( {
|
|
32
|
+
solidSkyColor: '#87CEEB',
|
|
33
|
+
skySunAzimuth: 180 - DEFAULT_SUN.azimuth,
|
|
34
|
+
skySunElevation: DEFAULT_SUN.elevation,
|
|
35
|
+
skySunStrength: 1, // artistic multiplier on the disc and its light; 1 is physical
|
|
36
|
+
skySunSize: 0.53, // angular diameter, degrees
|
|
37
|
+
skyTurbidity: 2, // 1 is aerosol-free air, ~2 a clear day, 6+ hazy
|
|
38
|
+
skyOzone: 300, // Dobson units
|
|
39
|
+
skyAirDensity: 1,
|
|
40
|
+
skyGroundAlbedo: '#959595', // 0.3 linear
|
|
41
|
+
skyAltitude: 50, // metres
|
|
42
|
+
} );
|
|
23
43
|
|
|
24
44
|
const SKY_WIDTH = 1024;
|
|
25
45
|
const SKY_HEIGHT = 512;
|
|
@@ -45,7 +65,12 @@ export class EnvironmentManager {
|
|
|
45
65
|
// CDF computation engine
|
|
46
66
|
this.equirectHdrInfo = new EquirectHDRInfo();
|
|
47
67
|
|
|
48
|
-
// Sky renderers (lazy init)
|
|
68
|
+
// Sky renderers (lazy init). The physical sky is a capability: setProceduralSky() installs its class.
|
|
69
|
+
this.ProceduralSky = null;
|
|
70
|
+
this._loadProceduralSky = null;
|
|
71
|
+
this._proceduralSkyLoading = null;
|
|
72
|
+
/** @type {?import('../EngineIssues.js').IssueLog} */
|
|
73
|
+
this.issues = null;
|
|
49
74
|
this.physicalSky = null;
|
|
50
75
|
this.simpleSkyRenderer = null;
|
|
51
76
|
this._sun = null;
|
|
@@ -83,28 +108,23 @@ export class EnvironmentManager {
|
|
|
83
108
|
this.envParams = {
|
|
84
109
|
mode: 'hdri',
|
|
85
110
|
|
|
86
|
-
// Gradient Sky
|
|
87
|
-
gradientZenithColor: new Color( DEFAULT_STATE.gradientZenithColor ),
|
|
88
|
-
gradientHorizonColor: new Color( DEFAULT_STATE.gradientHorizonColor ),
|
|
89
|
-
gradientGroundColor: new Color( DEFAULT_STATE.gradientGroundColor ),
|
|
90
|
-
|
|
91
111
|
// Solid Color Sky
|
|
92
|
-
solidSkyColor: new Color(
|
|
112
|
+
solidSkyColor: new Color( SKY_DEFAULTS.solidSkyColor ),
|
|
93
113
|
|
|
94
114
|
// Physical sky. The sun direction is in the sky's own frame; environment rotation turns both.
|
|
95
115
|
skySunDirection: this._calculateInitialSunDirection(),
|
|
96
|
-
skySunStrength:
|
|
97
|
-
skySunSize:
|
|
98
|
-
skyTurbidity:
|
|
99
|
-
skyOzone:
|
|
100
|
-
skyAirDensity:
|
|
101
|
-
skyGroundAlbedo: new Color(
|
|
102
|
-
skyAltitude:
|
|
116
|
+
skySunStrength: SKY_DEFAULTS.skySunStrength,
|
|
117
|
+
skySunSize: SKY_DEFAULTS.skySunSize,
|
|
118
|
+
skyTurbidity: SKY_DEFAULTS.skyTurbidity,
|
|
119
|
+
skyOzone: SKY_DEFAULTS.skyOzone,
|
|
120
|
+
skyAirDensity: SKY_DEFAULTS.skyAirDensity,
|
|
121
|
+
skyGroundAlbedo: new Color( SKY_DEFAULTS.skyGroundAlbedo ),
|
|
122
|
+
skyAltitude: SKY_DEFAULTS.skyAltitude,
|
|
103
123
|
};
|
|
104
124
|
|
|
105
125
|
/**
|
|
106
126
|
* Optional callbacks set by the owning stage.
|
|
107
|
-
* @type {{ onReset?: Function,
|
|
127
|
+
* @type {{ onReset?: Function, onLightingChanged?: Function, getSceneTextureNodes?: Function }}
|
|
108
128
|
*/
|
|
109
129
|
this.callbacks = {};
|
|
110
130
|
|
|
@@ -116,9 +136,9 @@ export class EnvironmentManager {
|
|
|
116
136
|
// ===== MODE STATE MACHINE =====
|
|
117
137
|
|
|
118
138
|
/**
|
|
119
|
-
* Switches the environment mode (hdri,
|
|
139
|
+
* Switches the environment mode (hdri, color, procedural — the physical sky).
|
|
120
140
|
* Preserves the HDRI texture when switching away, restores when switching back.
|
|
121
|
-
* @param {'hdri'|'
|
|
141
|
+
* @param {'hdri'|'color'|'procedural'} mode
|
|
122
142
|
*/
|
|
123
143
|
async setMode( mode ) {
|
|
124
144
|
|
|
@@ -132,11 +152,7 @@ export class EnvironmentManager {
|
|
|
132
152
|
|
|
133
153
|
}
|
|
134
154
|
|
|
135
|
-
if ( mode === '
|
|
136
|
-
|
|
137
|
-
await this.generateGradientTexture();
|
|
138
|
-
|
|
139
|
-
} else if ( mode === 'color' ) {
|
|
155
|
+
if ( mode === 'color' ) {
|
|
140
156
|
|
|
141
157
|
await this.generateSolidColorTexture();
|
|
142
158
|
|
|
@@ -154,7 +170,7 @@ export class EnvironmentManager {
|
|
|
154
170
|
if ( mode !== 'procedural' && prev === 'procedural' ) this._releaseSky();
|
|
155
171
|
|
|
156
172
|
this.markDirty();
|
|
157
|
-
this.callbacks.
|
|
173
|
+
this.callbacks.onLightingChanged?.();
|
|
158
174
|
this._notifyReset();
|
|
159
175
|
|
|
160
176
|
}
|
|
@@ -185,9 +201,6 @@ export class EnvironmentManager {
|
|
|
185
201
|
return {
|
|
186
202
|
mode: p.mode,
|
|
187
203
|
hdri: this.hdriSource,
|
|
188
|
-
gradientZenithColor: p.gradientZenithColor.toArray(),
|
|
189
|
-
gradientHorizonColor: p.gradientHorizonColor.toArray(),
|
|
190
|
-
gradientGroundColor: p.gradientGroundColor.toArray(),
|
|
191
204
|
solidSkyColor: p.solidSkyColor.toArray(),
|
|
192
205
|
skyModel: 'atmosphere',
|
|
193
206
|
skySunDirection: p.skySunDirection.toArray(),
|
|
@@ -212,7 +225,7 @@ export class EnvironmentManager {
|
|
|
212
225
|
const p = this.envParams;
|
|
213
226
|
// Sessions saved before the physical sky gave the same names other meanings.
|
|
214
227
|
const atmosphere = state.skyModel === 'atmosphere';
|
|
215
|
-
const colors = [ '
|
|
228
|
+
const colors = [ 'solidSkyColor', 'skySunDirection' ];
|
|
216
229
|
for ( const key of atmosphere ? [ ...colors, 'skyGroundAlbedo' ] : colors ) {
|
|
217
230
|
|
|
218
231
|
if ( Array.isArray( state[ key ] ) ) p[ key ].fromArray( state[ key ] );
|
|
@@ -229,7 +242,9 @@ export class EnvironmentManager {
|
|
|
229
242
|
|
|
230
243
|
}
|
|
231
244
|
|
|
232
|
-
|
|
245
|
+
// A session saved with the removed gradient sky keeps the sky it is already showing.
|
|
246
|
+
const known = [ 'hdri', 'color', 'procedural' ].includes( state.mode );
|
|
247
|
+
if ( known && ( state.mode !== 'hdri' || p.mode !== 'hdri' ) ) await this.setMode( state.mode );
|
|
233
248
|
|
|
234
249
|
}
|
|
235
250
|
|
|
@@ -249,13 +264,6 @@ export class EnvironmentManager {
|
|
|
249
264
|
|
|
250
265
|
}
|
|
251
266
|
|
|
252
|
-
/** @see generateGradientTexture */
|
|
253
|
-
generateGradient() {
|
|
254
|
-
|
|
255
|
-
return this.generateGradientTexture();
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
|
|
259
267
|
/** @see generateSolidColorTexture */
|
|
260
268
|
generateSolid() {
|
|
261
269
|
|
|
@@ -276,42 +284,43 @@ export class EnvironmentManager {
|
|
|
276
284
|
* Initialize the packed CDF storage buffer with placeholder data.
|
|
277
285
|
* Must be called before shader compilation so the node exists in the graph.
|
|
278
286
|
*
|
|
279
|
-
* 1×1
|
|
287
|
+
* 1×1 RGBA32F placeholder until a real env table is built (env IS is off meanwhile).
|
|
280
288
|
* @private
|
|
281
289
|
*/
|
|
282
290
|
_initCDFTexture() {
|
|
283
291
|
|
|
284
|
-
this.envCDFTexture = new DataTexture( new Float32Array(
|
|
292
|
+
this.envCDFTexture = new DataTexture( new Float32Array( 4 ), 1, 1, RGBAFormat, FloatType );
|
|
285
293
|
this.envCDFTexture.needsUpdate = true;
|
|
294
|
+
this._exactTable = null;
|
|
286
295
|
|
|
287
296
|
}
|
|
288
297
|
|
|
289
298
|
/**
|
|
290
|
-
* Rebuild the CDF texture from equirectHdrInfo
|
|
291
|
-
*
|
|
299
|
+
* Rebuild the CDF texture from equirectHdrInfo's table, laid out as packExactTable (EnvironmentExactTable.js)
|
|
300
|
+
* has it.
|
|
292
301
|
* @private
|
|
293
302
|
*/
|
|
294
303
|
_updateCDFTexture() {
|
|
295
304
|
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
if ( ! marginal || ! conditional ) return;
|
|
305
|
+
const info = this.equirectHdrInfo;
|
|
306
|
+
if ( ! info.exactConditional || ! ( info.exactWidth > 0 ) ) return;
|
|
299
307
|
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
308
|
+
const { data, width, height } = packExactTable( info );
|
|
309
|
+
if ( ! this.envCDFTexture?._isPhysicalSky ) this.envCDFTexture?.dispose?.();
|
|
310
|
+
this.envCDFTexture = new DataTexture( data, width, height, RGBAFormat, FloatType );
|
|
311
|
+
this.envCDFTexture.needsUpdate = true;
|
|
312
|
+
this._exactTable = { radianceIntegral: info.radianceIntegral };
|
|
305
313
|
|
|
306
|
-
|
|
307
|
-
data.set( conditional.subarray( cy * W, cy * W + W ), dstRow ); // conditional → columns [0,W)
|
|
308
|
-
data[ dstRow + W ] = marginal[ cy ]; // marginal → column W
|
|
314
|
+
}
|
|
309
315
|
|
|
310
|
-
|
|
316
|
+
/**
|
|
317
|
+
* The environment as a bidirectional light source: ∫ luminance dω of the map, before intensity, while the
|
|
318
|
+
* CDF texture carries its table; null otherwise.
|
|
319
|
+
* @returns {?{ radianceIntegral: number }}
|
|
320
|
+
*/
|
|
321
|
+
get exactTable() {
|
|
311
322
|
|
|
312
|
-
|
|
313
|
-
this.envCDFTexture = new DataTexture( data, texW, H, RedFormat, FloatType );
|
|
314
|
-
this.envCDFTexture.needsUpdate = true;
|
|
323
|
+
return this.scene.environment ? this._exactTable ?? null : null;
|
|
315
324
|
|
|
316
325
|
}
|
|
317
326
|
|
|
@@ -388,7 +397,6 @@ export class EnvironmentManager {
|
|
|
388
397
|
this._cdfSignature = null;
|
|
389
398
|
this._updateCDFTexture();
|
|
390
399
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
391
|
-
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
392
400
|
return;
|
|
393
401
|
|
|
394
402
|
}
|
|
@@ -406,7 +414,6 @@ export class EnvironmentManager {
|
|
|
406
414
|
this._cdfSignature = null;
|
|
407
415
|
this._updateCDFTexture();
|
|
408
416
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
409
|
-
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
410
417
|
return;
|
|
411
418
|
|
|
412
419
|
}
|
|
@@ -436,7 +443,6 @@ export class EnvironmentManager {
|
|
|
436
443
|
|
|
437
444
|
this._updateCDFTexture();
|
|
438
445
|
this.uniforms.set( 'envTotalSum', this.equirectHdrInfo.totalSum );
|
|
439
|
-
this.uniforms.set( 'envCompensationDelta', this.equirectHdrInfo.compensationDelta );
|
|
440
446
|
|
|
441
447
|
const { width, height } = this.equirectHdrInfo;
|
|
442
448
|
if ( width && height ) {
|
|
@@ -455,7 +461,6 @@ export class EnvironmentManager {
|
|
|
455
461
|
this._cdfSignature = null;
|
|
456
462
|
log.error( 'CDF build failed:', error );
|
|
457
463
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
458
|
-
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
459
464
|
|
|
460
465
|
}
|
|
461
466
|
|
|
@@ -517,7 +522,6 @@ export class EnvironmentManager {
|
|
|
517
522
|
this._cdfSignature = null;
|
|
518
523
|
this._updateCDFTexture();
|
|
519
524
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
520
|
-
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
521
525
|
|
|
522
526
|
}
|
|
523
527
|
|
|
@@ -547,7 +551,7 @@ export class EnvironmentManager {
|
|
|
547
551
|
|
|
548
552
|
/**
|
|
549
553
|
* Enter 'hdri' mode ahead of an async HDRI install, and drop the texture stashed by a
|
|
550
|
-
* previous setMode( '
|
|
554
|
+
* previous setMode( 'color' | 'procedural' ): a new HDRI makes it
|
|
551
555
|
* unreachable, so leaving it in place both leaks it and lets a setMode( 'hdri' )
|
|
552
556
|
* arriving mid-download restore it over the map we are about to install.
|
|
553
557
|
* @param {import('three').Texture} [incoming] - Never disposed, even if it is the stash.
|
|
@@ -576,38 +580,6 @@ export class EnvironmentManager {
|
|
|
576
580
|
|
|
577
581
|
// ===== SKY GENERATORS =====
|
|
578
582
|
|
|
579
|
-
/**
|
|
580
|
-
* Generate gradient sky texture and set as environment.
|
|
581
|
-
*/
|
|
582
|
-
async generateGradientTexture() {
|
|
583
|
-
|
|
584
|
-
if ( ! this.simpleSkyRenderer ) {
|
|
585
|
-
|
|
586
|
-
this.simpleSkyRenderer = new SimpleSky( 512, 256 );
|
|
587
|
-
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
const params = {
|
|
591
|
-
zenithColor: this.envParams.gradientZenithColor,
|
|
592
|
-
horizonColor: this.envParams.gradientHorizonColor,
|
|
593
|
-
groundColor: this.envParams.gradientGroundColor,
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
try {
|
|
597
|
-
|
|
598
|
-
const texture = this.simpleSkyRenderer.renderGradient( params );
|
|
599
|
-
texture._isGeneratedProcedural = true;
|
|
600
|
-
await this.setEnvironmentMap( texture );
|
|
601
|
-
this.uniforms.set( 'hasSun', 0 );
|
|
602
|
-
|
|
603
|
-
} catch ( error ) {
|
|
604
|
-
|
|
605
|
-
log.error( 'gradient sky generation failed:', error );
|
|
606
|
-
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
}
|
|
610
|
-
|
|
611
583
|
/**
|
|
612
584
|
* Generate solid color sky texture and set as environment.
|
|
613
585
|
*/
|
|
@@ -645,6 +617,29 @@ export class EnvironmentManager {
|
|
|
645
617
|
*/
|
|
646
618
|
generateProceduralSkyTexture() {
|
|
647
619
|
|
|
620
|
+
if ( ! this.ProceduralSky && this._loadProceduralSky ) {
|
|
621
|
+
|
|
622
|
+
this._proceduralSkyLoading ??= this._loadProceduralSky().then( ( Sky ) => {
|
|
623
|
+
|
|
624
|
+
this._proceduralSkyLoading = null;
|
|
625
|
+
if ( ! this.ProceduralSky ) this.ProceduralSky = Sky;
|
|
626
|
+
|
|
627
|
+
} );
|
|
628
|
+
return this._proceduralSkyLoading.then( () => this.generateProceduralSkyTexture() );
|
|
629
|
+
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if ( ! this.ProceduralSky ) {
|
|
633
|
+
|
|
634
|
+
this.issues?.record(
|
|
635
|
+
ISSUE_CODES.CAPABILITY_MISSING,
|
|
636
|
+
'procedural mode needs the physical sky: environmentManager.setProceduralSky( PhysicalSky ), from rayzee/addons/physical-sky',
|
|
637
|
+
{ capability: 'physical-sky' }
|
|
638
|
+
);
|
|
639
|
+
return Promise.resolve();
|
|
640
|
+
|
|
641
|
+
}
|
|
642
|
+
|
|
648
643
|
this._skyRequested = true;
|
|
649
644
|
this._skyCaughtUp ??= new Promise( resolve => void ( this._resolveSky = resolve ) );
|
|
650
645
|
this._pumpSky();
|
|
@@ -688,7 +683,7 @@ export class EnvironmentManager {
|
|
|
688
683
|
|
|
689
684
|
}
|
|
690
685
|
|
|
691
|
-
const sky = this.physicalSky ??= new
|
|
686
|
+
const sky = this.physicalSky ??= new this.ProceduralSky( SKY_WIDTH, SKY_HEIGHT );
|
|
692
687
|
const albedo = p.skyGroundAlbedo;
|
|
693
688
|
const bake = ++ this._skyBakes;
|
|
694
689
|
const latest = () => bake === this._skyBakes && ! this._skyRequested;
|
|
@@ -710,12 +705,12 @@ export class EnvironmentManager {
|
|
|
710
705
|
this._installSky( texture, cdfTexture );
|
|
711
706
|
|
|
712
707
|
// Frames until they land normalise by an older bake's.
|
|
713
|
-
const { totalSum,
|
|
708
|
+
const { totalSum, radianceIntegral } = await stats;
|
|
714
709
|
if ( p.mode === 'procedural' && sky === this.physicalSky && bake > this._skyStatsBake ) {
|
|
715
710
|
|
|
716
711
|
this._skyStatsBake = bake;
|
|
717
712
|
this.uniforms.set( 'envTotalSum', totalSum );
|
|
718
|
-
this.
|
|
713
|
+
if ( this._exactTable?.sky ) this._exactTable.radianceIntegral = radianceIntegral;
|
|
719
714
|
if ( latest() ) this._notifyReset();
|
|
720
715
|
|
|
721
716
|
}
|
|
@@ -736,6 +731,32 @@ export class EnvironmentManager {
|
|
|
736
731
|
|
|
737
732
|
}
|
|
738
733
|
|
|
734
|
+
/**
|
|
735
|
+
* Installs the class that bakes 'procedural' mode — `PhysicalSky` from rayzee/addons/physical-sky: constructed with
|
|
736
|
+
* (width, height), `bake( renderer, params )` returns `{ texture, cdfTexture, sun, stats }`, and `dispose( renderer )`.
|
|
737
|
+
* @param {?Function} Sky
|
|
738
|
+
*/
|
|
739
|
+
setProceduralSky( Sky ) {
|
|
740
|
+
|
|
741
|
+
this._loadProceduralSky = null;
|
|
742
|
+
if ( Sky === this.ProceduralSky ) return;
|
|
743
|
+
this._releaseSky();
|
|
744
|
+
this.ProceduralSky = Sky;
|
|
745
|
+
if ( Sky && this.envParams.mode === 'procedural' ) this.generateProceduralSkyTexture();
|
|
746
|
+
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Installs the physical sky on first use: `load()` resolves to the class setProceduralSky() takes, the first time
|
|
751
|
+
* 'procedural' mode is baked.
|
|
752
|
+
* @param {function(): Promise<Function>} load
|
|
753
|
+
*/
|
|
754
|
+
setProceduralSkyLoader( load ) {
|
|
755
|
+
|
|
756
|
+
this._loadProceduralSky = load;
|
|
757
|
+
|
|
758
|
+
}
|
|
759
|
+
|
|
739
760
|
/** @private */
|
|
740
761
|
_installSky( texture, cdfTexture ) {
|
|
741
762
|
|
|
@@ -750,6 +771,7 @@ export class EnvironmentManager {
|
|
|
750
771
|
|
|
751
772
|
// So an HDRI coming back rebuilds its own table.
|
|
752
773
|
this._cdfSignature = null;
|
|
774
|
+
if ( ! this._exactTable?.sky ) this._exactTable = { radianceIntegral: 0, sky: true };
|
|
753
775
|
texture._isGeneratedProcedural = true;
|
|
754
776
|
this.scene.environment = texture;
|
|
755
777
|
this.environmentTexture = texture;
|
|
@@ -798,8 +820,8 @@ export class EnvironmentManager {
|
|
|
798
820
|
/** @private */
|
|
799
821
|
_calculateInitialSunDirection() {
|
|
800
822
|
|
|
801
|
-
const azimuth =
|
|
802
|
-
const elevation =
|
|
823
|
+
const azimuth = SKY_DEFAULTS.skySunAzimuth * ( Math.PI / 180 );
|
|
824
|
+
const elevation = SKY_DEFAULTS.skySunElevation * ( Math.PI / 180 );
|
|
803
825
|
return new Vector3(
|
|
804
826
|
Math.cos( elevation ) * Math.sin( azimuth ),
|
|
805
827
|
Math.sin( elevation ),
|
|
@@ -71,6 +71,7 @@ export class GoboManager {
|
|
|
71
71
|
cnv.width = width;
|
|
72
72
|
cnv.height = height;
|
|
73
73
|
const ctx = cnv.getContext( '2d', { willReadFrequently: true } );
|
|
74
|
+
let lastYield = performance.now();
|
|
74
75
|
|
|
75
76
|
for ( let i = 0; i < depth; i ++ ) {
|
|
76
77
|
|
|
@@ -79,6 +80,14 @@ export class GoboManager {
|
|
|
79
80
|
const img = ctx.getImageData( 0, 0, width, height );
|
|
80
81
|
data.set( img.data, i * width * height * 4 );
|
|
81
82
|
|
|
83
|
+
// Each first draw decodes its image, so the library packs in short tasks.
|
|
84
|
+
if ( performance.now() - lastYield > 16 ) {
|
|
85
|
+
|
|
86
|
+
await new Promise( resolve => setTimeout( resolve, 0 ) );
|
|
87
|
+
lastYield = performance.now();
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
const tex = new DataArrayTexture( data, width, height, depth );
|
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
import { StorageInstancedBufferAttribute } from 'three/webgpu';
|
|
11
11
|
import { storage } from 'three/tsl';
|
|
12
12
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from '../
|
|
13
|
+
TRIANGLE_DATA_LAYOUT as T, TRI_MATERIAL_MASK, TRI_SIDE_SHIFT, TRI_BLOCKER_SHIFT, shadowBlockerBits,
|
|
14
|
+
MATERIAL_DATA_LAYOUT as M, normalizeAttenuationDistance,
|
|
15
|
+
} from '../Processor/BufferLayout.js';
|
|
16
16
|
import { packMaterial, UNIT_RANGE_PROPERTIES, clampUnit } from '../Processor/MaterialPacking.js';
|
|
17
17
|
import { resolveMaterialTextures, MATERIAL_VALUE_SOURCE } from '../Processor/GeometryExtractor.js';
|
|
18
18
|
import { convertLinearTriple, convertLinearTriples, getWorkingMatrixSpace } from '../Color/WorkingMatrix.js';
|
|
19
19
|
import { createLogger, fmt } from '../utils/Logger.js';
|
|
20
20
|
import { toPortable } from '../SceneState/portable.js';
|
|
21
|
+
import { MATERIAL_LAYERS } from '../TSL/SceneResources.js';
|
|
21
22
|
|
|
22
23
|
/** Material buffers already moved into the working space, so a re-init cannot convert twice. */
|
|
23
24
|
const convertedBuffers = new WeakSet();
|
|
@@ -41,6 +42,7 @@ const TEXTURE_POOLS = [
|
|
|
41
42
|
[ 'displacementMap', false ], [ 'anisotropyMap', false ], [ 'transmissionMap', false ],
|
|
42
43
|
[ 'clearcoatMap', false ], [ 'clearcoatRoughnessMap', false ], [ 'sheenRoughnessMap', false ],
|
|
43
44
|
[ 'iridescenceMap', false ], [ 'iridescenceThicknessMap', false ], [ 'specularIntensityMap', false ],
|
|
45
|
+
[ 'diffuseTransmissionColorMap', true ], [ 'diffuseTransmissionMap', false ],
|
|
44
46
|
];
|
|
45
47
|
|
|
46
48
|
// Scalar slots readable via getMaterialProperty().
|
|
@@ -67,6 +69,7 @@ const SCALAR_PROPERTY_OFFSETS = {
|
|
|
67
69
|
subsurfaceAnisotropy: M.SUBSURFACE_ANISOTROPY,
|
|
68
70
|
anisotropy: M.ANISOTROPY,
|
|
69
71
|
anisotropyRotation: M.ANISOTROPY_ROTATION, // radians, unlike the degrees hosts usually show
|
|
72
|
+
diffuseTransmission: M.DIFFUSE_TRANSMISSION,
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
export class MaterialDataManager {
|
|
@@ -119,6 +122,7 @@ export class MaterialDataManager {
|
|
|
119
122
|
*/
|
|
120
123
|
static COLOR_OFFSETS = [
|
|
121
124
|
M.COLOR, M.EMISSIVE, M.ATTENUATION_COLOR, M.SHEEN_COLOR, M.SPECULAR_COLOR, M.SUBSURFACE_COLOR,
|
|
125
|
+
M.DIFFUSE_TRANSMISSION_COLOR,
|
|
122
126
|
].filter( o => Number.isInteger( o ) );
|
|
123
127
|
|
|
124
128
|
/**
|
|
@@ -186,6 +190,7 @@ export class MaterialDataManager {
|
|
|
186
190
|
this.materialCount = Math.floor( vec4Count / PIXELS_PER_MATERIAL );
|
|
187
191
|
this._sources = [ ...sources ];
|
|
188
192
|
this._hostSet = [];
|
|
193
|
+
this.callbacks.onMaterialFeaturesChanged?.();
|
|
189
194
|
log.debug( `${fmt.n( this.materialCount )} materials (storage buffer)` );
|
|
190
195
|
|
|
191
196
|
}
|
|
@@ -300,6 +305,26 @@ export class MaterialDataManager {
|
|
|
300
305
|
|
|
301
306
|
}
|
|
302
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Which MATERIAL_LAYERS some material uses (its factor above 0): the kernels compile the others out.
|
|
310
|
+
* @returns {Object<string, boolean>}
|
|
311
|
+
*/
|
|
312
|
+
materialLayers() {
|
|
313
|
+
|
|
314
|
+
const layers = Object.fromEntries( MATERIAL_LAYERS.map( ( layer ) => [ layer, false ] ) );
|
|
315
|
+
const data = this.materialStorageAttr?.array;
|
|
316
|
+
if ( ! data ) return layers;
|
|
317
|
+
for ( let i = 0; i < this.materialCount; i ++ ) {
|
|
318
|
+
|
|
319
|
+
const base = i * M.FLOATS_PER_MATERIAL;
|
|
320
|
+
for ( const layer of MATERIAL_LAYERS ) if ( data[ base + SCALAR_PROPERTY_OFFSETS[ layer ] ] > 0 ) layers[ layer ] = true;
|
|
321
|
+
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return layers;
|
|
325
|
+
|
|
326
|
+
}
|
|
327
|
+
|
|
303
328
|
/**
|
|
304
329
|
* Where a material property's value came from, as a MATERIAL_VALUE_SOURCE. `default` means the
|
|
305
330
|
* model never said and the engine filled it in.
|
|
@@ -466,6 +491,19 @@ export class MaterialDataManager {
|
|
|
466
491
|
case 'subsurfaceAnisotropy': data[ stride + M.SUBSURFACE_ANISOTROPY ] = value; break;
|
|
467
492
|
case 'anisotropy': data[ stride + M.ANISOTROPY ] = value; break;
|
|
468
493
|
case 'anisotropyRotation': data[ stride + M.ANISOTROPY_ROTATION ] = value; break;
|
|
494
|
+
case 'diffuseTransmission': data[ stride + M.DIFFUSE_TRANSMISSION ] = value; break;
|
|
495
|
+
case 'diffuseTransmissionColor':
|
|
496
|
+
if ( value.r !== undefined ) {
|
|
497
|
+
|
|
498
|
+
this._writeColor( data, stride + M.DIFFUSE_TRANSMISSION_COLOR, value.r, value.g, value.b );
|
|
499
|
+
|
|
500
|
+
} else if ( Array.isArray( value ) ) {
|
|
501
|
+
|
|
502
|
+
this._writeColor( data, stride + M.DIFFUSE_TRANSMISSION_COLOR, value[ 0 ], value[ 1 ], value[ 2 ] );
|
|
503
|
+
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
break;
|
|
469
507
|
case 'subsurfaceColor':
|
|
470
508
|
if ( value.r !== undefined ) {
|
|
471
509
|
|
|
@@ -510,6 +548,9 @@ export class MaterialDataManager {
|
|
|
510
548
|
|
|
511
549
|
}
|
|
512
550
|
|
|
551
|
+
// A material layer is compiled in only while some material uses it.
|
|
552
|
+
if ( MATERIAL_LAYERS.includes( property ) ) this.callbacks.onMaterialFeaturesChanged?.();
|
|
553
|
+
|
|
513
554
|
this._notifyReset();
|
|
514
555
|
|
|
515
556
|
}
|
|
@@ -545,6 +586,7 @@ export class MaterialDataManager {
|
|
|
545
586
|
// Both read back the block, so they must follow the write.
|
|
546
587
|
this._patchTriangleSideForMaterial( materialIndex, data[ base + M.SIDE ] );
|
|
547
588
|
this._recomputeOpaqueBlockerForMaterial( materialIndex );
|
|
589
|
+
this.callbacks.onMaterialFeaturesChanged?.();
|
|
548
590
|
|
|
549
591
|
this.materialStorageAttr.needsUpdate = true;
|
|
550
592
|
this._notifyReset();
|
|
@@ -672,43 +714,12 @@ export class MaterialDataManager {
|
|
|
672
714
|
|
|
673
715
|
}
|
|
674
716
|
|
|
675
|
-
/**
|
|
676
|
-
* One side for several materials in a single pass over the triangles; per-material edits scan
|
|
677
|
-
* every triangle once each.
|
|
678
|
-
* @param {Iterable<number>} materialIndices
|
|
679
|
-
* @param {number} side - 0 front, 1 back, 2 double, MATERIAL_SIDE_CUTAWAY
|
|
680
|
-
*/
|
|
681
|
-
setMaterialsSide( materialIndices, side ) {
|
|
682
|
-
|
|
683
|
-
if ( ! this.materialStorageAttr ) return;
|
|
684
|
-
|
|
685
|
-
const indices = new Set( materialIndices );
|
|
686
|
-
const data = this.materialStorageAttr.array;
|
|
687
|
-
for ( const i of indices ) {
|
|
688
|
-
|
|
689
|
-
data[ i * M.FLOATS_PER_MATERIAL + M.SIDE ] = side;
|
|
690
|
-
( this._hostSet[ i ] ??= new Map() ).set( 'side', side );
|
|
691
|
-
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
this._patchTriangleFlagForMaterials( indices, TRI_SIDE_SHIFT, 2, side );
|
|
695
|
-
this.materialStorageAttr.needsUpdate = true;
|
|
696
|
-
this._notifyReset();
|
|
697
|
-
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
_patchTriangleFlagForMaterial( materialIndex, shift, width, value ) {
|
|
701
|
-
|
|
702
|
-
this._patchTriangleFlagForMaterials( new Set( [ materialIndex ] ), shift, width, value );
|
|
703
|
-
|
|
704
|
-
}
|
|
705
|
-
|
|
706
717
|
/**
|
|
707
718
|
* Generic helper: rewrite `width` bits at `shift` in the flags lane of every triangle
|
|
708
|
-
* whose materialIndex
|
|
719
|
+
* whose materialIndex matches, then fire onTriangleDataChanged.
|
|
709
720
|
* @private
|
|
710
721
|
*/
|
|
711
|
-
|
|
722
|
+
_patchTriangleFlagForMaterial( materialIndex, shift, width, value ) {
|
|
712
723
|
|
|
713
724
|
const triInfo = this.callbacks.getTriangleData?.();
|
|
714
725
|
// Chunked past the ~2 GB array cap; a flat array is the single-chunk case.
|
|
@@ -725,7 +736,7 @@ export class MaterialDataManager {
|
|
|
725
736
|
|
|
726
737
|
const triData = records ? records.chunkFor( i ) : flat;
|
|
727
738
|
const base = records ? records.baseOf( i ) : i * stride;
|
|
728
|
-
if (
|
|
739
|
+
if ( ( triData[ base + TRI_FLAGS_OFFSET ] & TRI_MATERIAL_MASK ) === materialIndex ) {
|
|
729
740
|
|
|
730
741
|
triData[ base + TRI_FLAGS_OFFSET ] = ( ( triData[ base + TRI_FLAGS_OFFSET ] & ~ mask ) | bits ) >>> 0;
|
|
731
742
|
patched ++;
|