Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 79 additions & 42 deletions src/materials/nodes/manager/NodeMaterialObserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ const refreshUniforms = [
*/
const _lightsCache = new WeakMap();

/**
* Holds the material data for comparison.
*
* @private
* @type {WeakMap<Material,Object>}
*/
const _materialCache = new WeakMap();

/**
* This class is used by {@link WebGPURenderer} as management component.
* It's primary purpose is to determine whether render objects require a
Expand Down Expand Up @@ -166,10 +174,9 @@ class NodeMaterialObserver {

if ( data === undefined ) {

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

data = {
material: this.getMaterialData( material ),
geometry: {
id: geometry.id,
attributes: this.getAttributesData( geometry.attributes ),
Expand Down Expand Up @@ -198,7 +205,7 @@ class NodeMaterialObserver {

}

if ( data.material.transmission > 0 ) {
if ( renderObject.material.transmission > 0 ) {

const { width, height } = renderObject.context;

Expand Down Expand Up @@ -277,32 +284,40 @@ class NodeMaterialObserver {
*/
getMaterialData( material ) {

const data = {};
let data = _materialCache.get( material );

for ( const property of this.refreshUniforms ) {
if ( data === undefined ) {

const value = material[ property ];
data = { _renderId: - 1, _equal: false };

if ( value === null || value === undefined ) continue;
for ( const property of this.refreshUniforms ) {

if ( typeof value === 'object' && value.clone !== undefined ) {
const value = material[ property ];

if ( value.isTexture === true ) {
if ( value === null || value === undefined ) continue;

data[ property ] = { id: value.id, version: value.version };
if ( typeof value === 'object' && value.clone !== undefined ) {

} else {
if ( value.isTexture === true ) {

data[ property ] = value.clone();
data[ property ] = { id: value.id, version: value.version };

}
} else {

} else {
data[ property ] = value.clone();

data[ property ] = value;
}

} else {

data[ property ] = value;

}

}

_materialCache.set( material, data );

}

return data;
Expand All @@ -314,9 +329,10 @@ class NodeMaterialObserver {
*
* @param {RenderObject} renderObject - The render object.
* @param {Array<Light>} lightsData - The current material lights.
* @param {number} renderId - The current render ID.
* @return {boolean} Whether the given render object has changed its state or not.
*/
equals( renderObject, lightsData ) {
equals( renderObject, lightsData, renderId ) {

const { object, material, geometry } = renderObject;

Expand All @@ -334,57 +350,78 @@ class NodeMaterialObserver {

// material

const materialData = renderObjectData.material;
const materialData = this.getMaterialData( renderObject.material );

for ( const property in materialData ) {
// check the material for the "equal" state just once per render for all render objects

const value = materialData[ property ];
const mtlValue = material[ property ];
if ( materialData._renderId !== renderId ) {

if ( value.equals !== undefined ) {
materialData._renderId = renderId;

if ( value.equals( mtlValue ) === false ) {
for ( const property in materialData ) {

value.copy( mtlValue );
const value = materialData[ property ];
const mtlValue = material[ property ];

return false;
if ( property === '_renderId' ) continue;
if ( property === '_equal' ) continue;

}
if ( value.equals !== undefined ) {

} else if ( mtlValue.isTexture === true ) {
if ( value.equals( mtlValue ) === false ) {

if ( value.id !== mtlValue.id || value.version !== mtlValue.version ) {
value.copy( mtlValue );

value.id = mtlValue.id;
value.version = mtlValue.version;
materialData._equal = false;
return false;

return false;
}

}
} else if ( mtlValue.isTexture === true ) {

} else if ( value !== mtlValue ) {
if ( value.id !== mtlValue.id || value.version !== mtlValue.version ) {

materialData[ property ] = mtlValue;
value.id = mtlValue.id;
value.version = mtlValue.version;

return false;
materialData._equal = false;
return false;

}

} else if ( value !== mtlValue ) {

materialData[ property ] = mtlValue;

materialData._equal = false;
return false;

}

}

}
if ( materialData.transmission > 0 ) {

if ( materialData.transmission > 0 ) {
const { width, height } = renderObject.context;

const { width, height } = renderObject.context;
if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) {

if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) {
renderObjectData.bufferWidth = width;
renderObjectData.bufferHeight = height;

renderObjectData.bufferWidth = width;
renderObjectData.bufferHeight = height;
materialData._equal = false;
return false;

return false;
}

}

materialData._equal = true;

} else {

if ( materialData._equal === false ) return false;

}

// geometry
Expand Down Expand Up @@ -612,7 +649,7 @@ class NodeMaterialObserver {
return false;

const lightsData = this.getLights( renderObject.lightsNode, renderId );
const notEqual = this.equals( renderObject, lightsData ) !== true;
const notEqual = this.equals( renderObject, lightsData, renderId ) !== true;

return notEqual;

Expand Down