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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rayzee",
3
- "version": "9.4.0",
3
+ "version": "9.4.2",
4
4
  "type": "module",
5
5
  "description": "Real-time WebGPU path tracing engine built on Three.js",
6
6
  "main": "dist/rayzee.umd.js",
@@ -91,12 +91,7 @@ export const ENGINE_DEFAULTS = {
91
91
  globalIlluminationIntensity: 1,
92
92
 
93
93
  // Environment Mode System
94
- environmentMode: 'hdri', // 'hdri' | 'procedural' | 'gradient' | 'color'
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',
@@ -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, gradient or colour in use outlives the model.
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 gradient and solid colour environment texture generator.
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
- const sourceCamera = this.cameras[ index ];
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/gradient/solid sky
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, gradient, color, procedural — the physical sky).
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'|'gradient'|'color'|'procedural'} mode
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 === 'gradient' ) {
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 = [ 'gradientZenithColor', 'gradientHorizonColor', 'gradientGroundColor', 'solidSkyColor', 'skySunDirection' ];
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
- if ( state.mode && ( state.mode !== 'hdri' || p.mode !== 'hdri' ) ) await this.setMode( state.mode );
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( 'gradient' | 'color' | 'procedural' ): a new HDRI makes it
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
  */