[committed] DirectionalShadowMapPass border glitches

Hi all,

I've been following the forums for some time and it helped me much, so I thought you could enjoy a modification I made to the DirectionalShadowMapPass to remove the annoying glitches that appear at the rendered texture borders, especially with high definition shadows (see attachment DirectionalShadowMapPass_glitch.jpg)

I'm a noob, so if you have comments I'll be happy to read them.



Here is the patch:


### Eclipse Workspace Patch 1.0
#P jME
Index: src/com/jme/renderer/pass/DirectionalShadowMapPass.java
===================================================================
--- src/com/jme/renderer/pass/DirectionalShadowMapPass.java   (revision 4862)
+++ src/com/jme/renderer/pass/DirectionalShadowMapPass.java   (working copy)
@@ -311,7 +311,8 @@
         shadowMapTexture.setApply(Texture.ApplyMode.Modulate);
         shadowMapTexture
                 .setMinificationFilter(Texture.MinificationFilter.NearestNeighborNoMipMaps);
-        shadowMapTexture.setWrap(Texture.WrapMode.Clamp);
+        shadowMapTexture.setWrap(Texture.WrapMode.BorderClamp);
+        shadowMapTexture.setBorderColor(ColorRGBA.white);
         shadowMapTexture
                 .setMagnificationFilter(Texture.MagnificationFilter.Bilinear);
         shadowMapTexture



I've removed the standard Clamp WrapMode and used the BorderClamp instead. The border color is set to white, too.
This will make the shadow texture to be correctly cut where the texture ends.
Please see attached DirectionalShadowMapPass_noglitch.jpg to see how it looks like with this patch.

Regards

when exactly happens that problem?

is it possible to reproduce the error in TestDirectionalShadowMapPass?

It happens when there is a shadow rendered on the shadow map texture border. For your eyes, you can make the border of the shadow map texture visible enabling the BorderClamp WrapMode.

It appears the shadow is stretched endlessly to the end of the x axis, positive or negative side depending on the border being crossed by the shadow outline.



In the TestDirectionalShadowMapPass class, the field of view is always inside the boundaries of the shadow map texture, so it is very hard to notice the glitch, or even impossible (I never noticed it). The DirectionalShadowMapPass has been configured to perfectly work with the test class, as you might see in the comments of the DirectionalShadowMapPass itself.



Changing the camera input mode to FirstPersonHandler (so you can effectively look around), removing the Fog (just to make it clearer) and increasing the frustum far plane to let say 3000, will make the problem (more) visible.

Decreasing the shadow map scale (e.g.: sPass.setShadowMapScale(0.25f):wink: will also make the problem more invasive, because the texture border will be rendered nearer to the observer.



However, I'm posting below the patch to modify the TestDirectionalShadowMapPass so you can see the problem by yourself. Play with the shadow map scale value to see how it affects the entity of the problem.



Index: src/jmetest/renderer/TestDirectionalShadowMapPass.java
===================================================================
--- src/jmetest/renderer/TestDirectionalShadowMapPass.java   (revision 4862)
+++ src/jmetest/renderer/TestDirectionalShadowMapPass.java   (working copy)
@@ -32,18 +32,14 @@
 
 package jmetest.renderer;
 
-import java.util.HashMap;
-
 import javax.swing.ImageIcon;
 
 import com.jme.app.SimplePassGame;
 import com.jme.bounding.BoundingBox;
 import com.jme.image.Texture;
-import com.jme.input.ChaseCamera;
-import com.jme.input.ThirdPersonHandler;
+import com.jme.input.FirstPersonHandler;
 import com.jme.light.DirectionalLight;
 import com.jme.light.PointLight;
-import com.jme.math.FastMath;
 import com.jme.math.Vector3f;
 import com.jme.renderer.ColorRGBA;
 import com.jme.renderer.Renderer;
@@ -54,7 +50,6 @@
 import com.jme.scene.shape.Box;
 import com.jme.scene.shape.PQTorus;
 import com.jme.scene.state.CullState;
-import com.jme.scene.state.FogState;
 import com.jme.scene.state.TextureState;
 import com.jme.util.TextureManager;
 import com.jmex.terrain.TerrainPage;
@@ -72,9 +67,7 @@
 public class TestDirectionalShadowMapPass extends SimplePassGame {
     private Node m_character;
     private Node occluders;
-    private ChaseCamera chaser;
     private TerrainPage page;
-    private FogState fs;
     private Vector3f normal = new Vector3f();
     private static DirectionalShadowMapPass sPass;
 
@@ -104,10 +97,10 @@
 
         setupCharacter();
         setupTerrain();
-        setupChaseCamera();
         setupInput();
         setupOccluders();
 
+        cam.setFrustumFar(3000);
         rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
 
         RenderPass rPass = new RenderPass();
@@ -124,7 +117,6 @@
     }
 
     protected void simpleUpdate() {
-        chaser.update(tpf);
         float characterMinHeight = page.getHeight(m_character
                 .getLocalTranslation())
                 + ((BoundingBox) m_character.getWorldBound()).yExtent;
@@ -251,16 +243,6 @@
         t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
         t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
         rootNode.setRenderState(ts);
-
-        fs = display.getRenderer().createFogState();
-        fs.setDensity(0.5f);
-        fs.setEnabled(true);
-        fs.setColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));
-        fs.setEnd(1000);
-        fs.setStart(500);
-        fs.setDensityFunction(FogState.DensityFunction.Linear);
-        fs.setQuality(FogState.Quality.PerVertex);
-        rootNode.setRenderState(fs);
     }
 
     private void setupOccluders() {
@@ -293,24 +275,8 @@
         occluders.lock();
     }
 
-    private void setupChaseCamera() {
-        Vector3f targetOffset = new Vector3f();
-        targetOffset.y = ((BoundingBox) m_character.getWorldBound()).yExtent * 1.5f;
-        chaser = new ChaseCamera(cam, m_character);
-        chaser.setTargetOffset(targetOffset);
-        chaser.getMouseLook().setMinRollOut(150);
-        chaser.setMaxDistance(300);
-    }
-
     private void setupInput() {
-        HashMap<String, Object> handlerProps = new HashMap<String, Object>();
-        handlerProps.put(ThirdPersonHandler.PROP_DOGRADUAL, "true");
-        handlerProps.put(ThirdPersonHandler.PROP_TURNSPEED, ""
-                + (.5f * FastMath.PI));
-        handlerProps.put(ThirdPersonHandler.PROP_LOCKBACKWARDS, "true");
-        handlerProps.put(ThirdPersonHandler.PROP_CAMERAALIGNEDMOVE, "true");
-        handlerProps.put(ThirdPersonHandler.PROP_ROTATEONLY, "true");
-        input = new ThirdPersonHandler(m_character, cam, handlerProps);
+        input = new FirstPersonHandler(cam,100,1);
         input.setActionSpeed(100f);
     }
 }



thanks for the example  :slight_smile:

your fix is committed now

thanks  :smiley: