cleanup_build_scripts
jmekaelthas 9 years ago
commit a9a1544681
  1. 47
      jme3-core/src/main/java/com/jme3/shadow/AbstractShadowFilter.java
  2. 104
      jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java
  3. 2
      jme3-core/src/main/java/com/jme3/shadow/DirectionalLightShadowRenderer.java
  4. 13
      jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md
  5. 4
      jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md
  6. 17
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.frag
  7. 4
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.j3md
  8. 32
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.vert
  9. 29
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter.frag
  10. 10
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter.j3md
  11. 48
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter15.frag
  12. 39
      jme3-examples/src/main/java/jme3test/light/TestDirectionalLightShadow.java
  13. 27
      jme3-examples/src/main/java/jme3test/light/TestPointLightShadows.java

@ -37,6 +37,7 @@ import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Vector4f; import com.jme3.math.Vector4f;
import com.jme3.post.Filter; import com.jme3.post.Filter;
@ -44,6 +45,7 @@ import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue; import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer;
import java.io.IOException; import java.io.IOException;
/** /**
@ -74,6 +76,9 @@ public abstract class AbstractShadowFilter<T extends AbstractShadowRenderer> ext
material = new Material(manager, "Common/MatDefs/Shadow/PostShadowFilter.j3md"); material = new Material(manager, "Common/MatDefs/Shadow/PostShadowFilter.j3md");
this.shadowRenderer = shadowRenderer; this.shadowRenderer = shadowRenderer;
this.shadowRenderer.setPostShadowMaterial(material); this.shadowRenderer.setPostShadowMaterial(material);
//this is legacy setting for shadows with backface shadows
this.shadowRenderer.setRenderBackFacesShadows(true);
} }
@Override @Override
@ -126,7 +131,7 @@ public abstract class AbstractShadowFilter<T extends AbstractShadowRenderer> ext
/** /**
* How far the shadows are rendered in the view * How far the shadows are rendered in the view
* *
* @see setShadowZExtend(float zFar) * @see #setShadowZExtend(float zFar)
* @return shadowZExtend * @return shadowZExtend
*/ */
public float getShadowZExtend() { public float getShadowZExtend() {
@ -248,6 +253,46 @@ public abstract class AbstractShadowFilter<T extends AbstractShadowRenderer> ext
shadowRenderer.setEdgeFilteringMode(filterMode); shadowRenderer.setEdgeFilteringMode(filterMode);
} }
/**
*
* !! WARNING !! this parameter is defaulted to true for the ShadowFilter.
* Setting it to true, may produce edges artifacts on shadows. *
*
* Set to true if you want back faces shadows on geometries.
* Note that back faces shadows will be blended over dark lighten areas and may produce overly dark lighting.
*
* Setting this parameter will override this parameter for ALL materials in the scene.
* This also will automatically adjust the faceCullMode and the PolyOffset of the pre shadow pass.
* You can modify them by using {@link #getPreShadowForcedRenderState()}
*
* If you want to set it differently for each material in the scene you have to use the ShadowRenderer instead
* of the shadow filter.
*
* @param renderBackFacesShadows true or false.
*/
public void setRenderBackFacesShadows(Boolean renderBackFacesShadows) {
shadowRenderer.setRenderBackFacesShadows(renderBackFacesShadows);
}
/**
* if this filter renders back faces shadows
* @return true if this filter renders back faces shadows
*/
public boolean isRenderBackFacesShadows() {
return shadowRenderer.isRenderBackFacesShadows();
}
/**
* returns the pre shadows pass render state.
* use it to adjust the RenderState parameters of the pre shadow pass.
* Note that this will be overriden if the preShadow technique in the material has a ForcedRenderState
* @return the pre shadow render state.
*/
public RenderState getPreShadowForcedRenderState() {
return shadowRenderer.getPreShadowForcedRenderState();
}
/** /**
* returns the the edge filtering mode * returns the the edge filtering mode
* *

@ -31,10 +31,6 @@
*/ */
package com.jme3.shadow; package com.jme3.shadow;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
@ -42,6 +38,7 @@ import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
@ -67,6 +64,10 @@ import com.jme3.texture.Texture.ShadowCompareMode;
import com.jme3.texture.Texture2D; import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture; import com.jme3.ui.Picture;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/** /**
* abstract shadow renderer that holds commons feature to have for a shadow * abstract shadow renderer that holds commons feature to have for a shadow
* renderer * renderer
@ -92,6 +93,8 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
protected EdgeFilteringMode edgeFilteringMode = EdgeFilteringMode.Bilinear; protected EdgeFilteringMode edgeFilteringMode = EdgeFilteringMode.Bilinear;
protected CompareMode shadowCompareMode = CompareMode.Hardware; protected CompareMode shadowCompareMode = CompareMode.Hardware;
protected Picture[] dispPic; protected Picture[] dispPic;
protected RenderState forcedRenderState = new RenderState();
protected Boolean renderBackFacesShadows;
/** /**
* true if the fallback material should be used, otherwise false * true if the fallback material should be used, otherwise false
@ -182,6 +185,14 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
setShadowCompareMode(shadowCompareMode); setShadowCompareMode(shadowCompareMode);
setEdgeFilteringMode(edgeFilteringMode); setEdgeFilteringMode(edgeFilteringMode);
setShadowIntensity(shadowIntensity); setShadowIntensity(shadowIntensity);
initForcedRenderState();
}
protected void initForcedRenderState() {
forcedRenderState.setFaceCullMode(RenderState.FaceCullMode.Front);
forcedRenderState.setColorWrite(false);
forcedRenderState.setDepthWrite(true);
forcedRenderState.setDepthTest(true);
} }
/** /**
@ -357,9 +368,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
* rendered in the shadow map * rendered in the shadow map
* *
* @param shadowMapIndex the index of the shadow map being rendered * @param shadowMapIndex the index of the shadow map being rendered
* @param sceneOccluders the occluders of the whole scene * @param shadowMapOccluders the list of occluders
* @param sceneReceivers the receivers of the whole scene
* @param shadowMapOcculders
* @return * @return
*/ */
protected abstract GeometryList getOccludersToRender(int shadowMapIndex, GeometryList shadowMapOccluders); protected abstract GeometryList getOccludersToRender(int shadowMapIndex, GeometryList shadowMapOccluders);
@ -426,9 +435,11 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
renderManager.getRenderer().setFrameBuffer(shadowFB[shadowMapIndex]); renderManager.getRenderer().setFrameBuffer(shadowFB[shadowMapIndex]);
renderManager.getRenderer().clearBuffers(true, true, true); renderManager.getRenderer().clearBuffers(true, true, true);
renderManager.setForcedRenderState(forcedRenderState);
// render shadow casters to shadow map // render shadow casters to shadow map
viewPort.getQueue().renderShadowQueue(shadowMapOccluders, renderManager, shadowCam, true); viewPort.getQueue().renderShadowQueue(shadowMapOccluders, renderManager, shadowCam, true);
renderManager.setForcedRenderState(null);
} }
boolean debugfrustums = false; boolean debugfrustums = false;
@ -536,18 +547,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
private void setMatParams(GeometryList l) { private void setMatParams(GeometryList l) {
//iteration throught all the geometries of the list to gather the materials //iteration throught all the geometries of the list to gather the materials
matCache.clear(); buildMatCache(l);
for (int i = 0; i < l.size(); i++) {
Material mat = l.get(i).getMaterial();
//checking if the material has the post technique and adding it to the material cache
if (mat.getMaterialDef().getTechniqueDef(postTechniqueName) != null) {
if (!matCache.contains(mat)) {
matCache.add(mat);
}
} else {
needsfallBackMaterial = true;
}
}
//iterating through the mat cache and setting the parameters //iterating through the mat cache and setting the parameters
for (Material mat : matCache) { for (Material mat : matCache) {
@ -567,6 +567,10 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
if (fadeInfo != null) { if (fadeInfo != null) {
mat.setVector2("FadeInfo", fadeInfo); mat.setVector2("FadeInfo", fadeInfo);
} }
if(renderBackFacesShadows != null){
mat.setBoolean("BackfaceShadows", renderBackFacesShadows);
}
setMaterialParameters(mat); setMaterialParameters(mat);
} }
@ -578,6 +582,21 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
} }
private void buildMatCache(GeometryList l) {
matCache.clear();
for (int i = 0; i < l.size(); i++) {
Material mat = l.get(i).getMaterial();
//checking if the material has the post technique and adding it to the material cache
if (mat.getMaterialDef().getTechniqueDef(postTechniqueName) != null) {
if (!matCache.contains(mat)) {
matCache.add(mat);
}
} else {
needsfallBackMaterial = true;
}
}
}
/** /**
* for internal use only * for internal use only
*/ */
@ -588,7 +607,10 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
postshadowMat.setTexture(shadowMapStringCache[j], shadowMaps[j]); postshadowMat.setTexture(shadowMapStringCache[j], shadowMaps[j]);
} }
if (fadeInfo != null) { if (fadeInfo != null) {
postshadowMat.setVector2("FadeInfo", fadeInfo); postshadowMat.setVector2("FadeInfo", fadeInfo);
}
if(renderBackFacesShadows != null){
postshadowMat.setBoolean("BackfaceShadows", renderBackFacesShadows);
} }
} }
@ -731,6 +753,48 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
@Deprecated @Deprecated
public void setFlushQueues(boolean flushQueues) {} public void setFlushQueues(boolean flushQueues) {}
/**
* returns the pre shadows pass render state.
* use it to adjust the RenderState parameters of the pre shadow pass.
* Note that this will be overriden if the preShadow technique in the material has a ForcedRenderState
* @return the pre shadow render state.
*/
public RenderState getPreShadowForcedRenderState() {
return forcedRenderState;
}
/**
* Set to true if you want back faces shadows on geometries.
* Note that back faces shadows will be blended over dark lighten areas and may produce overly dark lighting.
*
* Also note that setting this parameter will override this parameter for ALL materials in the scene.
* You can alternatively change this parameter on a single material using {@link Material#setBoolean(String, boolean)}
*
* This also will automatically adjust the faceCullMode and the PolyOffset of the pre shadow pass.
* You can modify them by using {@link #getPreShadowForcedRenderState()}
*
* @param renderBackFacesShadows true or false.
*/
public void setRenderBackFacesShadows(Boolean renderBackFacesShadows) {
this.renderBackFacesShadows = renderBackFacesShadows;
if(renderBackFacesShadows) {
getPreShadowForcedRenderState().setPolyOffset(5, 3);
getPreShadowForcedRenderState().setFaceCullMode(RenderState.FaceCullMode.Back);
}else{
getPreShadowForcedRenderState().setPolyOffset(0, 0);
getPreShadowForcedRenderState().setFaceCullMode(RenderState.FaceCullMode.Front);
}
}
/**
* if this processor renders back faces shadows
* @return true if this processor renders back faces shadows
*/
public boolean isRenderBackFacesShadows() {
return renderBackFacesShadows != null?renderBackFacesShadows:false;
}
/** /**
* De-serialize this instance, for example when loading from a J3O file. * De-serialize this instance, for example when loading from a J3O file.
* *

@ -215,6 +215,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
@Override @Override
protected void setMaterialParameters(Material material) { protected void setMaterialParameters(Material material) {
material.setColor("Splits", splits); material.setColor("Splits", splits);
material.setVector3("LightDir", light.getDirection());
if (fadeInfo != null) { if (fadeInfo != null) {
material.setVector2("FadeInfo", fadeInfo); material.setVector2("FadeInfo", fadeInfo);
} }
@ -224,6 +225,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
protected void clearMaterialParameters(Material material) { protected void clearMaterialParameters(Material material) {
material.clearParam("Splits"); material.clearParam("Splits");
material.clearParam("FadeInfo"); material.clearParam("FadeInfo");
material.clearParam("LightDir");
} }
/** /**

@ -113,6 +113,8 @@ MaterialDef Phong Lighting {
//For instancing //For instancing
Boolean UseInstancing Boolean UseInstancing
Boolean BackfaceShadows: false
} }
Technique { Technique {
@ -213,14 +215,6 @@ MaterialDef Phong Lighting {
INSTANCING : UseInstancing INSTANCING : UseInstancing
} }
ForcedRenderState {
FaceCull Off
DepthTest On
DepthWrite On
PolyOffset 5 3
ColorWrite Off
}
} }
@ -233,6 +227,7 @@ MaterialDef Phong Lighting {
WorldMatrix WorldMatrix
ViewProjectionMatrix ViewProjectionMatrix
ViewMatrix ViewMatrix
NormalMatrix
} }
Defines { Defines {
@ -247,6 +242,7 @@ MaterialDef Phong Lighting {
POINTLIGHT : LightViewProjectionMatrix5 POINTLIGHT : LightViewProjectionMatrix5
NUM_BONES : NumberOfBones NUM_BONES : NumberOfBones
INSTANCING : UseInstancing INSTANCING : UseInstancing
BACKFACE_SHADOWS: BackfaceShadows
} }
ForcedRenderState { ForcedRenderState {
@ -265,6 +261,7 @@ MaterialDef Phong Lighting {
WorldMatrix WorldMatrix
ViewProjectionMatrix ViewProjectionMatrix
ViewMatrix ViewMatrix
NormalMatrix
} }
Defines { Defines {

@ -51,6 +51,8 @@ MaterialDef Unshaded {
Float PCFEdge Float PCFEdge
Float ShadowMapSize Float ShadowMapSize
Boolean BackfaceShadows: true
} }
Technique { Technique {
@ -169,6 +171,7 @@ MaterialDef Unshaded {
POINTLIGHT : LightViewProjectionMatrix5 POINTLIGHT : LightViewProjectionMatrix5
NUM_BONES : NumberOfBones NUM_BONES : NumberOfBones
INSTANCING : UseInstancing INSTANCING : UseInstancing
BACKFACE_SHADOWS: BackfaceShadows
} }
ForcedRenderState { ForcedRenderState {
@ -201,6 +204,7 @@ MaterialDef Unshaded {
POINTLIGHT : LightViewProjectionMatrix5 POINTLIGHT : LightViewProjectionMatrix5
NUM_BONES : NumberOfBones NUM_BONES : NumberOfBones
INSTANCING : UseInstancing INSTANCING : UseInstancing
BACKFACE_SHADOWS: BackfaceShadows
} }
ForcedRenderState { ForcedRenderState {

@ -9,6 +9,9 @@ varying vec4 projCoord0;
varying vec4 projCoord1; varying vec4 projCoord1;
varying vec4 projCoord2; varying vec4 projCoord2;
varying vec4 projCoord3; varying vec4 projCoord3;
#ifndef BACKFACE_SHADOWS
varying float nDotL;
#endif
#ifdef POINTLIGHT #ifdef POINTLIGHT
varying vec4 projCoord4; varying vec4 projCoord4;
@ -46,9 +49,15 @@ void main(){
if(alpha<=m_AlphaDiscardThreshold){ if(alpha<=m_AlphaDiscardThreshold){
discard; discard;
} }
#endif
#ifndef BACKFACE_SHADOWS
if(nDotL > 0.0){
discard;
}
#endif #endif
float shadow = 1.0; float shadow = 1.0;
#ifdef POINTLIGHT #ifdef POINTLIGHT
@ -71,11 +80,11 @@ void main(){
#endif #endif
#ifdef FADE #ifdef FADE
shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y)); shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y));
#endif #endif
shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);
gl_FragColor = vec4(shadow, shadow, shadow, 1.0); shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);
gl_FragColor = vec4(shadow, shadow, shadow, 1.0);
} }

@ -29,6 +29,8 @@ MaterialDef Post Shadow {
Float PCFEdge Float PCFEdge
Float ShadowMapSize Float ShadowMapSize
Boolean BackfaceShadows: false
} }
@ -49,6 +51,7 @@ MaterialDef Post Shadow {
FADE : FadeInfo FADE : FadeInfo
PSSM : Splits PSSM : Splits
POINTLIGHT : LightViewProjectionMatrix5 POINTLIGHT : LightViewProjectionMatrix5
BACKFACE_SHADOWS: BackfaceShadows
} }
RenderState { RenderState {
@ -75,6 +78,7 @@ MaterialDef Post Shadow {
FADE : FadeInfo FADE : FadeInfo
PSSM : Splits PSSM : Splits
POINTLIGHT : LightViewProjectionMatrix5 POINTLIGHT : LightViewProjectionMatrix5
BACKFACE_SHADOWS: BackfaceShadows
} }
RenderState { RenderState {

@ -7,7 +7,6 @@ uniform mat4 m_LightViewProjectionMatrix1;
uniform mat4 m_LightViewProjectionMatrix2; uniform mat4 m_LightViewProjectionMatrix2;
uniform mat4 m_LightViewProjectionMatrix3; uniform mat4 m_LightViewProjectionMatrix3;
uniform vec3 m_LightPos;
varying vec4 projCoord0; varying vec4 projCoord0;
varying vec4 projCoord1; varying vec4 projCoord1;
@ -17,12 +16,14 @@ varying vec4 projCoord3;
#ifdef POINTLIGHT #ifdef POINTLIGHT
uniform mat4 m_LightViewProjectionMatrix4; uniform mat4 m_LightViewProjectionMatrix4;
uniform mat4 m_LightViewProjectionMatrix5; uniform mat4 m_LightViewProjectionMatrix5;
uniform vec3 m_LightPos;
varying vec4 projCoord4; varying vec4 projCoord4;
varying vec4 projCoord5; varying vec4 projCoord5;
varying vec4 worldPos; varying vec4 worldPos;
#else #else
uniform vec3 m_LightDir;
#ifndef PSSM #ifndef PSSM
uniform vec3 m_LightDir; uniform vec3 m_LightPos;
varying float lightDot; varying float lightDot;
#endif #endif
#endif #endif
@ -30,12 +31,15 @@ varying vec4 projCoord3;
#if defined(PSSM) || defined(FADE) #if defined(PSSM) || defined(FADE)
varying float shadowPosition; varying float shadowPosition;
#endif #endif
varying vec3 lightVec;
varying vec2 texCoord; varying vec2 texCoord;
attribute vec3 inPosition; attribute vec3 inPosition;
#ifndef BACKFACE_SHADOWS
attribute vec3 inNormal;
varying float nDotL;
#endif
#ifdef DISCARD_ALPHA #ifdef DISCARD_ALPHA
attribute vec2 inTexCoord; attribute vec2 inTexCoord;
#endif #endif
@ -53,16 +57,17 @@ void main(){
Skinning_Compute(modelSpacePos); Skinning_Compute(modelSpacePos);
#endif #endif
gl_Position = TransformWorldViewProjection(modelSpacePos); gl_Position = TransformWorldViewProjection(modelSpacePos);
vec3 lightDir;
#if defined(PSSM) || defined(FADE) #if defined(PSSM) || defined(FADE)
shadowPosition = gl_Position.z; shadowPosition = gl_Position.z;
#endif #endif
#ifndef POINTLIGHT #ifndef POINTLIGHT
vec4 worldPos=vec4(0.0); vec4 worldPos=vec4(0.0);
#endif #endif
// get the vertex in world space // get the vertex in world space
worldPos = g_WorldMatrix * modelSpacePos; worldPos = TransformWorld(modelSpacePos);
#ifdef DISCARD_ALPHA #ifdef DISCARD_ALPHA
texCoord = inTexCoord; texCoord = inTexCoord;
@ -77,8 +82,21 @@ void main(){
projCoord5 = biasMat * m_LightViewProjectionMatrix5 * worldPos; projCoord5 = biasMat * m_LightViewProjectionMatrix5 * worldPos;
#else #else
#ifndef PSSM #ifndef PSSM
vec3 lightDir = worldPos.xyz - m_LightPos; //Spot light
lightDir = worldPos.xyz - m_LightPos;
lightDot = dot(m_LightDir,lightDir); lightDot = dot(m_LightDir,lightDir);
#endif #endif
#endif #endif
#ifndef BACKFACE_SHADOWS
vec3 normal = normalize(TransformWorld(vec4(inNormal,0.0))).xyz;
#ifdef POINTLIGHT
lightDir = worldPos.xyz - m_LightPos;
#else
#ifdef PSSM
lightDir = m_LightDir;
#endif
#endif
nDotL = dot(normal, lightDir);
#endif
} }

@ -18,6 +18,8 @@ uniform mat4 m_LightViewProjectionMatrix1;
uniform mat4 m_LightViewProjectionMatrix2; uniform mat4 m_LightViewProjectionMatrix2;
uniform mat4 m_LightViewProjectionMatrix3; uniform mat4 m_LightViewProjectionMatrix3;
uniform vec2 g_ResolutionInverse;
#ifdef POINTLIGHT #ifdef POINTLIGHT
uniform vec3 m_LightPos; uniform vec3 m_LightPos;
uniform mat4 m_LightViewProjectionMatrix4; uniform mat4 m_LightViewProjectionMatrix4;
@ -39,6 +41,19 @@ vec3 getPosition(in float depth, in vec2 uv){
return pos.xyz / pos.w; return pos.xyz / pos.w;
} }
vec3 approximateNormal(in vec4 worldPos,in vec2 texCoord){
float step = g_ResolutionInverse.x ;
float stepy = g_ResolutionInverse.y ;
float depth2 = texture2D(m_DepthTexture,texCoord + vec2(step,-stepy)).r;
float depth3 = texture2D(m_DepthTexture,texCoord + vec2(-step,-stepy)).r;
vec4 worldPos2 = vec4(getPosition(depth2,texCoord + vec2(step,-stepy)),1.0);
vec4 worldPos3 = vec4(getPosition(depth3,texCoord + vec2(-step,-stepy)),1.0);
vec3 v1 = (worldPos - worldPos2).xyz;
vec3 v2 = (worldPos3 - worldPos2).xyz;
return normalize(cross(v1, v2));
}
void main(){ void main(){
#if !defined( RENDER_SHADOWS ) #if !defined( RENDER_SHADOWS )
gl_FragColor = texture2D(m_Texture,texCoord); gl_FragColor = texture2D(m_Texture,texCoord);
@ -48,6 +63,7 @@ void main(){
float depth = texture2D(m_DepthTexture,texCoord).r; float depth = texture2D(m_DepthTexture,texCoord).r;
vec4 color = texture2D(m_Texture,texCoord); vec4 color = texture2D(m_Texture,texCoord);
//Discard shadow computation on the sky //Discard shadow computation on the sky
if(depth == 1.0){ if(depth == 1.0){
gl_FragColor = color; gl_FragColor = color;
@ -56,6 +72,19 @@ void main(){
// get the vertex in world space // get the vertex in world space
vec4 worldPos = vec4(getPosition(depth,texCoord),1.0); vec4 worldPos = vec4(getPosition(depth,texCoord),1.0);
vec3 normal = approximateNormal(worldPos, texCoord);
vec3 lightDir;
#ifdef PSSM
lightDir = m_LightDir;
#else
lightDir = worldPos.xyz - m_LightPos;
#endif
float ndotl = dot(normal, lightDir);
if(ndotl > -0.0){
gl_FragColor = color;
return;
}
#if (!defined(POINTLIGHT) && !defined(PSSM)) #if (!defined(POINTLIGHT) && !defined(PSSM))
vec3 lightDir = worldPos.xyz - m_LightPos; vec3 lightDir = worldPos.xyz - m_LightPos;

@ -38,13 +38,15 @@ MaterialDef Post Shadow {
Texture2D Texture Texture2D Texture
Texture2D DepthTexture Texture2D DepthTexture
Boolean BackfaceShadows: true
} }
Technique { Technique {
VertexShader GLSL150: Common/MatDefs/Shadow/PostShadowFilter15.vert VertexShader GLSL150: Common/MatDefs/Shadow/PostShadowFilter15.vert
FragmentShader GLSL150: Common/MatDefs/Shadow/PostShadowFilter15.frag FragmentShader GLSL150: Common/MatDefs/Shadow/PostShadowFilter15.frag
WorldParameters { WorldParameters {
ResolutionInverse
} }
Defines { Defines {
@ -59,7 +61,7 @@ MaterialDef Post Shadow {
POINTLIGHT : LightViewProjectionMatrix5 POINTLIGHT : LightViewProjectionMatrix5
//if no shadow map don't render shadows //if no shadow map don't render shadows
RENDER_SHADOWS : ShadowMap0 RENDER_SHADOWS : ShadowMap0
BACKFACE_SHADOWS : BackfaceShadows
} }
} }
@ -68,7 +70,8 @@ MaterialDef Post Shadow {
VertexShader GLSL100: Common/MatDefs/Shadow/PostShadowFilter.vert VertexShader GLSL100: Common/MatDefs/Shadow/PostShadowFilter.vert
FragmentShader GLSL100: Common/MatDefs/Shadow/PostShadowFilter.frag FragmentShader GLSL100: Common/MatDefs/Shadow/PostShadowFilter.frag
WorldParameters { WorldParameters {
ResolutionInverse
} }
Defines { Defines {
@ -79,6 +82,7 @@ MaterialDef Post Shadow {
FADE : FadeInfo FADE : FadeInfo
PSSM : Splits PSSM : Splits
POINTLIGHT : LightViewProjectionMatrix5 POINTLIGHT : LightViewProjectionMatrix5
BACKFACE_SHADOWS : BackfaceShadows
} }
} }

@ -20,14 +20,16 @@ uniform mat4 m_LightViewProjectionMatrix1;
uniform mat4 m_LightViewProjectionMatrix2; uniform mat4 m_LightViewProjectionMatrix2;
uniform mat4 m_LightViewProjectionMatrix3; uniform mat4 m_LightViewProjectionMatrix3;
uniform vec2 g_ResolutionInverse;
#ifdef POINTLIGHT #ifdef POINTLIGHT
uniform vec3 m_LightPos; uniform vec3 m_LightPos;
uniform mat4 m_LightViewProjectionMatrix4; uniform mat4 m_LightViewProjectionMatrix4;
uniform mat4 m_LightViewProjectionMatrix5; uniform mat4 m_LightViewProjectionMatrix5;
#else #else
uniform vec3 m_LightDir;
#ifndef PSSM #ifndef PSSM
uniform vec3 m_LightPos; uniform vec3 m_LightPos;
uniform vec3 m_LightDir;
#endif #endif
#endif #endif
@ -41,6 +43,23 @@ vec3 getPosition(in float depth, in vec2 uv){
return pos.xyz / pos.w; return pos.xyz / pos.w;
} }
#ifndef BACKFACE_SHADOWS
vec3 approximateNormal(in float depth,in vec4 worldPos,in vec2 texCoord, in int numSample){
float step = g_ResolutionInverse.x ;
float stepy = g_ResolutionInverse.y ;
float depth1 = fetchTextureSample(m_DepthTexture,texCoord + vec2(-step,stepy),numSample).r;
float depth2 = fetchTextureSample(m_DepthTexture,texCoord + vec2(step,stepy),numSample).r;
vec3 v1, v2;
vec4 worldPos1 = vec4(getPosition(depth1,texCoord + vec2(-step,stepy)),1.0);
vec4 worldPos2 = vec4(getPosition(depth2,texCoord + vec2(step,stepy)),1.0);
v1 = normalize((worldPos1 - worldPos)).xyz;
v2 = normalize((worldPos2 - worldPos)).xyz;
return normalize(cross(v2, v1));
}
#endif
vec4 main_multiSample(in int numSample){ vec4 main_multiSample(in int numSample){
float depth = fetchTextureSample(m_DepthTexture,texCoord,numSample).r;//getDepth(m_DepthTexture,texCoord).r; float depth = fetchTextureSample(m_DepthTexture,texCoord,numSample).r;//getDepth(m_DepthTexture,texCoord).r;
vec4 color = fetchTextureSample(m_Texture,texCoord,numSample); vec4 color = fetchTextureSample(m_Texture,texCoord,numSample);
@ -52,12 +71,27 @@ vec4 main_multiSample(in int numSample){
// get the vertex in world space // get the vertex in world space
vec4 worldPos = vec4(getPosition(depth,texCoord),1.0); vec4 worldPos = vec4(getPosition(depth,texCoord),1.0);
vec3 lightDir;
#ifdef PSSM
lightDir = m_LightDir;
#else
lightDir = worldPos.xyz - m_LightPos;
#endif
#ifndef BACKFACE_SHADOWS
vec3 normal = approximateNormal(depth, worldPos, texCoord, numSample);
float ndotl = dot(normal, lightDir);
if(ndotl > 0.0){
return color;
}
#endif
#if (!defined(POINTLIGHT) && !defined(PSSM)) #if (!defined(POINTLIGHT) && !defined(PSSM))
vec3 lightDir = worldPos.xyz - m_LightPos; if( dot(m_LightDir,lightDir)<0){
if( dot(m_LightDir,lightDir)<0){ return color;
return color; }
}
#endif #endif
// populate the light view matrices array and convert vertex to light viewProj space // populate the light view matrices array and convert vertex to light viewProj space

@ -40,12 +40,14 @@ import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight; import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight; import com.jme3.light.DirectionalLight;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor; import com.jme3.post.FilterPostProcessor;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.queue.RenderQueue.ShadowMode; import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
@ -69,6 +71,7 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
private Geometry ground; private Geometry ground;
private Material matGroundU; private Material matGroundU;
private Material matGroundL; private Material matGroundL;
private AmbientLight al;
public static void main(String[] args) { public static void main(String[] args) {
TestDirectionalLightShadow app = new TestDirectionalLightShadow(); TestDirectionalLightShadow app = new TestDirectionalLightShadow();
@ -99,7 +102,7 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
mat[0] = assetManager.loadMaterial("Common/Materials/RedColor.j3m"); mat[0] = assetManager.loadMaterial("Common/Materials/RedColor.j3m");
mat[1] = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m"); mat[1] = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
mat[1].setBoolean("UseMaterialColors", true); mat[1].setBoolean("UseMaterialColors", true);
mat[1].setColor("Ambient", ColorRGBA.White.mult(0.5f)); mat[1].setColor("Ambient", ColorRGBA.White);
mat[1].setColor("Diffuse", ColorRGBA.White.clone()); mat[1].setColor("Diffuse", ColorRGBA.White.clone());
@ -110,9 +113,14 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
TangentBinormalGenerator.generate(obj[1]); TangentBinormalGenerator.generate(obj[1]);
TangentBinormalGenerator.generate(obj[0]); TangentBinormalGenerator.generate(obj[0]);
Spatial t = obj[0].clone(false);
t.setLocalScale(10f);
t.setMaterial(mat[1]);
rootNode.attachChild(t);
t.setLocalTranslation(0, 25, 0);
for (int i = 0; i < 60; i++) { for (int i = 0; i < 60; i++) {
Spatial t = obj[FastMath.nextRandomInt(0, obj.length - 1)].clone(false); t = obj[FastMath.nextRandomInt(0, obj.length - 1)].clone(false);
t.setLocalScale(FastMath.nextRandomFloat() * 10f); t.setLocalScale(FastMath.nextRandomFloat() * 10f);
t.setMaterial(mat[FastMath.nextRandomInt(0, mat.length - 1)]); t.setMaterial(mat[FastMath.nextRandomInt(0, mat.length - 1)]);
rootNode.attachChild(t); rootNode.attachChild(t);
@ -142,8 +150,8 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
rootNode.addLight(l); rootNode.addLight(l);
AmbientLight al = new AmbientLight(); al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(0.5f)); al.setColor(ColorRGBA.White.mult(0.02f));
rootNode.addLight(al); rootNode.addLight(al);
Spatial sky = SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false); Spatial sky = SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false);
@ -156,8 +164,11 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
@Override @Override
public void simpleInitApp() { public void simpleInitApp() {
// put the camera in a bad position // put the camera in a bad position
cam.setLocation(new Vector3f(65.25412f, 44.38738f, 9.087874f)); // cam.setLocation(new Vector3f(65.25412f, 44.38738f, 9.087874f));
cam.setRotation(new Quaternion(0.078139365f, 0.050241485f, -0.003942559f, 0.9956679f)); // cam.setRotation(new Quaternion(0.078139365f, 0.050241485f, -0.003942559f, 0.9956679f));
cam.setLocation(new Vector3f(3.3720117f, 42.838284f, -83.43792f));
cam.setRotation(new Quaternion(0.13833192f, -0.08969371f, 0.012581267f, 0.9862358f));
flyCam.setMoveSpeed(100); flyCam.setMoveSpeed(100);
@ -166,7 +177,7 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 3); dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 3);
dlsr.setLight(l); dlsr.setLight(l);
dlsr.setLambda(0.55f); dlsr.setLambda(0.55f);
dlsr.setShadowIntensity(0.6f); dlsr.setShadowIntensity(0.8f);
dlsr.setEdgeFilteringMode(EdgeFilteringMode.Nearest); dlsr.setEdgeFilteringMode(EdgeFilteringMode.Nearest);
dlsr.displayDebug(); dlsr.displayDebug();
viewPort.addProcessor(dlsr); viewPort.addProcessor(dlsr);
@ -174,7 +185,7 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
dlsf = new DirectionalLightShadowFilter(assetManager, SHADOWMAP_SIZE, 3); dlsf = new DirectionalLightShadowFilter(assetManager, SHADOWMAP_SIZE, 3);
dlsf.setLight(l); dlsf.setLight(l);
dlsf.setLambda(0.55f); dlsf.setLambda(0.55f);
dlsf.setShadowIntensity(0.6f); dlsf.setShadowIntensity(0.8f);
dlsf.setEdgeFilteringMode(EdgeFilteringMode.Nearest); dlsf.setEdgeFilteringMode(EdgeFilteringMode.Nearest);
dlsf.setEnabled(false); dlsf.setEnabled(false);
@ -205,10 +216,11 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
inputManager.addMapping("fwd", new KeyTrigger(KeyInput.KEY_PGUP)); inputManager.addMapping("fwd", new KeyTrigger(KeyInput.KEY_PGUP));
inputManager.addMapping("back", new KeyTrigger(KeyInput.KEY_PGDN)); inputManager.addMapping("back", new KeyTrigger(KeyInput.KEY_PGDN));
inputManager.addMapping("pp", new KeyTrigger(KeyInput.KEY_P)); inputManager.addMapping("pp", new KeyTrigger(KeyInput.KEY_P));
inputManager.addMapping("backShadows", new KeyTrigger(KeyInput.KEY_B));
inputManager.addListener(this, "lambdaUp", "lambdaDown", "ThicknessUp", "ThicknessDown", inputManager.addListener(this, "lambdaUp", "lambdaDown", "ThicknessUp", "ThicknessDown",
"switchGroundMat", "debug", "up", "down", "right", "left", "fwd", "back", "pp", "stabilize", "distance"); "switchGroundMat", "debug", "up", "down", "right", "left", "fwd", "back", "pp", "stabilize", "distance", "ShadowUp", "ShadowDown", "backShadows");
ShadowTestUIManager uiMan = new ShadowTestUIManager(assetManager, dlsr, dlsf, guiNode, inputManager, viewPort); ShadowTestUIManager uiMan = new ShadowTestUIManager(assetManager, dlsr, dlsf, guiNode, inputManager, viewPort);
@ -255,12 +267,19 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
dlsf.setLambda(dlsr.getLambda() - 0.01f); dlsf.setLambda(dlsr.getLambda() - 0.01f);
System.out.println("Lambda : " + dlsr.getLambda()); System.out.println("Lambda : " + dlsr.getLambda());
} }
if ((name.equals("ShadowUp") || name.equals("ShadowDown")) && keyPressed) {
al.setColor(ColorRGBA.White.mult((1 - dlsr.getShadowIntensity()) * 0.2f));
}
if (name.equals("debug") && keyPressed) { if (name.equals("debug") && keyPressed) {
dlsr.displayFrustum(); dlsr.displayFrustum();
} }
if (name.equals("backShadows") && keyPressed) {
dlsr.setRenderBackFacesShadows(!dlsr.isRenderBackFacesShadows());
dlsf.setRenderBackFacesShadows(!dlsf.isRenderBackFacesShadows());
}
if (name.equals("stabilize") && keyPressed) { if (name.equals("stabilize") && keyPressed) {
dlsr.setEnabledStabilization(!dlsr.isEnabledStabilization()); dlsr.setEnabledStabilization(!dlsr.isEnabledStabilization());
dlsf.setEnabledStabilization(!dlsf.isEnabledStabilization()); dlsf.setEnabledStabilization(!dlsf.isEnabledStabilization());

@ -32,7 +32,10 @@
package jme3test.light; package jme3test.light;
import com.jme3.app.SimpleApplication; import com.jme3.app.SimpleApplication;
import com.jme3.input.controls.ActionListener;
import com.jme3.light.AmbientLight;
import com.jme3.light.PointLight; import com.jme3.light.PointLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor; import com.jme3.post.FilterPostProcessor;
@ -45,7 +48,7 @@ import com.jme3.shadow.EdgeFilteringMode;
import com.jme3.shadow.PointLightShadowFilter; import com.jme3.shadow.PointLightShadowFilter;
import com.jme3.shadow.PointLightShadowRenderer; import com.jme3.shadow.PointLightShadowRenderer;
public class TestPointLightShadows extends SimpleApplication { public class TestPointLightShadows extends SimpleApplication implements ActionListener{
public static final int SHADOWMAP_SIZE = 512; public static final int SHADOWMAP_SIZE = 512;
public static void main(String[] args) { public static void main(String[] args) {
@ -55,15 +58,21 @@ public class TestPointLightShadows extends SimpleApplication {
Node lightNode; Node lightNode;
PointLightShadowRenderer plsr; PointLightShadowRenderer plsr;
PointLightShadowFilter plsf; PointLightShadowFilter plsf;
AmbientLight al;
@Override @Override
public void simpleInitApp() { public void simpleInitApp () {
flyCam.setMoveSpeed(10); flyCam.setMoveSpeed(10);
cam.setLocation(new Vector3f(0.040581334f, 1.7745866f, 6.155161f)); cam.setLocation(new Vector3f(0.040581334f, 1.7745866f, 6.155161f));
cam.setRotation(new Quaternion(4.3868728E-5f, 0.9999293f, -0.011230096f, 0.0039059948f)); cam.setRotation(new Quaternion(4.3868728E-5f, 0.9999293f, -0.011230096f, 0.0039059948f));
al = new AmbientLight(ColorRGBA.White.mult(0.02f));
rootNode.addLight(al);
Node scene = (Node) assetManager.loadModel("Models/Test/CornellBox.j3o");
Node scene = (Node) assetManager.loadModel("Models/Test/CornellBox_1.j3o");
scene.setShadowMode(RenderQueue.ShadowMode.CastAndReceive); scene.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
rootNode.attachChild(scene); rootNode.attachChild(scene);
rootNode.getChild("Cube").setShadowMode(RenderQueue.ShadowMode.Receive); rootNode.getChild("Cube").setShadowMode(RenderQueue.ShadowMode.Receive);
@ -89,6 +98,7 @@ public class TestPointLightShadows extends SimpleApplication {
plsr.setEdgeFilteringMode(EdgeFilteringMode.PCF4); plsr.setEdgeFilteringMode(EdgeFilteringMode.PCF4);
plsr.setShadowZExtend(15); plsr.setShadowZExtend(15);
plsr.setShadowZFadeLength(5); plsr.setShadowZFadeLength(5);
plsr.setShadowIntensity(0.9f);
// plsr.setFlushQueues(false); // plsr.setFlushQueues(false);
//plsr.displayFrustum(); //plsr.displayFrustum();
plsr.displayDebug(); plsr.displayDebug();
@ -99,18 +109,27 @@ public class TestPointLightShadows extends SimpleApplication {
plsf.setLight((PointLight) scene.getLocalLightList().get(0)); plsf.setLight((PointLight) scene.getLocalLightList().get(0));
plsf.setShadowZExtend(15); plsf.setShadowZExtend(15);
plsf.setShadowZFadeLength(5); plsf.setShadowZFadeLength(5);
plsf.setShadowIntensity(0.8f);
plsf.setEdgeFilteringMode(EdgeFilteringMode.PCF4); plsf.setEdgeFilteringMode(EdgeFilteringMode.PCF4);
plsf.setEnabled(false); plsf.setEnabled(false);
FilterPostProcessor fpp = new FilterPostProcessor(assetManager); FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
fpp.addFilter(plsf); fpp.addFilter(plsf);
viewPort.addProcessor(fpp); viewPort.addProcessor(fpp);
inputManager.addListener(this,"ShadowUp","ShadowDown");
ShadowTestUIManager uiMan = new ShadowTestUIManager(assetManager, plsr, plsf, guiNode, inputManager, viewPort); ShadowTestUIManager uiMan = new ShadowTestUIManager(assetManager, plsr, plsf, guiNode, inputManager, viewPort);
} }
@Override @Override
public void simpleUpdate(float tpf) { public void simpleUpdate(float tpf) {
// lightNode.move(FastMath.cos(tpf) * 0.4f, 0, FastMath.sin(tpf) * 0.4f); // lightNode.move(FastMath.cos(tpf) * 0.4f, 0, FastMath.sin(tpf) * 0.4f);
} }
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if ((name.equals("ShadowUp") || name.equals("ShadowDown")) && isPressed) {
al.setColor(ColorRGBA.White.mult((1 - plsr.getShadowIntensity()) * 0.2f));
}
}
} }
Loading…
Cancel
Save