|
|
@@ -63,12 +63,34 @@ const getShadowMaterial = ( light ) => {
|
|
|
|
|
|
};
|
|
|
|
|
|
+/** @module ShadowNode **/
|
|
|
+
|
|
|
+/**
|
|
|
+ * A shadow filtering function performing basic filtering. This is in fact an unfiltered version of the shadow map
|
|
|
+ * with a binary `[0,1]` result.
|
|
|
+ *
|
|
|
+ * @method
|
|
|
+ * @param {Object} inputs - The input parameter object.
|
|
|
+ * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
|
|
|
+ * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
|
|
|
+ * @return {Node<float>} The filtering result.
|
|
|
+ */
|
|
|
export const BasicShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord } ) => {
|
|
|
|
|
|
return texture( depthTexture, shadowCoord.xy ).compare( shadowCoord.z );
|
|
|
|
|
|
} );
|
|
|
|
|
|
+/**
|
|
|
+ * A shadow filtering function performing PCF filtering.
|
|
|
+ *
|
|
|
+ * @method
|
|
|
+ * @param {Object} inputs - The input parameter object.
|
|
|
+ * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
|
|
|
+ * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
|
|
|
+ * @param {LightShadow} inputs.shadow - The light shadow.
|
|
|
+ * @return {Node<float>} The filtering result.
|
|
|
+ */
|
|
|
export const PCFShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord, shadow } ) => {
|
|
|
|
|
|
const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
|
|
|
@@ -108,6 +130,16 @@ export const PCFShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord,
|
|
|
|
|
|
} );
|
|
|
|
|
|
+/**
|
|
|
+ * A shadow filtering function performing PCF soft filtering.
|
|
|
+ *
|
|
|
+ * @method
|
|
|
+ * @param {Object} inputs - The input parameter object.
|
|
|
+ * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
|
|
|
+ * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
|
|
|
+ * @param {LightShadow} inputs.shadow - The light shadow.
|
|
|
+ * @return {Node<float>} The filtering result.
|
|
|
+ */
|
|
|
export const PCFSoftShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord, shadow } ) => {
|
|
|
|
|
|
const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
|
|
|
@@ -164,8 +196,15 @@ export const PCFSoftShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoo
|
|
|
|
|
|
} );
|
|
|
|
|
|
-// VSM
|
|
|
-
|
|
|
+/**
|
|
|
+ * A shadow filtering function performing VSM filtering.
|
|
|
+ *
|
|
|
+ * @method
|
|
|
+ * @param {Object} inputs - The input parameter object.
|
|
|
+ * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
|
|
|
+ * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
|
|
|
+ * @return {Node<float>} The filtering result.
|
|
|
+ */
|
|
|
export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord } ) => {
|
|
|
|
|
|
const occlusion = float( 1 ).toVar();
|
|
|
@@ -188,6 +227,17 @@ export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord }
|
|
|
|
|
|
} );
|
|
|
|
|
|
+/**
|
|
|
+ * Represents the shader code for the first VSM render pass.
|
|
|
+ *
|
|
|
+ * @method
|
|
|
+ * @param {Object} inputs - The input parameter object.
|
|
|
+ * @param {Node<float>} inputs.samples - The number of samples
|
|
|
+ * @param {Node<float>} inputs.radius - The radius.
|
|
|
+ * @param {Node<float>} inputs.size - The size.
|
|
|
+ * @param {TextureNode} inputs.shadowPass - A reference to the render target's depth data.
|
|
|
+ * @return {Node<vec2>} The VSM output.
|
|
|
+ */
|
|
|
const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass } ) => {
|
|
|
|
|
|
const mean = float( 0 ).toVar();
|
|
|
@@ -214,6 +264,17 @@ const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass
|
|
|
|
|
|
} );
|
|
|
|
|
|
+/**
|
|
|
+ * Represents the shader code for the second VSM render pass.
|
|
|
+ *
|
|
|
+ * @method
|
|
|
+ * @param {Object} inputs - The input parameter object.
|
|
|
+ * @param {Node<float>} inputs.samples - The number of samples
|
|
|
+ * @param {Node<float>} inputs.radius - The radius.
|
|
|
+ * @param {Node<float>} inputs.size - The size.
|
|
|
+ * @param {TextureNode} inputs.shadowPass - The result of the first VSM render pass.
|
|
|
+ * @return {Node<vec2>} The VSM output.
|
|
|
+ */
|
|
|
const VSMPassHorizontal = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass } ) => {
|
|
|
|
|
|
const mean = float( 0 ).toVar();
|
|
|
@@ -246,6 +307,11 @@ const _shadowFilterLib = [ BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilt
|
|
|
|
|
|
const _quadMesh = /*@__PURE__*/ new QuadMesh();
|
|
|
|
|
|
+/**
|
|
|
+ * Represents the default shadow implementation for lighting nodes.
|
|
|
+ *
|
|
|
+ * @augments ShadowBaseNode
|
|
|
+ */
|
|
|
class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
static get type() {
|
|
|
@@ -254,26 +320,101 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Constructs a new shadow node.
|
|
|
+ *
|
|
|
+ * @param {Light} light - The shadow casting light.
|
|
|
+ * @param {LightShadow?} [shadow=null] - An optional light shadow.
|
|
|
+ */
|
|
|
constructor( light, shadow = null ) {
|
|
|
|
|
|
super( light );
|
|
|
|
|
|
+ /**
|
|
|
+ * The light shadow which defines the properties light's
|
|
|
+ * shadow.
|
|
|
+ *
|
|
|
+ * @type {LightShadow?}
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
this.shadow = shadow || light.shadow;
|
|
|
|
|
|
+ /**
|
|
|
+ * A reference to the shadow map which is a render target.
|
|
|
+ *
|
|
|
+ * @type {RenderTarget?}
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
this.shadowMap = null;
|
|
|
|
|
|
+ /**
|
|
|
+ * Only relevant for VSM shadows. Render target for the
|
|
|
+ * first VSM render pass.
|
|
|
+ *
|
|
|
+ * @type {RenderTarget?}
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
this.vsmShadowMapVertical = null;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Only relevant for VSM shadows. Render target for the
|
|
|
+ * second VSM render pass.
|
|
|
+ *
|
|
|
+ * @type {RenderTarget?}
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
this.vsmShadowMapHorizontal = null;
|
|
|
|
|
|
+ /**
|
|
|
+ * Only relevant for VSM shadows. Node material which
|
|
|
+ * is used to render the first VSM pass.
|
|
|
+ *
|
|
|
+ * @type {NodeMaterial?}
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
this.vsmMaterialVertical = null;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Only relevant for VSM shadows. Node material which
|
|
|
+ * is used to render the second VSM pass.
|
|
|
+ *
|
|
|
+ * @type {NodeMaterial?}
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
this.vsmMaterialHorizontal = null;
|
|
|
|
|
|
+ /**
|
|
|
+ * A reference to the output node which defines the
|
|
|
+ * final result of this shadow node.
|
|
|
+ *
|
|
|
+ * @type {Node?}
|
|
|
+ * @private
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
this._node = null;
|
|
|
|
|
|
+ /**
|
|
|
+ * This flag can be used for type testing.
|
|
|
+ *
|
|
|
+ * @type {Boolean}
|
|
|
+ * @readonly
|
|
|
+ * @default true
|
|
|
+ */
|
|
|
this.isShadowNode = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Setups the shadow filtering.
|
|
|
+ *
|
|
|
+ * @param {NodeBuilder} builder - A reference to the current node builder.
|
|
|
+ * @param {Object} inputs - A configuration object that defines the shadow filtering.
|
|
|
+ * @param {Function} inputs.filterFn - This function defines the filtering type of the shadow map e.g. PCF.
|
|
|
+ * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
|
|
|
+ * @param {Node<vec3>} inputs.shadowCoord - Shadow coordinates which are used to sample from the shadow map.
|
|
|
+ * @param {LightShadow} inputs.shadow - The light shadow.
|
|
|
+ * @return {Node<float>} The result node of the shadow filtering.
|
|
|
+ */
|
|
|
setupShadowFilter( builder, { filterFn, depthTexture, shadowCoord, shadow } ) {
|
|
|
|
|
|
const frustumTest = shadowCoord.x.greaterThanEqual( 0 )
|
|
|
@@ -288,6 +429,13 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Setups the shadow coordinates.
|
|
|
+ *
|
|
|
+ * @param {NodeBuilder} builder - A reference to the current node builder.
|
|
|
+ * @param {Node<vec3>} shadowPosition - A node representing the shadow position.
|
|
|
+ * @return {Node<vec3>} The shadow coordinates.
|
|
|
+ */
|
|
|
setupShadowCoord( builder, shadowPosition ) {
|
|
|
|
|
|
const { shadow } = this;
|
|
|
@@ -335,12 +483,24 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns the shadow filtering function for the given shadow type.
|
|
|
+ *
|
|
|
+ * @param {Number} type - The shadow type.
|
|
|
+ * @return {Function} The filtering function.
|
|
|
+ */
|
|
|
getShadowFilterFn( type ) {
|
|
|
|
|
|
return _shadowFilterLib[ type ];
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Setups the shadow output node.
|
|
|
+ *
|
|
|
+ * @param {NodeBuilder} builder - A reference to the current node builder.
|
|
|
+ * @return {Node<vec3>} The shadow output node.
|
|
|
+ */
|
|
|
setupShadow( builder ) {
|
|
|
|
|
|
const { renderer } = builder;
|
|
|
@@ -415,6 +575,13 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * The implementation performs the setup of the output node. An output is only
|
|
|
+ * produces if shadow mapping is globally enabled in the renderer.
|
|
|
+ *
|
|
|
+ * @param {NodeBuilder} builder - A reference to the current node builder.
|
|
|
+ * @return {ShaderCallNodeInternal} The output node.
|
|
|
+ */
|
|
|
setup( builder ) {
|
|
|
|
|
|
if ( builder.renderer.shadowMap.enabled === false ) return;
|
|
|
@@ -449,6 +616,14 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Renders the shadow. The logic of this function could be included
|
|
|
+ * into {@link ShadowNode#updateShadow} however more specialized shadow
|
|
|
+ * nodes might require a custom shadow map rendering. By having a
|
|
|
+ * dedicated method, it's easier to overwrite the default beavior.
|
|
|
+ *
|
|
|
+ * @param {NodeFrme} frame - A reference to the current node frame.
|
|
|
+ */
|
|
|
renderShadow( frame ) {
|
|
|
|
|
|
const { shadow, shadowMap, light } = this;
|
|
|
@@ -462,6 +637,11 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Updates the shadow.
|
|
|
+ *
|
|
|
+ * @param {NodeFrme} frame - A reference to the current node frame.
|
|
|
+ */
|
|
|
updateShadow( frame ) {
|
|
|
|
|
|
const { shadowMap, light, shadow } = this;
|
|
|
@@ -520,6 +700,11 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * For VSM additional render passes are required.
|
|
|
+ *
|
|
|
+ * @param {Renderer} renderer - A reference to the current renderer.
|
|
|
+ */
|
|
|
vsmPass( renderer ) {
|
|
|
|
|
|
const { shadow } = this;
|
|
|
@@ -537,6 +722,9 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Frees the internal resources of this shadow node.
|
|
|
+ */
|
|
|
dispose() {
|
|
|
|
|
|
this.shadowMap.dispose();
|
|
|
@@ -566,6 +754,11 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * The implementation performs the update of the shadow map if necessary.
|
|
|
+ *
|
|
|
+ * @param {NodeFrme} frame - A reference to the current node frame.
|
|
|
+ */
|
|
|
updateBefore( frame ) {
|
|
|
|
|
|
const { shadow } = this;
|
|
|
@@ -590,4 +783,12 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
|
|
|
export default ShadowNode;
|
|
|
|
|
|
+/**
|
|
|
+ * Factory method for creating an instance of `ShadowNode`.
|
|
|
+ *
|
|
|
+ * @method
|
|
|
+ * @param {Light} light - The shadow casting light.
|
|
|
+ * @param {LightShadow} shadow - The light shadow.
|
|
|
+ * @return {ShadowNode} The created shadow node.
|
|
|
+ */
|
|
|
export const shadow = ( light, shadow ) => nodeObject( new ShadowNode( light, shadow ) );
|