Skip to content

Commit 8a318e4

Browse files
authored
NodeMaterialObserver: Add checking the lights (#31440)
* Revert "LightsNode: Honor map version in cache key. (#31396)" This reverts commit 2f1c6c0. * add lights check * add stats
1 parent 0b7bcc0 commit 8a318e4

File tree

3 files changed

+99
-4
lines changed

3 files changed

+99
-4
lines changed

examples/webgpu_lights_projector.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import * as THREE from 'three';
3434
import { Fn, color, mx_worley_noise_float, time } from 'three/tsl';
3535

36+
import Stats from 'three/addons/libs/stats.module.js';
37+
3638
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
3739

3840
import { PLYLoader } from 'three/addons/loaders/PLYLoader.js';
@@ -42,10 +44,17 @@
4244

4345
let projectorLight, lightHelper;
4446

47+
let stats;
48+
4549
init();
4650

4751
function init() {
4852

53+
// Stats
54+
55+
stats = new Stats();
56+
document.body.appendChild( stats.dom );
57+
4958
// Renderer
5059

5160
renderer = new THREE.WebGPURenderer( { antialias: true } );
@@ -281,6 +290,8 @@
281290

282291
const time = performance.now() / 3000;
283292

293+
stats.update();
294+
284295
projectorLight.position.x = Math.cos( time ) * 2.5;
285296
projectorLight.position.z = Math.sin( time ) * 2.5;
286297

src/materials/nodes/manager/NodeMaterialObserver.js

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ const refreshUniforms = [
5555
'transmissionMap'
5656
];
5757

58+
59+
/**
60+
* A WeakMap to cache lights data for node materials.
61+
* Cache lights data by render ID to avoid unnecessary recalculations.
62+
*
63+
* @private
64+
* @type {WeakMap<LightsNode,Object>}
65+
*/
66+
const _lightsCache = new WeakMap();
67+
5868
/**
5969
* This class is used by {@link WebGPURenderer} as management component.
6070
* It's primary purpose is to determine whether render objects require a
@@ -196,6 +206,8 @@ class NodeMaterialObserver {
196206

197207
}
198208

209+
data.lights = this.getLightsData( renderObject.lightsNode.getLights() );
210+
199211
this.renderObjects.set( renderObject, data );
200212

201213
}
@@ -299,9 +311,10 @@ class NodeMaterialObserver {
299311
* Returns `true` if the given render object has not changed its state.
300312
*
301313
* @param {RenderObject} renderObject - The render object.
314+
* @param {Array<Light>} lightsData - The current material lights.
302315
* @return {boolean} Whether the given render object has changed its state or not.
303316
*/
304-
equals( renderObject ) {
317+
equals( renderObject, lightsData ) {
305318

306319
const { object, material, geometry } = renderObject;
307320

@@ -462,6 +475,22 @@ class NodeMaterialObserver {
462475

463476
}
464477

478+
// lights
479+
480+
if ( renderObjectData.lights ) {
481+
482+
for ( let i = 0; i < lightsData.length; i ++ ) {
483+
484+
if ( renderObjectData.lights[ i ].map !== lightsData[ i ].map ) {
485+
486+
return false;
487+
488+
}
489+
490+
}
491+
492+
}
493+
465494
// center
466495

467496
if ( renderObjectData.center ) {
@@ -488,6 +517,61 @@ class NodeMaterialObserver {
488517

489518
}
490519

520+
/**
521+
* Returns the lights data for the given material lights.
522+
*
523+
* @param {Array<Light>} materialLights - The material lights.
524+
* @return {Array<Object>} The lights data for the given material lights.
525+
*/
526+
getLightsData( materialLights ) {
527+
528+
const lights = [];
529+
530+
for ( const light of materialLights ) {
531+
532+
if ( light.isSpotLight === true && light.map !== null ) {
533+
534+
// only add lights that have a map
535+
536+
lights.push( { map: light.map.version } );
537+
538+
}
539+
540+
}
541+
542+
return lights;
543+
544+
}
545+
546+
/**
547+
* Returns the lights for the given lights node and render ID.
548+
*
549+
* @param {LightsNode} lightsNode - The lights node.
550+
* @param {number} renderId - The render ID.
551+
* @return {Array} The lights for the given lights node and render ID.
552+
*/
553+
getLights( lightsNode, renderId ) {
554+
555+
if ( _lightsCache.has( lightsNode ) ) {
556+
557+
const cached = _lightsCache.get( lightsNode );
558+
559+
if ( cached.renderId === renderId ) {
560+
561+
return cached.lightsData;
562+
563+
}
564+
565+
}
566+
567+
const lightsData = this.getLightsData( lightsNode.getLights() );
568+
569+
_lightsCache.set( lightsNode, { renderId, lightsData } );
570+
571+
return lightsData;
572+
573+
}
574+
491575
/**
492576
* Checks if the given render object requires a refresh.
493577
*
@@ -516,7 +600,8 @@ class NodeMaterialObserver {
516600
if ( isStatic || isBundle )
517601
return false;
518602

519-
const notEqual = this.equals( renderObject ) !== true;
603+
const lightsData = this.getLights( renderObject.lightsNode, renderId );
604+
const notEqual = this.equals( renderObject, lightsData ) !== true;
520605

521606
return notEqual;
522607

src/nodes/lighting/LightsNode.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,9 @@ class LightsNode extends Node {
127127
if ( light.isSpotLight === true ) {
128128

129129
const hashMap = ( light.map !== null ) ? light.map.id : - 1;
130-
const hashMapVersion = ( light.map !== null ) ? light.map.version : - 1;
131130
const hashColorNode = ( light.colorNode ) ? light.colorNode.getCacheKey() : - 1;
132131

133-
_hashData.push( hashMap, hashMapVersion, hashColorNode );
132+
_hashData.push( hashMap, hashColorNode );
134133

135134
}
136135

0 commit comments

Comments
 (0)