diff --git a/engine/src/core-data/Common/MatDefs/Light/Lighting.j3md b/engine/src/core-data/Common/MatDefs/Light/Lighting.j3md index 3aee7cfac..23ec35d13 100644 --- a/engine/src/core-data/Common/MatDefs/Light/Lighting.j3md +++ b/engine/src/core-data/Common/MatDefs/Light/Lighting.j3md @@ -111,6 +111,7 @@ MaterialDef Phong Lighting { Float ShadowIntensity Vector4 Splits + Vector2 FadeInfo Matrix4 LightViewProjectionMatrix0 Matrix4 LightViewProjectionMatrix1 @@ -207,6 +208,7 @@ MaterialDef Phong Lighting { DISCARD_ALPHA : AlphaDiscardThreshold COLOR_MAP : ColorMap SHADOWMAP_SIZE : ShadowMapSize + FADE : FadeInfo } ForcedRenderState { @@ -232,6 +234,7 @@ MaterialDef Phong Lighting { DISCARD_ALPHA : AlphaDiscardThreshold COLOR_MAP : ColorMap SHADOWMAP_SIZE : ShadowMapSize + FADE : FadeInfo } ForcedRenderState { diff --git a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.frag b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.frag index ec43349fe..bb2625983 100644 --- a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.frag +++ b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.frag @@ -18,6 +18,10 @@ uniform mat4 m_LightViewProjectionMatrix1; uniform mat4 m_LightViewProjectionMatrix2; uniform mat4 m_LightViewProjectionMatrix3; +#ifdef FADE +uniform vec2 m_FadeInfo; +#endif + vec3 getPosition(in float depth, in vec2 uv){ vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0; pos = m_ViewProjectionMatrixInverse * pos; @@ -47,7 +51,7 @@ void main(){ float shadowPosition = m_ViewProjectionMatrixRow2.x * worldPos.x + m_ViewProjectionMatrixRow2.y * worldPos.y + m_ViewProjectionMatrixRow2.z * worldPos.z + m_ViewProjectionMatrixRow2.w; - float shadow = 0.0; + float shadow = 1.0; if(shadowPosition < m_Splits.x){ shadow = GETSHADOW(m_ShadowMap0, projCoord0); }else if( shadowPosition < m_Splits.y){ @@ -59,10 +63,11 @@ void main(){ }else if( shadowPosition < m_Splits.w){ shadowBorderScale = 0.125; shadow = GETSHADOW(m_ShadowMap3, projCoord3); - }else{ - shadow = 1.0; } - + + #ifdef FADE + shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y)); + #endif shadow= shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity); gl_FragColor = color * vec4(shadow, shadow, shadow, 1.0); diff --git a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.j3md b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.j3md index 1a611908a..711729aef 100644 --- a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.j3md +++ b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter.j3md @@ -11,6 +11,7 @@ MaterialDef Post Shadow { Float ShadowIntensity Vector4 Splits + Vector2 FadeInfo Matrix4 LightViewProjectionMatrix0 Matrix4 LightViewProjectionMatrix1 @@ -46,6 +47,7 @@ MaterialDef Post Shadow { FILTER_MODE : FilterMode PCFEDGE : PCFEdge SHADOWMAP_SIZE : ShadowMapSize + FADE : FadeInfo } } @@ -63,6 +65,7 @@ MaterialDef Post Shadow { FILTER_MODE : FilterMode PCFEDGE : PCFEdge SHADOWMAP_SIZE : ShadowMapSize + FADE : FadeInfo } } diff --git a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter15.frag b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter15.frag index 782f66934..a331b625a 100644 --- a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter15.frag +++ b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowFilter15.frag @@ -20,6 +20,9 @@ uniform mat4 m_LightViewProjectionMatrix1; uniform mat4 m_LightViewProjectionMatrix2; uniform mat4 m_LightViewProjectionMatrix3; +#ifdef FADE +uniform vec2 m_FadeInfo; +#endif vec3 getPosition(in float depth, in vec2 uv){ vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0; @@ -47,7 +50,7 @@ vec4 main_multiSample(in int numSample){ float shadowPosition = m_ViewProjectionMatrixRow2.x * worldPos.x + m_ViewProjectionMatrixRow2.y * worldPos.y + m_ViewProjectionMatrixRow2.z * worldPos.z + m_ViewProjectionMatrixRow2.w; -float shadow = 0.0; + float shadow = 1.0; if(shadowPosition < m_Splits.x){ shadow = GETSHADOW(m_ShadowMap0, projCoord0); }else if( shadowPosition < m_Splits.y){ @@ -59,10 +62,11 @@ float shadow = 0.0; }else if( shadowPosition < m_Splits.w){ shadowBorderScale = 0.125; shadow = GETSHADOW(m_ShadowMap3, projCoord3); - }else{ - shadow = 1.0; } - + + #ifdef FADE + shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y)); + #endif shadow= shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity); return color * vec4(shadow, shadow, shadow, 1.0); diff --git a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.frag b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.frag index 7329bcb35..e9661e510 100644 --- a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.frag +++ b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.frag @@ -16,6 +16,10 @@ varying vec4 projCoord3; varying vec2 texCoord; #endif +#ifdef FADE +uniform vec2 m_FadeInfo; +#endif + void main(){ #ifdef DISCARD_ALPHA @@ -30,7 +34,7 @@ void main(){ #endif - float shadow = 0.0; + float shadow = 1.0; if(shadowPosition < m_Splits.x){ shadow = GETSHADOW(m_ShadowMap0, projCoord0); }else if( shadowPosition < m_Splits.y){ @@ -42,10 +46,11 @@ void main(){ }else if( shadowPosition < m_Splits.w){ shadowBorderScale = 0.125; shadow = GETSHADOW(m_ShadowMap3, projCoord3); - }else{ - shadow = 1.0; } + #ifdef FADE + shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y)); + #endif shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity); gl_FragColor = vec4(shadow, shadow, shadow, 1.0); diff --git a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.j3md b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.j3md index fd820faea..f502aaed1 100644 --- a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.j3md +++ b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.j3md @@ -11,6 +11,7 @@ MaterialDef Post Shadow { Float ShadowIntensity Vector4 Splits + Vector2 FadeInfo Matrix4 LightViewProjectionMatrix0 Matrix4 LightViewProjectionMatrix1 @@ -36,6 +37,7 @@ MaterialDef Post Shadow { FILTER_MODE : FilterMode PCFEDGE : PCFEdge SHADOWMAP_SIZE : ShadowMapSize + FADE : FadeInfo } RenderState { @@ -59,6 +61,7 @@ MaterialDef Post Shadow { FILTER_MODE : FilterMode PCFEDGE : PCFEdge SHADOWMAP_SIZE : ShadowMapSize + FADE : FadeInfo } RenderState { diff --git a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM15.frag b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM15.frag index 0c13287f1..f9cdc5eb4 100644 --- a/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM15.frag +++ b/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM15.frag @@ -17,6 +17,10 @@ in vec4 projCoord3; varying vec2 texCoord; #endif +#ifdef FADE +uniform vec2 m_FadeInfo; +#endif + void main(){ #ifdef DISCARD_ALPHA @@ -32,24 +36,25 @@ void main(){ #endif - float shadow = 0.0; + float shadow = 1.0; if(shadowPosition < m_Splits.x){ - shadow = GETSHADOW(m_ShadowMap0, projCoord0); + shadow = GETSHADOW(m_ShadowMap0, projCoord0); }else if( shadowPosition < m_Splits.y){ shadowBorderScale = 0.5; - shadow = GETSHADOW(m_ShadowMap1, projCoord1); + shadow = GETSHADOW(m_ShadowMap1, projCoord1); }else if( shadowPosition < m_Splits.z){ shadowBorderScale = 0.25; - shadow = GETSHADOW(m_ShadowMap2, projCoord2); + shadow = GETSHADOW(m_ShadowMap2, projCoord2); }else if( shadowPosition < m_Splits.w){ shadowBorderScale = 0.125; - shadow = GETSHADOW(m_ShadowMap3, projCoord3); - }else{ - shadow = 1.0; + shadow = GETSHADOW(m_ShadowMap3, projCoord3); } - - shadow= shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity); - + + #ifdef FADE + shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y)); + #endif + + shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity); outFragColor = vec4(shadow, shadow, shadow, 1.0); } diff --git a/engine/src/core/com/jme3/shadow/PssmShadowFilter.java b/engine/src/core/com/jme3/shadow/PssmShadowFilter.java index 518477a5b..b3bc69134 100644 --- a/engine/src/core/com/jme3/shadow/PssmShadowFilter.java +++ b/engine/src/core/com/jme3/shadow/PssmShadowFilter.java @@ -245,6 +245,22 @@ public class PssmShadowFilter extends Filter { final public void setFilterMode(FilterMode filterMode) { pssmRenderer.setFilterMode(filterMode); } + + /** + * Define the length over which the shadow will fade out when using a shadowZextend + * @param length the fade length in world units + */ + public void setShadowZFadeLength(float length){ + pssmRenderer.setShadowZFadeLength(length); + } + + /** + * get the length over which the shadow will fade out when using a shadowZextend + * @return the fade length in world units + */ + public float getShadowZFadeLength(){ + return pssmRenderer.getShadowZFadeLength(); + } @Override public void write(JmeExporter ex) throws IOException { diff --git a/engine/src/core/com/jme3/shadow/PssmShadowRenderer.java b/engine/src/core/com/jme3/shadow/PssmShadowRenderer.java index cb898fbff..e6fd6fcf3 100644 --- a/engine/src/core/com/jme3/shadow/PssmShadowRenderer.java +++ b/engine/src/core/com/jme3/shadow/PssmShadowRenderer.java @@ -35,6 +35,7 @@ import com.jme3.asset.AssetManager; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.Matrix4f; +import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; import com.jme3.post.SceneProcessor; import com.jme3.renderer.Camera; @@ -162,6 +163,10 @@ public class PssmShadowRenderer implements SceneProcessor { private boolean applyShadowIntensity = true; //a list of material of the post shadow queue geometries. private List matCache = new ArrayList(); + //Holding the info for fading shadows in the far distance + private Vector2f fadeInfo; + private float fadeLength; + private boolean applyFadeInfo = true; /** * Create a PSSM Shadow Renderer @@ -214,7 +219,7 @@ public class PssmShadowRenderer implements SceneProcessor { //DO NOT COMMENT THIS (it prevent the OSX incomplete read buffer crash) shadowFB[i].setColorTexture(dummyTex); - postshadowMat.setTexture("ShadowMap" + i, shadowMaps[i]); + postshadowMat.setTexture("ShadowMap" + i, shadowMaps[i]); //quads for debuging purpose dispPic[i] = new Picture("Picture" + i); @@ -541,6 +546,11 @@ public class PssmShadowRenderer implements SceneProcessor { mat.setFloat("ShadowIntensity", shadowIntensity); applyShadowIntensity = false; } + + if (fadeInfo != null && mat.getParam("FadeInfo") == null || applyFadeInfo) { + mat.setVector2("FadeInfo", fadeInfo); + applyFadeInfo = false; + } } @@ -604,7 +614,11 @@ public class PssmShadowRenderer implements SceneProcessor { * @param zFar the zFar values that override the computed one */ public void setShadowZExtend(float zFar) { + if(fadeInfo!=null){ + fadeInfo.set(zFar - fadeLength, 1f / fadeLength); + } this.zFarOverride = zFar; + } /** @@ -665,4 +679,37 @@ public class PssmShadowRenderer implements SceneProcessor { public void setFlushQueues(boolean flushQueues) { this.flushQueues = flushQueues; } + + /** + * Define the length over which the shadow will fade out when using a + * shadowZextend + * This is useful to make dynamic shadows fade into baked shadows in the distance. + * @param length the fade length in world units + */ + public void setShadowZFadeLength(float length) { + if (length == 0) { + fadeInfo = null; + fadeLength = 0; + postshadowMat.clearParam("FadeInfo"); + } else { + if (zFarOverride == 0) { + fadeInfo = new Vector2f(0, 0); + } else { + fadeInfo = new Vector2f(zFarOverride - length, 1.0f / length); + } + fadeLength = length; + postshadowMat.setVector2("FadeInfo", fadeInfo); + } + } + + /** + * get the length over which the shadow will fade out when using a shadowZextend + * @return the fade length in world units + */ + public float getShadowZFadeLength(){ + if(fadeInfo!=null){ + return zFarOverride - fadeInfo.x; + } + return 0f; + } }