rayzee 9.4.0 → 9.4.2
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 +3 -4
- package/dist/rayzee.es.js +30 -67
- package/dist/rayzee.umd.js +5 -5
- package/package.json +1 -1
- package/src/EngineDefaults.js +1 -6
- package/src/PathTracerApp.js +1 -1
- package/src/Processor/SimpleSky.js +1 -62
- package/src/managers/CameraManager.js +55 -34
- package/src/managers/EnvironmentManager.js +9 -58
package/package.json
CHANGED
package/src/EngineDefaults.js
CHANGED
|
@@ -91,12 +91,7 @@ export const ENGINE_DEFAULTS = {
|
|
|
91
91
|
globalIlluminationIntensity: 1,
|
|
92
92
|
|
|
93
93
|
// Environment Mode System
|
|
94
|
-
environmentMode: 'hdri', // 'hdri' | 'procedural' | '
|
|
95
|
-
|
|
96
|
-
// Gradient Sky Colors
|
|
97
|
-
gradientZenithColor: '#0077BE',
|
|
98
|
-
gradientHorizonColor: '#87CEEB',
|
|
99
|
-
gradientGroundColor: '#654321',
|
|
94
|
+
environmentMode: 'hdri', // 'hdri' | 'procedural' | 'color'
|
|
100
95
|
|
|
101
96
|
// Solid Color Sky
|
|
102
97
|
solidSkyColor: '#87CEEB',
|
package/src/PathTracerApp.js
CHANGED
|
@@ -1408,7 +1408,7 @@ export class PathTracerApp extends EventDispatcher {
|
|
|
1408
1408
|
this._tagPrimarySceneObject();
|
|
1409
1409
|
|
|
1410
1410
|
const timer = new BuildTimer( '', { namespace: 'scene', level: 'info' } );
|
|
1411
|
-
// meshScene.environment is the HDRI slot: a sky
|
|
1411
|
+
// meshScene.environment is the HDRI slot: a sky or colour in use outlives the model.
|
|
1412
1412
|
const hdri = () => this.stages.pathTracer.environment.envParams.mode === 'hdri' ? this.meshScene.environment : null;
|
|
1413
1413
|
const environmentTexture = hdri();
|
|
1414
1414
|
|
|
@@ -6,12 +6,11 @@ import {
|
|
|
6
6
|
/**
|
|
7
7
|
* SimpleSky
|
|
8
8
|
*
|
|
9
|
-
* CPU-based
|
|
9
|
+
* CPU-based solid colour environment texture generator.
|
|
10
10
|
* Produces a DataTexture directly — no render targets, no GPU readback,
|
|
11
11
|
* no resource lifecycle issues with the WebGPU backend.
|
|
12
12
|
*
|
|
13
13
|
* Public API matches SimpleSkyRenderer:
|
|
14
|
-
* renderGradient(params) → texture
|
|
15
14
|
* renderSolid(params) → texture
|
|
16
15
|
*/
|
|
17
16
|
|
|
@@ -36,66 +35,6 @@ export class SimpleSky {
|
|
|
36
35
|
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
/**
|
|
40
|
-
* Generate a three-colour vertical gradient sky.
|
|
41
|
-
* @param {Object} params - { zenithColor, horizonColor, groundColor } (Three.js Color)
|
|
42
|
-
* @returns {DataTexture} Equirectangular gradient texture
|
|
43
|
-
*/
|
|
44
|
-
renderGradient( params ) {
|
|
45
|
-
|
|
46
|
-
const startTime = performance.now();
|
|
47
|
-
const { width, height } = this;
|
|
48
|
-
const pixels = this._pixels;
|
|
49
|
-
|
|
50
|
-
const zr = params.zenithColor.r, zg = params.zenithColor.g, zb = params.zenithColor.b;
|
|
51
|
-
const hr = params.horizonColor.r, hg = params.horizonColor.g, hb = params.horizonColor.b;
|
|
52
|
-
const gr = params.groundColor.r, gg = params.groundColor.g, gb = params.groundColor.b;
|
|
53
|
-
|
|
54
|
-
for ( let y = 0; y < height; y ++ ) {
|
|
55
|
-
|
|
56
|
-
const t = ( y + 0.5 ) / height;
|
|
57
|
-
let r, g, b;
|
|
58
|
-
|
|
59
|
-
if ( t > 0.5 ) {
|
|
60
|
-
|
|
61
|
-
// Top half: horizon → zenith
|
|
62
|
-
const blend = ( t - 0.5 ) * 2.0;
|
|
63
|
-
r = hr + ( zr - hr ) * blend;
|
|
64
|
-
g = hg + ( zg - hg ) * blend;
|
|
65
|
-
b = hb + ( zb - hb ) * blend;
|
|
66
|
-
|
|
67
|
-
} else {
|
|
68
|
-
|
|
69
|
-
// Bottom half: ground → horizon
|
|
70
|
-
const blend = t * 2.0;
|
|
71
|
-
r = gr + ( hr - gr ) * blend;
|
|
72
|
-
g = gg + ( hg - gg ) * blend;
|
|
73
|
-
b = gb + ( hb - gb ) * blend;
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
for ( let x = 0; x < width; x ++ ) {
|
|
78
|
-
|
|
79
|
-
const idx = ( y * width + x ) * 4;
|
|
80
|
-
pixels[ idx ] = r;
|
|
81
|
-
pixels[ idx + 1 ] = g;
|
|
82
|
-
pixels[ idx + 2 ] = b;
|
|
83
|
-
pixels[ idx + 3 ] = 1.0;
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this._texture.needsUpdate = true;
|
|
90
|
-
// Fresh linear Rec.709 pixels in a reused texture. Colour management records which space a
|
|
91
|
-
// texture's pixels hold so it never converts them twice; left in place, that record would
|
|
92
|
-
// claim these were already converted and they never would be.
|
|
93
|
-
delete this._texture.userData?.__rayzeeColorSpace;
|
|
94
|
-
this.lastRenderTime = performance.now() - startTime;
|
|
95
|
-
return this._texture;
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
38
|
/**
|
|
100
39
|
* Generate a uniform solid-colour sky.
|
|
101
40
|
* @param {Object} params - { color } (Three.js Color)
|
|
@@ -312,40 +312,7 @@ export class CameraManager extends EventDispatcher {
|
|
|
312
312
|
|
|
313
313
|
} else {
|
|
314
314
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
this.camera.position.copy( sourceCamera.position );
|
|
318
|
-
this.camera.quaternion.copy( sourceCamera.quaternion );
|
|
319
|
-
// An imported camera can carry a mirror (a negative axis scale) that no
|
|
320
|
-
// quaternion can express — a pbrt scene's `Scale -1 1 1`, for one. Copying
|
|
321
|
-
// pose alone would silently un-mirror the view.
|
|
322
|
-
this.camera.scale.copy( sourceCamera.scale );
|
|
323
|
-
if ( sourceCamera.isPerspectiveCamera ) this.camera.fov = sourceCamera.fov;
|
|
324
|
-
this.camera.near = sourceCamera.near;
|
|
325
|
-
this.camera.far = sourceCamera.far;
|
|
326
|
-
this.camera.updateProjectionMatrix();
|
|
327
|
-
this.camera.updateMatrixWorld( true );
|
|
328
|
-
|
|
329
|
-
// Restore the saved orbit target for user cameras; otherwise place it
|
|
330
|
-
// along the forward direction at the focus distance.
|
|
331
|
-
if ( this.controls ) {
|
|
332
|
-
|
|
333
|
-
const savedTarget = sourceCamera.userData?.__rayzeeOrbitTarget;
|
|
334
|
-
if ( savedTarget ) {
|
|
335
|
-
|
|
336
|
-
this.controls.target.copy( savedTarget );
|
|
337
|
-
|
|
338
|
-
} else {
|
|
339
|
-
|
|
340
|
-
const forward = new Vector3( 0, 0, - 1 ).applyQuaternion( sourceCamera.quaternion );
|
|
341
|
-
const focusDist = focusDistance || 5.0;
|
|
342
|
-
this.controls.target.copy( this.camera.position ).addScaledVector( forward, focusDist );
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
this.controls.update();
|
|
347
|
-
|
|
348
|
-
}
|
|
315
|
+
this._placeAt( this.cameras[ index ], focusDistance );
|
|
349
316
|
|
|
350
317
|
}
|
|
351
318
|
|
|
@@ -370,6 +337,60 @@ export class CameraManager extends EventDispatcher {
|
|
|
370
337
|
|
|
371
338
|
}
|
|
372
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Puts the active camera back at the view it starts from: the default camera at the framing the
|
|
342
|
+
* model loaded with, any other at its own pose and lens. Its effects and projection stay.
|
|
343
|
+
*/
|
|
344
|
+
resetView() {
|
|
345
|
+
|
|
346
|
+
const source = this.currentCameraIndex > 0 ? this.cameras[ this.currentCameraIndex ] : null;
|
|
347
|
+
if ( ! source ) {
|
|
348
|
+
|
|
349
|
+
this.controls.reset();
|
|
350
|
+
return;
|
|
351
|
+
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
this._placeAt( source, this._getSettings?.( 'focusDistance' ) );
|
|
355
|
+
const height = orthoHeightOf( source );
|
|
356
|
+
if ( this.camera.orthographic ) this._setView( true, height ? height / 2 : this.camera.orthoHalfHeight );
|
|
357
|
+
this._onReset?.();
|
|
358
|
+
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// The view takes a camera's pose and lens, orbiting its saved target or a point ahead at the focus distance.
|
|
362
|
+
_placeAt( source, focusDistance ) {
|
|
363
|
+
|
|
364
|
+
this.camera.position.copy( source.position );
|
|
365
|
+
this.camera.quaternion.copy( source.quaternion );
|
|
366
|
+
// An imported camera can carry a mirror (a negative axis scale) that no
|
|
367
|
+
// quaternion can express — a pbrt scene's `Scale -1 1 1`, for one. Copying
|
|
368
|
+
// pose alone would silently un-mirror the view.
|
|
369
|
+
this.camera.scale.copy( source.scale );
|
|
370
|
+
if ( source.isPerspectiveCamera ) this.camera.fov = source.fov;
|
|
371
|
+
this.camera.near = source.near;
|
|
372
|
+
this.camera.far = source.far;
|
|
373
|
+
this.camera.updateProjectionMatrix();
|
|
374
|
+
this.camera.updateMatrixWorld( true );
|
|
375
|
+
|
|
376
|
+
if ( ! this.controls ) return;
|
|
377
|
+
|
|
378
|
+
const savedTarget = source.userData?.__rayzeeOrbitTarget;
|
|
379
|
+
if ( savedTarget ) {
|
|
380
|
+
|
|
381
|
+
this.controls.target.copy( savedTarget );
|
|
382
|
+
|
|
383
|
+
} else {
|
|
384
|
+
|
|
385
|
+
const forward = new Vector3( 0, 0, - 1 ).applyQuaternion( source.quaternion );
|
|
386
|
+
this.controls.target.copy( this.camera.position ).addScaledVector( forward, focusDistance || 5.0 );
|
|
387
|
+
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
this.controls.update();
|
|
391
|
+
|
|
392
|
+
}
|
|
393
|
+
|
|
373
394
|
/**
|
|
374
395
|
* Makes the camera orthographic at `height`, or perspective for null, then hands the `cameraProjection`
|
|
375
396
|
* setting the outcome — after, so its handler finds the camera already there. A 360° panorama stays on
|
|
@@ -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
|
|
@@ -83,11 +83,6 @@ export class EnvironmentManager {
|
|
|
83
83
|
this.envParams = {
|
|
84
84
|
mode: 'hdri',
|
|
85
85
|
|
|
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
86
|
// Solid Color Sky
|
|
92
87
|
solidSkyColor: new Color( DEFAULT_STATE.solidSkyColor ),
|
|
93
88
|
|
|
@@ -116,9 +111,9 @@ export class EnvironmentManager {
|
|
|
116
111
|
// ===== MODE STATE MACHINE =====
|
|
117
112
|
|
|
118
113
|
/**
|
|
119
|
-
* Switches the environment mode (hdri,
|
|
114
|
+
* Switches the environment mode (hdri, color, procedural — the physical sky).
|
|
120
115
|
* Preserves the HDRI texture when switching away, restores when switching back.
|
|
121
|
-
* @param {'hdri'|'
|
|
116
|
+
* @param {'hdri'|'color'|'procedural'} mode
|
|
122
117
|
*/
|
|
123
118
|
async setMode( mode ) {
|
|
124
119
|
|
|
@@ -132,11 +127,7 @@ export class EnvironmentManager {
|
|
|
132
127
|
|
|
133
128
|
}
|
|
134
129
|
|
|
135
|
-
if ( mode === '
|
|
136
|
-
|
|
137
|
-
await this.generateGradientTexture();
|
|
138
|
-
|
|
139
|
-
} else if ( mode === 'color' ) {
|
|
130
|
+
if ( mode === 'color' ) {
|
|
140
131
|
|
|
141
132
|
await this.generateSolidColorTexture();
|
|
142
133
|
|
|
@@ -185,9 +176,6 @@ export class EnvironmentManager {
|
|
|
185
176
|
return {
|
|
186
177
|
mode: p.mode,
|
|
187
178
|
hdri: this.hdriSource,
|
|
188
|
-
gradientZenithColor: p.gradientZenithColor.toArray(),
|
|
189
|
-
gradientHorizonColor: p.gradientHorizonColor.toArray(),
|
|
190
|
-
gradientGroundColor: p.gradientGroundColor.toArray(),
|
|
191
179
|
solidSkyColor: p.solidSkyColor.toArray(),
|
|
192
180
|
skyModel: 'atmosphere',
|
|
193
181
|
skySunDirection: p.skySunDirection.toArray(),
|
|
@@ -212,7 +200,7 @@ export class EnvironmentManager {
|
|
|
212
200
|
const p = this.envParams;
|
|
213
201
|
// Sessions saved before the physical sky gave the same names other meanings.
|
|
214
202
|
const atmosphere = state.skyModel === 'atmosphere';
|
|
215
|
-
const colors = [ '
|
|
203
|
+
const colors = [ 'solidSkyColor', 'skySunDirection' ];
|
|
216
204
|
for ( const key of atmosphere ? [ ...colors, 'skyGroundAlbedo' ] : colors ) {
|
|
217
205
|
|
|
218
206
|
if ( Array.isArray( state[ key ] ) ) p[ key ].fromArray( state[ key ] );
|
|
@@ -229,7 +217,9 @@ export class EnvironmentManager {
|
|
|
229
217
|
|
|
230
218
|
}
|
|
231
219
|
|
|
232
|
-
|
|
220
|
+
// A session saved with the removed gradient sky keeps the sky it is already showing.
|
|
221
|
+
const known = [ 'hdri', 'color', 'procedural' ].includes( state.mode );
|
|
222
|
+
if ( known && ( state.mode !== 'hdri' || p.mode !== 'hdri' ) ) await this.setMode( state.mode );
|
|
233
223
|
|
|
234
224
|
}
|
|
235
225
|
|
|
@@ -249,13 +239,6 @@ export class EnvironmentManager {
|
|
|
249
239
|
|
|
250
240
|
}
|
|
251
241
|
|
|
252
|
-
/** @see generateGradientTexture */
|
|
253
|
-
generateGradient() {
|
|
254
|
-
|
|
255
|
-
return this.generateGradientTexture();
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
|
|
259
242
|
/** @see generateSolidColorTexture */
|
|
260
243
|
generateSolid() {
|
|
261
244
|
|
|
@@ -547,7 +530,7 @@ export class EnvironmentManager {
|
|
|
547
530
|
|
|
548
531
|
/**
|
|
549
532
|
* Enter 'hdri' mode ahead of an async HDRI install, and drop the texture stashed by a
|
|
550
|
-
* previous setMode( '
|
|
533
|
+
* previous setMode( 'color' | 'procedural' ): a new HDRI makes it
|
|
551
534
|
* unreachable, so leaving it in place both leaks it and lets a setMode( 'hdri' )
|
|
552
535
|
* arriving mid-download restore it over the map we are about to install.
|
|
553
536
|
* @param {import('three').Texture} [incoming] - Never disposed, even if it is the stash.
|
|
@@ -576,38 +559,6 @@ export class EnvironmentManager {
|
|
|
576
559
|
|
|
577
560
|
// ===== SKY GENERATORS =====
|
|
578
561
|
|
|
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
562
|
/**
|
|
612
563
|
* Generate solid color sky texture and set as environment.
|
|
613
564
|
*/
|