Introduced light culling when rendering shadow maps for all light types. When a light is out of the frustum, the shadow maps are not rendered anymore.

Also implemented proper Zextend and ZFade for al Light type allowing to cap the shadow distance and to smoothly fade shadows in and out
experimental
Nehon 10 years ago
parent 260eb128f6
commit 6e287d0ef2
  1. 41
      jme3-core/src/main/java/com/jme3/shadow/AbstractShadowFilter.java
  2. 117
      jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java
  3. 41
      jme3-core/src/main/java/com/jme3/shadow/DirectionalLightShadowFilter.java
  4. 86
      jme3-core/src/main/java/com/jme3/shadow/DirectionalLightShadowRenderer.java
  5. 29
      jme3-core/src/main/java/com/jme3/shadow/PointLightShadowRenderer.java
  6. 43
      jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowFilter.java
  7. 95
      jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java
  8. 2
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.frag
  9. 9
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.vert
  10. 4
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow15.frag
  11. 13
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow15.vert
  12. 7
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter.frag
  13. 9
      jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter15.frag
  14. 35
      jme3-examples/src/main/java/jme3test/light/TestDirectionalLightShadow.java
  15. 25
      jme3-examples/src/main/java/jme3test/light/TestPointLightShadows.java
  16. 17
      jme3-examples/src/main/java/jme3test/light/TestSpotLightShadows.java

@ -122,6 +122,47 @@ public abstract class AbstractShadowFilter<T extends AbstractShadowRenderer> ext
shadowRenderer.initialize(renderManager, vp);
this.viewPort = vp;
}
/**
* How far the shadows are rendered in the view
*
* @see setShadowZExtend(float zFar)
* @return shadowZExtend
*/
public float getShadowZExtend() {
return shadowRenderer.getShadowZExtend();
}
/**
* Set the distance from the eye where the shadows will be rendered default
* value is dynamicaly computed to the shadow casters/receivers union bound
* zFar, capped to view frustum far value.
*
* @param zFar the zFar values that override the computed one
*/
public void setShadowZExtend(float zFar) {
shadowRenderer.setShadowZExtend(zFar);
}
/**
* 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) {
shadowRenderer.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 shadowRenderer.getShadowZFadeLength();
}
/**
* returns the shdaow intensity

@ -44,6 +44,7 @@ import com.jme3.export.Savable;
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;
@ -109,11 +110,17 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
protected GeometryList shadowMapOccluders = new GeometryList(new OpaqueComparator());
private String[] shadowMapStringCache;
private String[] lightViewStringCache;
/**
* fade shadows at distance
*/
protected float zFarOverride = 0;
protected Vector2f fadeInfo;
protected float fadeLength;
protected Camera frustumCam;
/**
* true to skip the post pass when there are no shadow casters
*/
protected boolean skipPostPass;
/**
* used for serialization
@ -319,7 +326,15 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
} else {
postTechniqueName = "PostShadow";
}
if(zFarOverride>0 && frustumCam == null){
initFrustumCam();
}
}
/**
* delegates the initialization of the frustum cam to child renderers
*/
protected abstract void initFrustumCam();
/**
* Test whether this shadow renderer has been initialized.
@ -373,25 +388,25 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast);
sceneReceivers = rq.getShadowQueueContent(ShadowMode.Receive);
skipPostPass = false;
if (sceneReceivers.size() == 0 || occluders.size() == 0) {
if (sceneReceivers.size() == 0 || occluders.size() == 0 || !checkCulling(viewPort.getCamera())) {
skipPostPass = true;
return;
}
updateShadowCams(viewPort.getCamera());
Renderer r = renderManager.getRenderer();
renderManager.setForcedMaterial(preshadowMat);
renderManager.setForcedTechnique("PreShadow");
for (int shadowMapIndex = 0; shadowMapIndex < nbShadowMaps; shadowMapIndex++) {
if (debugfrustums) {
doDisplayFrustumDebug(shadowMapIndex);
}
renderShadowMap(shadowMapIndex, occluders, sceneReceivers);
if (debugfrustums) {
doDisplayFrustumDebug(shadowMapIndex);
}
renderShadowMap(shadowMapIndex, occluders, sceneReceivers);
}
}
debugfrustums = false;
if (flushQueues) {
@ -402,7 +417,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
renderManager.setForcedMaterial(null);
renderManager.setForcedTechnique(null);
renderManager.setCamera(viewPort.getCamera(), false);
}
protected void renderShadowMap(int shadowMapIndex, GeometryList occluders, GeometryList receivers) {
@ -512,6 +527,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
for (int j = 1; j < nbShadowMaps; j++) {
mat.clearParam(shadowMapStringCache[j]);
}
mat.clearParam("FadeInfo");
clearMaterialParameters(mat);
}
//No need to clear the postShadowMat params as the instance is locale to each renderer
@ -559,7 +575,9 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
mat.setInt("FilterMode", edgeFilteringMode.getMaterialParamValue());
mat.setFloat("PCFEdge", edgesThickness);
mat.setFloat("ShadowIntensity", shadowIntensity);
if (fadeInfo != null) {
mat.setVector2("FadeInfo", fadeInfo);
}
setMaterialParameters(mat);
}
@ -580,9 +598,86 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
postshadowMat.setMatrix4(lightViewStringCache[j], lightViewProjectionsMatrices[j]);
postshadowMat.setTexture(shadowMapStringCache[j], shadowMaps[j]);
}
if (fadeInfo != null) {
postshadowMat.setVector2("FadeInfo", fadeInfo);
}
}
/**
* How far the shadows are rendered in the view
*
* @see #setShadowZExtend(float zFar)
* @return shadowZExtend
*/
public float getShadowZExtend() {
return zFarOverride;
}
/**
* Set the distance from the eye where the shadows will be rendered default
* value is dynamicaly computed to the shadow casters/receivers union bound
* zFar, capped to view frustum far value.
*
* @param zFar the zFar values that override the computed one
*/
public void setShadowZExtend(float zFar) {
this.zFarOverride = zFar;
if(zFarOverride == 0){
fadeInfo = null;
frustumCam = null;
}else{
if (fadeInfo != null) {
fadeInfo.set(zFarOverride - fadeLength, 1f / fadeLength);
}
if(frustumCam == null && viewPort != null){
initFrustumCam();
}
}
}
/**
* 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;
}
/**
* returns true if the light source bounding box is in the view frustum
* @return
*/
protected abstract boolean checkCulling(Camera viewCam);
public void preFrame(float tpf) {
public void preFrame(float tpf) {
}
public void cleanup() {

@ -114,47 +114,6 @@ public class DirectionalLightShadowFilter extends AbstractShadowFilter<Direction
shadowRenderer.setLambda(lambda);
}
/**
* How far the shadows are rendered in the view
*
* @see setShadowZExtend(float zFar)
* @return shadowZExtend
*/
public float getShadowZExtend() {
return shadowRenderer.getShadowZExtend();
}
/**
* Set the distance from the eye where the shadows will be rendered default
* value is dynamicaly computed to the shadow casters/receivers union bound
* zFar, capped to view frustum far value.
*
* @param zFar the zFar values that override the computed one
*/
public void setShadowZExtend(float zFar) {
shadowRenderer.setShadowZExtend(zFar);
}
/**
* 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) {
shadowRenderer.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 shadowRenderer.getShadowZFadeLength();
}
/**
* retruns true if stabilization is enabled
* @return

@ -59,16 +59,13 @@ import java.io.IOException;
*/
public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
protected float lambda = 0.65f;
protected float zFarOverride = 0;
protected float lambda = 0.65f;
protected Camera shadowCam;
protected ColorRGBA splits;
protected float[] splitsArray;
protected DirectionalLight light;
protected Vector3f[] points = new Vector3f[8];
//Holding the info for fading shadows in the far distance
protected Vector2f fadeInfo;
protected float fadeLength;
//Holding the info for fading shadows in the far distance
private boolean stabilize = true;
/**
@ -109,6 +106,13 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
}
}
@Override
protected void initFrustumCam() {
//nothing to do
}
/**
* return the light used to cast shadows
*
@ -232,67 +236,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
this.lambda = lambda;
}
/**
* How far the shadows are rendered in the view
*
* @see #setShadowZExtend(float zFar)
* @return shadowZExtend
*/
public float getShadowZExtend() {
return zFarOverride;
}
/**
* Set the distance from the eye where the shadows will be rendered default
* value is dynamicaly computed to the shadow casters/receivers union bound
* zFar, capped to view frustum far value.
*
* @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;
}
/**
* 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;
}
/**
* retruns true if stabilization is enabled
* @return
@ -333,4 +277,14 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
oc.write(fadeInfo, "fadeInfo", null);
oc.write(fadeLength, "fadeLength", 0f);
}
/**
* Directional light are always in the view frustum
* @param viewCam
* @return
*/
@Override
protected boolean checkCulling(Camera viewCam) {
return true;
}
}

@ -43,6 +43,7 @@ import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.GeometryList;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.util.TempVars;
import java.io.IOException;
/**
@ -84,6 +85,14 @@ public class PointLightShadowRenderer extends AbstractShadowRenderer {
shadowCams[i] = new Camera(shadowMapSize, shadowMapSize);
}
}
@Override
protected void initFrustumCam() {
Camera viewCam = viewPort.getCamera();
frustumCam = viewCam.clone();
frustumCam.setFrustum(viewCam.getFrustumNear(), zFarOverride, viewCam.getFrustumLeft(), viewCam.getFrustumRight(), viewCam.getFrustumTop(), viewCam.getFrustumBottom());
}
@Override
protected void updateShadowCams(Camera viewCam) {
@ -197,4 +206,24 @@ public class PointLightShadowRenderer extends AbstractShadowRenderer {
OutputCapsule oc = (OutputCapsule) ex.getCapsule(this);
oc.write(light, "light", null);
}
/**
*
* @param viewCam
* @return
*/
@Override
protected boolean checkCulling(Camera viewCam) {
Camera cam = viewCam;
if(frustumCam != null){
cam = frustumCam;
cam.setLocation(viewCam.getLocation());
cam.setRotation(viewCam.getRotation());
}
TempVars vars = TempVars.get();
boolean intersects = light.intersectsFrustum(cam,vars);
vars.release();
return intersects;
}
}

@ -84,48 +84,7 @@ public class SpotLightShadowFilter extends AbstractShadowFilter<SpotLightShadowR
public void setLight(SpotLight light) {
shadowRenderer.setLight(light);
}
/**
* How far the shadows are rendered in the view
*
* @see setShadowZExtend(float zFar)
* @return shadowZExtend
*/
public float getShadowZExtend() {
return shadowRenderer.getShadowZExtend();
}
/**
* Set the distance from the eye where the shadows will be rendered default
* value is dynamicaly computed to the shadow casters/receivers union bound
* zFar, capped to view frustum far value.
*
* @param zFar the zFar values that override the computed one
*/
public void setShadowZExtend(float zFar) {
shadowRenderer.setShadowZExtend(zFar);
}
/**
* 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) {
shadowRenderer.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 shadowRenderer.getShadowZFadeLength();
}
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);

@ -44,6 +44,7 @@ import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.GeometryList;
import com.jme3.scene.Node;
import com.jme3.util.TempVars;
import java.io.IOException;
/**
@ -59,15 +60,12 @@ import java.io.IOException;
*/
public class SpotLightShadowRenderer extends AbstractShadowRenderer {
protected float zFarOverride = 0;
protected Camera shadowCam;
protected SpotLight light;
protected Vector3f[] points = new Vector3f[8];
//Holding the info for fading shadows in the far distance
protected Vector2f fadeInfo;
protected float fadeLength;
/**
* Used for serialization use SpotLightShadowRenderer#SpotLightShadowRenderer(AssetManager assetManager, int shadowMapSize)
*/
@ -94,7 +92,14 @@ public class SpotLightShadowRenderer extends AbstractShadowRenderer {
points[i] = new Vector3f();
}
}
@Override
protected void initFrustumCam() {
Camera viewCam = viewPort.getCamera();
frustumCam = viewCam.clone();
frustumCam.setFrustum(viewCam.getFrustumNear(), zFarOverride, viewCam.getFrustumLeft(), viewCam.getFrustumRight(), viewCam.getFrustumTop(), viewCam.getFrustumBottom());
}
/**
* return the light used to cast shadows
*
@ -173,67 +178,7 @@ public class SpotLightShadowRenderer extends AbstractShadowRenderer {
material.clearParam("LightPos");
material.clearParam("LightDir");
}
/**
* How far the shadows are rendered in the view
*
* @see #setShadowZExtend(float zFar)
* @return shadowZExtend
*/
public float getShadowZExtend() {
return zFarOverride;
}
/**
* Set the distance from the eye where the shadows will be rendered default
* value is dynamicaly computed to the shadow casters/receivers union bound
* zFar, capped to view frustum far value.
*
* @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;
}
/**
* 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;
}
@Override
public void read(JmeImporter im) throws IOException {
@ -256,5 +201,25 @@ public class SpotLightShadowRenderer extends AbstractShadowRenderer {
oc.write(fadeInfo, "fadeInfo", null);
oc.write(fadeLength, "fadeLength", 0f);
}
/**
*
* @param viewCam
* @return
*/
@Override
protected boolean checkCulling(Camera viewCam) {
Camera cam = viewCam;
if(frustumCam != null){
cam = frustumCam;
cam.setLocation(viewCam.getLocation());
cam.setRotation(viewCam.getRotation());
}
TempVars vars = TempVars.get();
boolean intersects = light.intersectsFrustum(cam,vars);
vars.release();
return intersects;
}
}

@ -1,6 +1,6 @@
#import "Common/ShaderLib/Shadows.glsllib"
#ifdef PSSM
#if defined(PSSM) || defined(FADE)
varying float shadowPosition;
#endif

@ -25,7 +25,7 @@ varying vec4 projCoord3;
#endif
#endif
#ifdef PSSM
#if defined(PSSM) || defined(FADE)
varying float shadowPosition;
#endif
varying vec3 lightVec;
@ -52,10 +52,11 @@ void main(){
#endif
gl_Position = TransformWorldViewProjection(modelSpacePos);
#if defined(PSSM) || defined(FADE)
shadowPosition = gl_Position.z;
#endif
#ifndef POINTLIGHT
#ifdef PSSM
shadowPosition = gl_Position.z;
#endif
vec4 worldPos=vec4(0.0);
#endif
// get the vertex in world space

@ -2,7 +2,7 @@
out vec4 outFragColor;
#ifdef PSSM
#if defined(PSSM) || defined(FADE)
in float shadowPosition;
#endif
@ -71,7 +71,7 @@ void main(){
#endif
#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
shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);

@ -25,8 +25,8 @@ out vec4 projCoord3;
#endif
#endif
#ifdef PSSM
out float shadowPosition;
#if defined(PSSM) || defined(FADE)
out float shadowPosition;
#endif
out vec3 lightVec;
@ -51,11 +51,12 @@ void main(){
Skinning_Compute(modelSpacePos);
#endif
gl_Position = TransformWorldViewProjection(modelSpacePos);
#if defined(PSSM) || defined(FADE)
shadowPosition = gl_Position.z;
#endif
#ifndef POINTLIGHT
#ifdef PSSM
shadowPosition = gl_Position.z;
#endif
#ifndef POINTLIGHT
vec4 worldPos=vec4(0.0);
#endif
// get the vertex in world space

@ -77,13 +77,16 @@ void main(){
float shadow = 1.0;
#if defined(PSSM) || defined(FADE)
float shadowPosition = m_ViewProjectionMatrixRow2.x * worldPos.x + m_ViewProjectionMatrixRow2.y * worldPos.y + m_ViewProjectionMatrixRow2.z * worldPos.z + m_ViewProjectionMatrixRow2.w;
#endif
#ifdef POINTLIGHT
shadow = getPointLightShadows(worldPos, m_LightPos,
m_ShadowMap0,m_ShadowMap1,m_ShadowMap2,m_ShadowMap3,m_ShadowMap4,m_ShadowMap5,
projCoord0, projCoord1, projCoord2, projCoord3, projCoord4, projCoord5);
#else
#ifdef PSSM
float shadowPosition = m_ViewProjectionMatrixRow2.x * worldPos.x + m_ViewProjectionMatrixRow2.y * worldPos.y + m_ViewProjectionMatrixRow2.z * worldPos.z + m_ViewProjectionMatrixRow2.w;
shadow = getDirectionalLightShadows(m_Splits, shadowPosition,
m_ShadowMap0,m_ShadowMap1,m_ShadowMap2,m_ShadowMap3,
projCoord0, projCoord1, projCoord2, projCoord3);
@ -94,7 +97,7 @@ void main(){
#endif
#ifdef FADE
shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y));
shadow = clamp(max(0.0,mix(shadow, 1.0 ,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y)),0.0,1.0);
#endif
shadow= shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);
gl_FragColor = color * vec4(shadow, shadow, shadow, 1.0);

@ -71,14 +71,17 @@ vec4 main_multiSample(in int numSample){
#endif
float shadow = 1.0;
#if defined(PSSM) || defined(FADE)
float shadowPosition = m_ViewProjectionMatrixRow2.x * worldPos.x + m_ViewProjectionMatrixRow2.y * worldPos.y + m_ViewProjectionMatrixRow2.z * worldPos.z + m_ViewProjectionMatrixRow2.w;
#endif
#ifdef POINTLIGHT
shadow = getPointLightShadows(worldPos, m_LightPos,
m_ShadowMap0,m_ShadowMap1,m_ShadowMap2,m_ShadowMap3,m_ShadowMap4,m_ShadowMap5,
projCoord0, projCoord1, projCoord2, projCoord3, projCoord4, projCoord5);
#else
#ifdef PSSM
float shadowPosition = m_ViewProjectionMatrixRow2.x * worldPos.x + m_ViewProjectionMatrixRow2.y * worldPos.y + m_ViewProjectionMatrixRow2.z * worldPos.z + m_ViewProjectionMatrixRow2.w;
#ifdef PSSM
shadow = getDirectionalLightShadows(m_Splits, shadowPosition,
m_ShadowMap0,m_ShadowMap1,m_ShadowMap2,m_ShadowMap3,
projCoord0, projCoord1, projCoord2, projCoord3);
@ -90,7 +93,7 @@ vec4 main_multiSample(in int numSample){
#ifdef FADE
shadow = max(0.0,mix(shadow,1.0,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y));
shadow = clamp(max(0.0,mix(shadow, 1.0 ,(shadowPosition - m_FadeInfo.x) * m_FadeInfo.y)),0.0,1.0);
#endif
shadow= shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);

@ -60,8 +60,8 @@ import com.jme3.util.SkyFactory;
import com.jme3.util.TangentBinormalGenerator;
public class TestDirectionalLightShadow extends SimpleApplication implements ActionListener, AnalogListener {
public static final int SHADOWMAP_SIZE = 1024;
public static final int SHADOWMAP_SIZE = 1024;
private Spatial[] obj;
private Material[] mat;
private DirectionalLightShadowRenderer dlsr;
@ -195,6 +195,7 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
inputManager.addMapping("switchGroundMat", new KeyTrigger(KeyInput.KEY_M));
inputManager.addMapping("debug", new KeyTrigger(KeyInput.KEY_X));
inputManager.addMapping("stabilize", new KeyTrigger(KeyInput.KEY_B));
inputManager.addMapping("distance", new KeyTrigger(KeyInput.KEY_N));
inputManager.addMapping("up", new KeyTrigger(KeyInput.KEY_NUMPAD8));
@ -207,21 +208,29 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
inputManager.addListener(this, "lambdaUp", "lambdaDown", "ThicknessUp", "ThicknessDown",
"switchGroundMat", "debug", "up", "down", "right", "left", "fwd", "back", "pp","stabilize");
"switchGroundMat", "debug", "up", "down", "right", "left", "fwd", "back", "pp", "stabilize", "distance");
ShadowTestUIManager uiMan = new ShadowTestUIManager(assetManager, dlsr, dlsf, guiNode, inputManager, viewPort);
inputManager.addListener(this, "Size+", "Size-");
inputManager.addMapping("Size+", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Size-", new KeyTrigger(KeyInput.KEY_S));
shadowStabilizationText = new BitmapText(guiFont, false);
shadowStabilizationText.setSize(guiFont.getCharSet().getRenderedSize() * 0.75f);
shadowStabilizationText.setText("(b:on/off) Shadow stabilization : " + dlsr.isEnabledStabilization());
shadowStabilizationText.setLocalTranslation(10, viewPort.getCamera().getHeight() - 100, 0);
guiNode.attachChild(shadowStabilizationText);
shadowZfarText = new BitmapText(guiFont, false);
shadowZfarText.setSize(guiFont.getCharSet().getRenderedSize() * 0.75f);
shadowZfarText.setText("(n:on/off) Shadow extend to 500 and fade to 50 : " + (dlsr.getShadowZExtend() > 0));
shadowZfarText.setLocalTranslation(10, viewPort.getCamera().getHeight() - 120, 0);
guiNode.attachChild(shadowZfarText);
}
private BitmapText shadowStabilizationText ;
private BitmapText shadowStabilizationText;
private BitmapText shadowZfarText;
public void onAction(String name, boolean keyPressed, float tpf) {
@ -254,9 +263,25 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
if (name.equals("stabilize") && keyPressed) {
dlsr.setEnabledStabilization(!dlsr.isEnabledStabilization());
dlsf.setEnabledStabilization(!dlsf.isEnabledStabilization());
dlsf.setEnabledStabilization(!dlsf.isEnabledStabilization());
shadowStabilizationText.setText("(b:on/off) Shadow stabilization : " + dlsr.isEnabledStabilization());
}
if (name.equals("distance") && keyPressed) {
if (dlsr.getShadowZExtend() > 0) {
dlsr.setShadowZExtend(0);
dlsr.setShadowZFadeLength(0);
dlsf.setShadowZExtend(0);
dlsf.setShadowZFadeLength(0);
} else {
dlsr.setShadowZExtend(500);
dlsr.setShadowZFadeLength(50);
dlsf.setShadowZExtend(500);
dlsf.setShadowZFadeLength(50);
}
shadowZfarText.setText("(n:on/off) Shadow extend to 500 and fade to 50 : " + (dlsr.getShadowZExtend() > 0));
}
if (name.equals("switchGroundMat") && keyPressed) {
if (ground.getMaterial() == matGroundL) {

@ -87,33 +87,18 @@ public class TestPointLightShadows extends SimpleApplication {
plsr = new PointLightShadowRenderer(assetManager, SHADOWMAP_SIZE);
plsr.setLight((PointLight) scene.getLocalLightList().get(0));
plsr.setEdgeFilteringMode(EdgeFilteringMode.PCF4);
plsr.setShadowZExtend(15);
plsr.setShadowZFadeLength(5);
// plsr.setFlushQueues(false);
//plsr.displayFrustum();
plsr.displayDebug();
viewPort.addProcessor(plsr);
// PointLight pl = new PointLight();
// pl.setPosition(new Vector3f(0, 0.5f, 0));
// pl.setRadius(5);
// rootNode.addLight(pl);
//
// Geometry lightMdl2 = new Geometry("Light2", new Sphere(10, 10, 0.1f));
// //Geometry lightMdl = new Geometry("Light", new Box(.1f,.1f,.1f));
// lightMdl2.setMaterial(assetManager.loadMaterial("Common/Materials/RedColor.j3m"));
// lightMdl2.setShadowMode(RenderQueue.ShadowMode.Off);
// rootNode.attachChild(lightMdl2);
// lightMdl2.setLocalTranslation(pl.getPosition());
// PointLightShadowRenderer plsr2 = new PointLightShadowRenderer(assetManager, 512);
// plsr2.setShadowIntensity(0.3f);
// plsr2.setLight(pl);
// plsr2.setEdgeFilteringMode(EdgeFilteringMode.PCF4);
// // plsr.displayDebug();
// viewPort.addProcessor(plsr2);
plsf = new PointLightShadowFilter(assetManager, SHADOWMAP_SIZE);
plsf.setLight((PointLight) scene.getLocalLightList().get(0));
plsf.setLight((PointLight) scene.getLocalLightList().get(0));
plsf.setShadowZExtend(15);
plsf.setShadowZFadeLength(5);
plsf.setEdgeFilteringMode(EdgeFilteringMode.PCF4);
plsf.setEnabled(false);

@ -36,7 +36,6 @@ import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.light.SpotLight;
import com.jme3.material.Material;
import com.jme3.math.*;
@ -46,12 +45,11 @@ import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.shader.VarType;
import com.jme3.shadow.CompareMode;
import com.jme3.shadow.EdgeFilteringMode;
import com.jme3.shadow.SpotLightShadowFilter;
import com.jme3.shadow.SpotLightShadowRenderer;
import com.jme3.texture.Texture.WrapMode;
import com.jme3.util.MaterialDebugAppState;
import com.jme3.util.TangentBinormalGenerator;
public class TestSpotLightShadows extends SimpleApplication {
@ -78,7 +76,7 @@ public class TestSpotLightShadows extends SimpleApplication {
spot.setSpotInnerAngle(5f * FastMath.DEG_TO_RAD);
spot.setSpotOuterAngle(10 * FastMath.DEG_TO_RAD);
spot.setPosition(new Vector3f(70.70334f, 34.013165f, 27.1017f));
spot.setDirection(lightTarget.subtract(spot.getPosition()));
spot.setDirection(lightTarget.subtract(spot.getPosition()).normalizeLocal());
spot.setColor(ColorRGBA.White.mult(2));
rootNode.addLight(spot);
@ -103,12 +101,16 @@ public class TestSpotLightShadows extends SimpleApplication {
final SpotLightShadowRenderer slsr = new SpotLightShadowRenderer(assetManager, 512);
slsr.setLight(spot);
slsr.setShadowIntensity(0.5f);
slsr.setShadowZExtend(100);
slsr.setShadowZFadeLength(5);
slsr.setEdgeFilteringMode(EdgeFilteringMode.PCFPOISSON);
viewPort.addProcessor(slsr);
SpotLightShadowFilter slsf = new SpotLightShadowFilter(assetManager, 512);
slsf.setLight(spot);
slsf.setShadowIntensity(0.5f);
slsf.setShadowZExtend(100);
slsf.setShadowZFadeLength(5);
slsf.setEdgeFilteringMode(EdgeFilteringMode.PCFPOISSON);
slsf.setEnabled(false);
@ -130,7 +132,12 @@ public class TestSpotLightShadows extends SimpleApplication {
}, "stop");
inputManager.addMapping("stop", new KeyTrigger(KeyInput.KEY_1));
MaterialDebugAppState s = new MaterialDebugAppState();
s.registerBinding("Common/MatDefs/Shadow/PostShadow15.frag", rootNode);
s.registerBinding(new KeyTrigger(KeyInput.KEY_R), rootNode);
stateManager.attach(s);
flyCam.setDragToRotate(true);
}
public void setupFloor() {

Loading…
Cancel
Save