|
|
@@ -624,6 +624,14 @@ class Renderer {
|
|
|
*/
|
|
|
this._colorBufferType = colorBufferType;
|
|
|
|
|
|
+ /**
|
|
|
+ * A cache for shadow nodes per material
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @type {WeakMap<Material, Object>}
|
|
|
+ */
|
|
|
+ this._cacheShadowNodes = new WeakMap();
|
|
|
+
|
|
|
/**
|
|
|
* Whether the renderer has been initialized or not.
|
|
|
*
|
|
|
@@ -2860,6 +2868,93 @@ class Renderer {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Retrieves shadow nodes for the given material. This is used to setup shadow passes.
|
|
|
+ * The result is cached per material and updated when the material's version changes.
|
|
|
+ *
|
|
|
+ * @param {Material} material
|
|
|
+ * @returns {Object} - The shadow nodes for the material.
|
|
|
+ */
|
|
|
+ _getShadowNodes( material ) {
|
|
|
+
|
|
|
+ const version = material.version;
|
|
|
+
|
|
|
+ let cache = this._cacheShadowNodes.get( material );
|
|
|
+
|
|
|
+ if ( cache === undefined || cache.version !== version ) {
|
|
|
+
|
|
|
+ const hasMap = material.map !== null;
|
|
|
+ const hasColorNode = material.colorNode && material.colorNode.isNode;
|
|
|
+ const hasCastShadowNode = material.castShadowNode && material.castShadowNode.isNode;
|
|
|
+
|
|
|
+ let positionNode = null;
|
|
|
+ let colorNode = null;
|
|
|
+ let depthNode = null;
|
|
|
+
|
|
|
+ if ( hasMap || hasColorNode || hasCastShadowNode ) {
|
|
|
+
|
|
|
+ let shadowRGB;
|
|
|
+ let shadowAlpha;
|
|
|
+
|
|
|
+ if ( hasCastShadowNode ) {
|
|
|
+
|
|
|
+ shadowRGB = material.castShadowNode.rgb;
|
|
|
+ shadowAlpha = material.castShadowNode.a;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ shadowRGB = vec3( 0 );
|
|
|
+ shadowAlpha = float( 1 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( hasMap ) {
|
|
|
+
|
|
|
+ shadowAlpha = shadowAlpha.mul( reference( 'map', 'texture', material ).a );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( hasColorNode ) {
|
|
|
+
|
|
|
+ shadowAlpha = shadowAlpha.mul( material.colorNode.a );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ colorNode = vec4( shadowRGB, shadowAlpha );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.depthNode && material.depthNode.isNode ) {
|
|
|
+
|
|
|
+ depthNode = material.depthNode;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.castShadowPositionNode && material.castShadowPositionNode.isNode ) {
|
|
|
+
|
|
|
+ positionNode = material.castShadowPositionNode;
|
|
|
+
|
|
|
+ } else if ( material.positionNode && material.positionNode.isNode ) {
|
|
|
+
|
|
|
+ positionNode = material.positionNode;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ cache = {
|
|
|
+ version,
|
|
|
+ colorNode,
|
|
|
+ depthNode,
|
|
|
+ positionNode
|
|
|
+ };
|
|
|
+
|
|
|
+ this._cacheShadowNodes.set( material, cache );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return cache;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* This method represents the default render object function that manages the render lifecycle
|
|
|
* of the object.
|
|
|
@@ -2876,9 +2971,11 @@ class Renderer {
|
|
|
*/
|
|
|
renderObject( object, scene, camera, geometry, material, group, lightsNode, clippingContext = null, passId = null ) {
|
|
|
|
|
|
- let overridePositionNode;
|
|
|
- let overrideColorNode;
|
|
|
- let overrideDepthNode;
|
|
|
+ let materialOverride = false;
|
|
|
+ let materialColorNode;
|
|
|
+ let materialDepthNode;
|
|
|
+ let materialPositionNode;
|
|
|
+ let materialSide;
|
|
|
|
|
|
//
|
|
|
|
|
|
@@ -2890,9 +2987,16 @@ class Renderer {
|
|
|
|
|
|
const overrideMaterial = scene.overrideMaterial;
|
|
|
|
|
|
+ materialOverride = true;
|
|
|
+
|
|
|
+ // store original nodes
|
|
|
+ materialColorNode = scene.overrideMaterial.colorNode;
|
|
|
+ materialDepthNode = scene.overrideMaterial.depthNode;
|
|
|
+ materialPositionNode = scene.overrideMaterial.positionNode;
|
|
|
+ materialSide = scene.overrideMaterial.side;
|
|
|
+
|
|
|
if ( material.positionNode && material.positionNode.isNode ) {
|
|
|
|
|
|
- overridePositionNode = overrideMaterial.positionNode;
|
|
|
overrideMaterial.positionNode = material.positionNode;
|
|
|
|
|
|
}
|
|
|
@@ -2903,60 +3007,13 @@ class Renderer {
|
|
|
|
|
|
if ( overrideMaterial.isShadowPassMaterial ) {
|
|
|
|
|
|
- overrideMaterial.side = material.shadowSide === null ? material.side : material.shadowSide;
|
|
|
-
|
|
|
- const hasMap = material.map !== null;
|
|
|
- const hasColorNode = material.colorNode && material.colorNode.isNode;
|
|
|
- const hasCastShadowNode = material.castShadowNode && material.castShadowNode.isNode;
|
|
|
-
|
|
|
- if ( hasMap || hasColorNode || hasCastShadowNode ) {
|
|
|
-
|
|
|
- overrideColorNode = overrideMaterial.colorNode;
|
|
|
-
|
|
|
- let shadowRGB;
|
|
|
- let shadowAlpha;
|
|
|
-
|
|
|
- if ( hasCastShadowNode ) {
|
|
|
-
|
|
|
- shadowRGB = material.castShadowNode.rgb;
|
|
|
- shadowAlpha = material.castShadowNode.a;
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- shadowRGB = vec3( 0 );
|
|
|
- shadowAlpha = float( 1 );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( hasMap ) {
|
|
|
-
|
|
|
- shadowAlpha = shadowAlpha.mul( reference( 'map', 'texture', material ).a );
|
|
|
-
|
|
|
- }
|
|
|
+ const { colorNode, depthNode, positionNode } = this._getShadowNodes( material );
|
|
|
|
|
|
- if ( hasColorNode ) {
|
|
|
-
|
|
|
- shadowAlpha = shadowAlpha.mul( material.colorNode.a );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- overrideMaterial.colorNode = vec4( shadowRGB, shadowAlpha );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( material.depthNode && material.depthNode.isNode ) {
|
|
|
-
|
|
|
- overrideDepthNode = overrideMaterial.depthNode;
|
|
|
- overrideMaterial.depthNode = material.depthNode;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( material.castShadowPositionNode && material.castShadowPositionNode.isNode ) {
|
|
|
-
|
|
|
- overridePositionNode = overrideMaterial.positionNode;
|
|
|
- overrideMaterial.positionNode = material.castShadowPositionNode;
|
|
|
+ overrideMaterial.side = material.shadowSide === null ? material.side : material.shadowSide;
|
|
|
|
|
|
- }
|
|
|
+ if ( colorNode !== null ) overrideMaterial.colorNode = colorNode;
|
|
|
+ if ( depthNode !== null ) overrideMaterial.depthNode = depthNode;
|
|
|
+ if ( positionNode !== null ) overrideMaterial.positionNode = positionNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -2984,21 +3041,12 @@ class Renderer {
|
|
|
|
|
|
//
|
|
|
|
|
|
- if ( overridePositionNode !== undefined ) {
|
|
|
-
|
|
|
- scene.overrideMaterial.positionNode = overridePositionNode;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( overrideDepthNode !== undefined ) {
|
|
|
-
|
|
|
- scene.overrideMaterial.depthNode = overrideDepthNode;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( overrideColorNode !== undefined ) {
|
|
|
+ if ( materialOverride ) {
|
|
|
|
|
|
- scene.overrideMaterial.colorNode = overrideColorNode;
|
|
|
+ scene.overrideMaterial.colorNode = materialColorNode;
|
|
|
+ scene.overrideMaterial.depthNode = materialDepthNode;
|
|
|
+ scene.overrideMaterial.positionNode = materialPositionNode;
|
|
|
+ scene.overrideMaterial.side = materialSide;
|
|
|
|
|
|
}
|
|
|
|