@gnsx/three 0.184.8 → 0.184.10

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.
@@ -1,4 +1,8 @@
1
- import { LightsNode, NodeUtils, warn } from 'three/webgpu';
1
+ import {
2
+ LightsNode,
3
+ NodeUtils,
4
+ warn
5
+ } from 'three/webgpu';
2
6
  import { nodeObject } from 'three/tsl';
3
7
 
4
8
  import AmbientLightDataNode from './data/AmbientLightDataNode.js';
@@ -145,6 +149,16 @@ class DynamicLightsNode extends LightsNode {
145
149
 
146
150
  }
147
151
 
152
+ // WITH_GENESYS
153
+ for ( let i = 0; i < this._lightProbeGrids.length; i ++ ) {
154
+
155
+ const lightProbeGrid = this._lightProbeGrids[ i ];
156
+
157
+ _hashData.push( lightProbeGrid.id );
158
+
159
+ }
160
+ // !WITH_GENESYS
161
+
148
162
  const cacheKey = NodeUtils.hashArray( _hashData );
149
163
 
150
164
  _hashData.length = 0;
@@ -230,6 +244,10 @@ class DynamicLightsNode extends LightsNode {
230
244
 
231
245
  }
232
246
 
247
+ // WITH_GENESYS
248
+ this._appendLightProbeGridNode( lightNodes );
249
+ // !WITH_GENESYS
250
+
233
251
  this._lightNodes = lightNodes;
234
252
 
235
253
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gnsx/three",
3
- "version": "0.184.8",
3
+ "version": "0.184.10",
4
4
  "description": "JavaScript 3D library",
5
5
  "type": "module",
6
6
  "main": "./build/three.cjs",
package/src/Three.TSL.js CHANGED
@@ -202,6 +202,10 @@ export const getCurrentStack = TSL.getCurrentStack;
202
202
  export const getDirection = TSL.getDirection;
203
203
  export const getDistanceAttenuation = TSL.getDistanceAttenuation;
204
204
  export const getGeometryRoughness = TSL.getGeometryRoughness;
205
+ // WITH_GENESYS
206
+ export const getLightProbeGridIrradiance = TSL.getLightProbeGridIrradiance;
207
+ export const getLightProbeGridIrradianceAtUV = TSL.getLightProbeGridIrradianceAtUV;
208
+ // !WITH_GENESYS
205
209
  export const getNormalFromDepth = TSL.getNormalFromDepth;
206
210
  export const interleavedGradientNoise = TSL.interleavedGradientNoise;
207
211
  export const vogelDiskSample = TSL.vogelDiskSample;
@@ -116,6 +116,9 @@ export { default as IESSpotLightNode } from './lighting/IESSpotLightNode.js';
116
116
  export { default as IrradianceNode } from './lighting/IrradianceNode.js';
117
117
  export { default as LightingContextNode } from './lighting/LightingContextNode.js';
118
118
  export { default as LightingNode } from './lighting/LightingNode.js';
119
+ // WITH_GENESYS
120
+ export { default as LightProbeGridNode } from './lighting/LightProbeGridNode.js';
121
+ // !WITH_GENESYS
119
122
  export { default as LightProbeNode } from './lighting/LightProbeNode.js';
120
123
  export { default as LightsNode } from './lighting/LightsNode.js';
121
124
  // WITH_GENESYS
package/src/nodes/TSL.js CHANGED
@@ -168,6 +168,10 @@ export { default as V_GGX_SmithCorrelated } from './functions/BSDF/V_GGX_SmithCo
168
168
  export * from './lighting/LightUtils.js';
169
169
 
170
170
  export { default as getGeometryRoughness } from './functions/material/getGeometryRoughness.js';
171
+ // WITH_GENESYS
172
+ export { default as getLightProbeGridIrradiance } from './functions/material/getLightProbeGridIrradiance.js';
173
+ export { getLightProbeGridIrradianceAtUV } from './functions/material/getLightProbeGridIrradiance.js';
174
+ // !WITH_GENESYS
171
175
  export { default as getParallaxCorrectNormal } from './functions/material/getParallaxCorrectNormal.js';
172
176
  export { default as getRoughness } from './functions/material/getRoughness.js';
173
177
  export { default as getShIrradianceAt } from './functions/material/getShIrradianceAt.js';
@@ -126,7 +126,13 @@ class CubeTextureNode extends TextureNode {
126
126
 
127
127
  // rotate first
128
128
 
129
- uvNode = materialEnvRotation.mul( uvNode );
129
+ // WITH_GENESYS: Skip material/scene env rotation in compute — no material or scene context.
130
+ if ( builder.shaderStage !== 'compute' ) {
131
+
132
+ uvNode = materialEnvRotation.mul( uvNode );
133
+
134
+ }
135
+ // !WITH_GENESYS
130
136
 
131
137
  // flip
132
138
 
@@ -366,7 +366,27 @@ class TextureNode extends UniformNode {
366
366
 
367
367
  if ( this.updateMatrix === true ) {
368
368
 
369
- uvNode = this.getTransformedUV( uvNode );
369
+ // eslint-disable-next-line no-constant-condition
370
+ if ( true ) {
371
+
372
+ // WITH_GENESYS: Do not apply UV matrix to integer texel coords or storage textures.
373
+ const explicitUV = this.uvNode;
374
+ const explicitUVType = explicitUV ? explicitUV.getNodeType( builder ) : null;
375
+ const isIntegerTexelCoord = explicitUVType === 'uvec2' || explicitUVType === 'uvec3' || explicitUVType === 'ivec2' || explicitUVType === 'ivec3';
376
+ const isStorageTexture = texture.isStorageTexture === true;
377
+
378
+ if ( isIntegerTexelCoord === false && isStorageTexture === false ) {
379
+
380
+ uvNode = this.getTransformedUV( uvNode );
381
+
382
+ }
383
+ // !WITH_GENESYS
384
+
385
+ } else {
386
+
387
+ uvNode = this.getTransformedUV( uvNode );
388
+
389
+ }
370
390
 
371
391
  }
372
392
 
@@ -0,0 +1,68 @@
1
+ import { Fn, max, vec3 } from '../../tsl/TSLBase.js';
2
+
3
+ export const getLightProbeGridIrradianceAtUV = /*@__PURE__*/ Fn( ( { probesSH, probesResolution, gridUVW, worldNormal } ) => {
4
+
5
+ const res = probesResolution;
6
+ const uvw = gridUVW.toVar();
7
+
8
+ const nz = res.z;
9
+ const paddedSlices = nz.add( 2.0 );
10
+ const atlasDepth = paddedSlices.mul( 7.0 );
11
+ const uvZBase = uvw.z.mul( nz ).add( 1.0 );
12
+
13
+ const atlasUv = ( sliceOffset ) => vec3( uvw.x, uvw.y, uvZBase.add( paddedSlices.mul( sliceOffset ) ).div( atlasDepth ) );
14
+
15
+ const s0 = probesSH.sample( atlasUv( 0.0 ) );
16
+ const s1 = probesSH.sample( atlasUv( 1.0 ) );
17
+ const s2 = probesSH.sample( atlasUv( 2.0 ) );
18
+ const s3 = probesSH.sample( atlasUv( 3.0 ) );
19
+ const s4 = probesSH.sample( atlasUv( 4.0 ) );
20
+ const s5 = probesSH.sample( atlasUv( 5.0 ) );
21
+ const s6 = probesSH.sample( atlasUv( 6.0 ) );
22
+
23
+ const c0 = s0.xyz;
24
+ const c1 = vec3( s0.w, s1.x, s1.y );
25
+ const c2 = vec3( s1.z, s1.w, s2.x );
26
+ const c3 = s2.yzw;
27
+ const c4 = s3.xyz;
28
+ const c5 = vec3( s3.w, s4.x, s4.y );
29
+ const c6 = vec3( s4.z, s4.w, s5.x );
30
+ const c7 = s5.yzw;
31
+ const c8 = s6.xyz;
32
+
33
+ const x = worldNormal.x, y = worldNormal.y, z = worldNormal.z;
34
+
35
+ let result = c0.mul( 0.886227 );
36
+ result = result.add( c1.mul( 2.0 * 0.511664 ).mul( y ) );
37
+ result = result.add( c2.mul( 2.0 * 0.511664 ).mul( z ) );
38
+ result = result.add( c3.mul( 2.0 * 0.511664 ).mul( x ) );
39
+ result = result.add( c4.mul( 2.0 * 0.429043 ).mul( x ).mul( y ) );
40
+ result = result.add( c5.mul( 2.0 * 0.429043 ).mul( y ).mul( z ) );
41
+ result = result.add( c6.mul( z.mul( z ).mul( 0.743125 ).sub( 0.247708 ) ) );
42
+ result = result.add( c7.mul( 2.0 * 0.429043 ).mul( x ).mul( z ) );
43
+ result = result.add( c8.mul( 0.429043 ).mul( x.mul( x ).sub( y.mul( y ) ) ) );
44
+
45
+ return max( result, vec3( 0.0 ) );
46
+
47
+ } );
48
+
49
+ const getLightProbeGridIrradiance = /*@__PURE__*/ Fn( ( { probesSH, probesMin, probesMax, probesResolution, worldPosition, worldNormal } ) => {
50
+
51
+ const res = probesResolution;
52
+ const gridRange = probesMax.sub( probesMin ).toVar();
53
+ const resMinusOne = res.sub( 1.0 );
54
+ const probeSpacing = gridRange.div( resMinusOne ).toVar();
55
+
56
+ const samplePos = worldPosition.add( worldNormal.mul( probeSpacing ).mul( 0.5 ) );
57
+ const gridUVW = samplePos.sub( probesMin ).div( gridRange ).clamp( 0.0, 1.0 ).mul( resMinusOne.div( res ) ).add( vec3( 0.5 ).div( res ) );
58
+
59
+ return getLightProbeGridIrradianceAtUV( {
60
+ probesSH,
61
+ probesResolution,
62
+ gridUVW,
63
+ worldNormal
64
+ } );
65
+
66
+ } );
67
+
68
+ export default getLightProbeGridIrradiance;
@@ -0,0 +1,137 @@
1
+ import LightingNode from './LightingNode.js';
2
+ import { normalWorld } from '../accessors/Normal.js';
3
+ import { positionWorld } from '../accessors/Position.js';
4
+ import { texture3D } from '../accessors/Texture3DNode.js';
5
+ import { NodeUpdateType } from '../core/constants.js';
6
+ import { uniform } from '../core/UniformNode.js';
7
+ import getLightProbeGridIrradiance from '../functions/material/getLightProbeGridIrradiance.js';
8
+ import { FloatType, LinearFilter, RGBAFormat } from '../../constants.js';
9
+ import { Data3DTexture } from '../../textures/Data3DTexture.js';
10
+ import { Vector3 } from '../../math/Vector3.js';
11
+
12
+ const _objectPosition = /*@__PURE__*/ new Vector3();
13
+ const _emptyTexture = /*@__PURE__*/ new Data3DTexture( new Float32Array( 1 * 1 * 28 * 4 ), 1, 1, 28 );
14
+
15
+ _emptyTexture.format = RGBAFormat;
16
+ _emptyTexture.type = FloatType;
17
+ _emptyTexture.minFilter = LinearFilter;
18
+ _emptyTexture.magFilter = LinearFilter;
19
+ _emptyTexture.needsUpdate = true;
20
+
21
+ function findLightProbeGrid( volumes, object ) {
22
+
23
+ if ( volumes.length === 0 ) return null;
24
+
25
+ if ( volumes.length === 1 ) {
26
+
27
+ return volumes[ 0 ].texture !== null ? volumes[ 0 ] : null;
28
+
29
+ }
30
+
31
+ _objectPosition.setFromMatrixPosition( object.matrixWorld );
32
+
33
+ for ( let i = 0, l = volumes.length; i < l; i ++ ) {
34
+
35
+ const volume = volumes[ i ];
36
+
37
+ if ( volume.texture !== null && volume.boundingBox.containsPoint( _objectPosition ) ) return volume;
38
+
39
+ }
40
+
41
+ return null;
42
+
43
+ }
44
+
45
+ /**
46
+ * Adds diffuse irradiance from the active LightProbeGrid to WebGPU node materials.
47
+ *
48
+ * @augments LightingNode
49
+ */
50
+ class LightProbeGridNode extends LightingNode {
51
+
52
+ static get type() {
53
+
54
+ return 'LightProbeGridNode';
55
+
56
+ }
57
+
58
+ /**
59
+ * Constructs a new light probe grid node.
60
+ *
61
+ * @param {Array<Object3D>} [lightProbeGrids=[]] - Light probe grids collected from the scene.
62
+ */
63
+ constructor( lightProbeGrids = [] ) {
64
+
65
+ super();
66
+
67
+ /**
68
+ * This flag can be used for type testing.
69
+ *
70
+ * @type {boolean}
71
+ * @readonly
72
+ * @default true
73
+ */
74
+ this.isLightProbeGridNode = true;
75
+
76
+ this.lightProbeGrids = lightProbeGrids;
77
+ this.activeLightProbeGrid = null;
78
+
79
+ this.probesSH = texture3D( _emptyTexture );
80
+ this.probesMin = uniform( new Vector3() );
81
+ this.probesMax = uniform( new Vector3( 1, 1, 1 ) );
82
+ this.probesResolution = uniform( new Vector3( 2, 2, 2 ) );
83
+
84
+ this.updateType = NodeUpdateType.OBJECT;
85
+
86
+ }
87
+
88
+ update( frame ) {
89
+
90
+ const activeLightProbeGrid = findLightProbeGrid( this.lightProbeGrids, frame.object );
91
+
92
+ this.activeLightProbeGrid = activeLightProbeGrid;
93
+
94
+ if ( activeLightProbeGrid !== null ) {
95
+
96
+ activeLightProbeGrid.updateBoundingBox();
97
+
98
+ this.probesSH.value = activeLightProbeGrid.texture;
99
+ this.probesMin.value.copy( activeLightProbeGrid.boundingBox.min );
100
+ this.probesMax.value.copy( activeLightProbeGrid.boundingBox.max );
101
+ this.probesResolution.value.copy( activeLightProbeGrid.resolution );
102
+
103
+ } else {
104
+
105
+ this.probesSH.value = _emptyTexture;
106
+ this.probesMin.value.set( 0, 0, 0 );
107
+ this.probesMax.value.set( 1, 1, 1 );
108
+ this.probesResolution.value.set( 2, 2, 2 );
109
+
110
+ }
111
+
112
+ }
113
+
114
+ setup( builder ) {
115
+
116
+ const irradiance = getLightProbeGridIrradiance( {
117
+ probesSH: this.probesSH,
118
+ probesMin: this.probesMin,
119
+ probesMax: this.probesMax,
120
+ probesResolution: this.probesResolution,
121
+ worldPosition: positionWorld,
122
+ worldNormal: normalWorld
123
+ } );
124
+
125
+ builder.context.irradiance.addAssign( irradiance );
126
+
127
+ }
128
+
129
+ getHash() {
130
+
131
+ return `lightProbeGrid-${ this.lightProbeGrids.map( ( lightProbeGrid ) => lightProbeGrid.id ).join( ',' ) }`;
132
+
133
+ }
134
+
135
+ }
136
+
137
+ export default LightProbeGridNode;
@@ -2,6 +2,9 @@ import Node from '../core/Node.js';
2
2
  import { nodeObject, property, vec3 } from '../tsl/TSLBase.js';
3
3
  import { hashArray } from '../core/NodeUtils.js';
4
4
  import { warn } from '../../utils.js';
5
+ // WITH_GENESYS
6
+ import LightProbeGridNode from './LightProbeGridNode.js';
7
+ // !WITH_GENESYS
5
8
 
6
9
  const sortLights = ( lights ) => {
7
10
 
@@ -79,6 +82,25 @@ class LightsNode extends Node {
79
82
  */
80
83
  this._lights = [];
81
84
 
85
+ // WITH_GENESYS
86
+ /**
87
+ * A list of light probe grids collected from the scene.
88
+ *
89
+ * @private
90
+ * @type {Array<Object3D>}
91
+ */
92
+ this._lightProbeGrids = [];
93
+
94
+ /**
95
+ * Cached light probe grid node reused across {@link LightsNode#setupLightsNode} calls.
96
+ *
97
+ * @private
98
+ * @type {?LightProbeGridNode}
99
+ * @default null
100
+ */
101
+ this._lightProbeGridNode = null;
102
+ // !WITH_GENESYS
103
+
82
104
  /**
83
105
  * For each light in the scene, this node will create a
84
106
  * corresponding light node.
@@ -136,6 +158,18 @@ class LightsNode extends Node {
136
158
 
137
159
  }
138
160
 
161
+ // WITH_GENESYS
162
+ const lightProbeGrids = this._lightProbeGrids;
163
+
164
+ for ( let i = 0; i < lightProbeGrids.length; i ++ ) {
165
+
166
+ const lightProbeGrid = lightProbeGrids[ i ];
167
+
168
+ _hashData.push( lightProbeGrid.id );
169
+
170
+ }
171
+ // !WITH_GENESYS
172
+
139
173
  const cacheKey = hashArray( _hashData );
140
174
 
141
175
  _hashData.length = 0;
@@ -244,10 +278,44 @@ class LightsNode extends Node {
244
278
 
245
279
  }
246
280
 
281
+ // WITH_GENESYS
282
+ this._appendLightProbeGridNode( lightNodes );
283
+ // !WITH_GENESYS
284
+
247
285
  this._lightNodes = lightNodes;
248
286
 
249
287
  }
250
288
 
289
+ // WITH_GENESYS
290
+ /**
291
+ * Appends the cached {@link LightProbeGridNode} for the current probe grids.
292
+ *
293
+ * @private
294
+ * @param {Array<LightingNode>} lightNodes - The light nodes array being built.
295
+ */
296
+ _appendLightProbeGridNode( lightNodes ) {
297
+
298
+ if ( this._lightProbeGrids.length === 0 ) {
299
+
300
+ return;
301
+
302
+ }
303
+
304
+ if ( this._lightProbeGridNode === null ) {
305
+
306
+ this._lightProbeGridNode = new LightProbeGridNode( this._lightProbeGrids );
307
+
308
+ } else {
309
+
310
+ this._lightProbeGridNode.lightProbeGrids = this._lightProbeGrids;
311
+
312
+ }
313
+
314
+ lightNodes.push( this._lightProbeGridNode );
315
+
316
+ }
317
+ // !WITH_GENESYS
318
+
251
319
  /**
252
320
  * Sets up a direct light in the lighting model.
253
321
  *
@@ -394,6 +462,31 @@ class LightsNode extends Node {
394
462
 
395
463
  }
396
464
 
465
+ // WITH_GENESYS
466
+ /**
467
+ * Configures this node with an array of light probe grids.
468
+ *
469
+ * @param {Array<Object3D>} lightProbeGrids - An array of light probe grids.
470
+ * @return {LightsNode} A reference to this node.
471
+ */
472
+ setLightProbeGrids( lightProbeGrids ) {
473
+
474
+ this._lightProbeGrids = lightProbeGrids;
475
+
476
+ if ( this._lightProbeGridNode !== null ) {
477
+
478
+ this._lightProbeGridNode.lightProbeGrids = lightProbeGrids;
479
+
480
+ }
481
+
482
+ this._lightNodes = null;
483
+ this._lightNodesHash = null;
484
+
485
+ return this;
486
+
487
+ }
488
+ // !WITH_GENESYS
489
+
397
490
  /**
398
491
  * Returns an array of the scene's lights.
399
492
  *
@@ -412,7 +505,11 @@ class LightsNode extends Node {
412
505
  */
413
506
  get hasLights() {
414
507
 
415
- return this._lights.length > 0;
508
+ return this._lights.length > 0
509
+ // WITH_GENESYS
510
+ || this._lightProbeGrids.length > 0
511
+ // !WITH_GENESYS
512
+ ;
416
513
 
417
514
  }
418
515
 
@@ -44,6 +44,39 @@ class Background extends DataMap {
44
44
 
45
45
  }
46
46
 
47
+ // WITH_GENESYS
48
+ /**
49
+ * Disposes the renderer-owned background skybox mesh (material and geometry)
50
+ * for `scene` and clears cached mesh state.
51
+ *
52
+ * Does not dispose {@link Scene#background}.
53
+ *
54
+ * @param {Scene} scene - The scene.
55
+ */
56
+ disposeScene( scene ) {
57
+
58
+ if ( this.has( scene ) === false ) return;
59
+
60
+ const sceneData = this.get( scene );
61
+
62
+ const backgroundMesh = sceneData.backgroundMesh;
63
+
64
+ if ( backgroundMesh !== undefined ) {
65
+
66
+ this.renderer._objects.disposeObjectResources( backgroundMesh, scene );
67
+
68
+ backgroundMesh.material.dispose();
69
+ backgroundMesh.geometry.dispose();
70
+
71
+ delete sceneData.backgroundMesh;
72
+ delete sceneData.backgroundMeshNode;
73
+ delete sceneData.backgroundCacheKey;
74
+
75
+ }
76
+
77
+ }
78
+ // !WITH_GENESYS
79
+
47
80
  /**
48
81
  * Updates the background for the given scene. Depending on how `Scene.background`
49
82
  * or `Scene.backgroundNode` are configured, this method might configure a simple clear
@@ -161,6 +161,15 @@ class RenderList {
161
161
  */
162
162
  this.lightsArray = [];
163
163
 
164
+ // WITH_GENESYS
165
+ /**
166
+ * The scene's light probe grids stored in an array.
167
+ *
168
+ * @type {Array<Object3D>}
169
+ */
170
+ this.lightProbeGridsArray = [];
171
+ // !WITH_GENESYS
172
+
164
173
  /**
165
174
  * The scene.
166
175
  *
@@ -202,6 +211,9 @@ class RenderList {
202
211
  this.bundles.length = 0;
203
212
 
204
213
  this.lightsArray.length = 0;
214
+ // WITH_GENESYS
215
+ this.lightProbeGridsArray.length = 0;
216
+ // !WITH_GENESYS
205
217
 
206
218
  this.occlusionQueryCount = 0;
207
219
 
@@ -353,6 +365,19 @@ class RenderList {
353
365
 
354
366
  }
355
367
 
368
+ // WITH_GENESYS
369
+ /**
370
+ * Pushes a light probe grid into the render list.
371
+ *
372
+ * @param {Object3D} lightProbeGrid - The light probe grid.
373
+ */
374
+ pushLightProbeGrid( lightProbeGrid ) {
375
+
376
+ this.lightProbeGridsArray.push( lightProbeGrid );
377
+
378
+ }
379
+ // !WITH_GENESYS
380
+
356
381
  /**
357
382
  * Sorts the internal render lists.
358
383
  *
@@ -376,6 +401,9 @@ class RenderList {
376
401
  // update lights
377
402
 
378
403
  this.lightsNode.setLights( this.lightsArray );
404
+ // WITH_GENESYS
405
+ this.lightsNode.setLightProbeGrids( this.lightProbeGridsArray );
406
+ // !WITH_GENESYS
379
407
 
380
408
  // Clear references from inactive renderItems in the list
381
409
 
@@ -207,6 +207,53 @@ class RenderObjects {
207
207
 
208
208
  }
209
209
 
210
+ // WITH_GENESYS
211
+ /**
212
+ * Disposes every {@link RenderObject} associated with `scene`.
213
+ *
214
+ * @param {Scene} scene - The scene being removed.
215
+ */
216
+ disposeSceneResources( scene ) {
217
+
218
+ const renderObjects = Array.from( this._renderObjects );
219
+
220
+ for ( const renderObject of renderObjects ) {
221
+
222
+ if ( renderObject.scene === scene ) {
223
+
224
+ renderObject.dispose();
225
+
226
+ }
227
+
228
+ }
229
+
230
+ }
231
+
232
+ /**
233
+ * Disposes every {@link RenderObject} for `object` drawn with `scene`.
234
+ * Call before disposing a renderer-owned mesh (e.g. background skybox) so WebGPU
235
+ * bindings are released while the renderer keeps running.
236
+ *
237
+ * @param {Object3D} object - The 3D object.
238
+ * @param {Scene} scene - The scene reference used when the object was rendered.
239
+ */
240
+ disposeObjectResources( object, scene ) {
241
+
242
+ const renderObjects = Array.from( this._renderObjects );
243
+
244
+ for ( const renderObject of renderObjects ) {
245
+
246
+ if ( renderObject.object === object && renderObject.scene === scene ) {
247
+
248
+ renderObject.dispose();
249
+
250
+ }
251
+
252
+ }
253
+
254
+ }
255
+ // !WITH_GENESYS
256
+
210
257
  /**
211
258
  * Factory method for creating render objects with the given list of parameters.
212
259
  *
@@ -935,7 +935,11 @@ class Renderer {
935
935
 
936
936
  renderList.pushLight( object );
937
937
 
938
- }
938
+ } else if ( object.isLightProbeGrid && object.layers.test( camera.layers ) ) { // WITH_GENESYS
939
+
940
+ renderList.pushLightProbeGrid( object );
941
+
942
+ } // !WITH_GENESYS
939
943
 
940
944
  } );
941
945
 
@@ -2552,6 +2556,28 @@ class Renderer {
2552
2556
 
2553
2557
  }
2554
2558
 
2559
+ // WITH_GENESYS
2560
+ /**
2561
+ * Releases renderer resources scoped to `scene` when the scene is removed but
2562
+ * this renderer instance continues to run. Disposes matching {@link RenderObject}s,
2563
+ * the internal background skybox mesh, and cached background/environment nodes.
2564
+ *
2565
+ * Does not call `texture.dispose()` on {@link Scene#background} or
2566
+ * {@link Scene#environment}; the caller remains responsible for those textures.
2567
+ *
2568
+ * @param {Scene} scene - The scene being removed.
2569
+ */
2570
+ disposeSceneResources( scene ) {
2571
+
2572
+ if ( this._initialized !== true ) return;
2573
+
2574
+ this._objects.disposeSceneResources( scene );
2575
+ this._nodes.clearSceneBackgroundAndEnvironmentNodes( scene );
2576
+ this._background.disposeScene( scene );
2577
+
2578
+ }
2579
+ // !WITH_GENESYS
2580
+
2555
2581
  /**
2556
2582
  * Sets the given render target. Calling this method means the renderer does not
2557
2583
  * target the default framebuffer (meaning the canvas) anymore but a custom framebuffer.
@@ -3085,7 +3111,11 @@ class Renderer {
3085
3111
 
3086
3112
  renderList.pushLight( object );
3087
3113
 
3088
- } else if ( object.isSprite ) {
3114
+ } else if ( object.isLightProbeGrid ) { // WITH_GENESYS
3115
+
3116
+ renderList.pushLightProbeGrid( object );
3117
+
3118
+ } else if ( object.isSprite ) { // !WITH_GENESYS
3089
3119
 
3090
3120
  const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
3091
3121