Shadows appear and disappear

I noticed that the shadows in my app occasionally disappear, like this:

I turn a bit, and the shadow disappears:

I did modify the shadows a little, especially with my materials’ PostShadow.frag, so that they can do exponential shadow mapping (ESM).
As you can see at the bottom of both images, the depth map suddenly changes, which is surely related to the problem. I’m pretty sure that it’s not something I did, but anyway, any ideas why this is happening? For example, could it be because I only use 1 split?

Both image links are identical.

@pspeed Fixed (I’m having a bit difficult time adjusting to the new UI :-P)

So far I’ve only found that sometimes shadows get darker as you look up and lighter as you look down… :-/

Does this happen with the non-modified version? If not, can you post the updated shader code?

I didn’t see this post before.
That’s interesting that you use ESM.
How did you implement it?

For your issue, did you base your modifications on the current SVN or on RC2 version?
I changed lots of things on shadows not so long ago and fixed dozens of issues.

I said “I’m pretty sure that it’s not something I did” on my first post, but I take that back, since I think I actually changed it quite a lot from the original…
@nehon I currently don’t have access on to my main laptop so I can’t fully explain, but it was pretty simple (if I did it correctly, that is). This was extremely helpful. At the bottom, there’s tabs with a demo, source code (in GLSL), and the explanation. On the right there’s tutorials on other effects (latest as of now is bloom). Since the “bloom” tutorial is the latest, it shows the updated effects “unlocked” in the series. Only a third of it’s covered though.
The page also covers VSM, but I went with ESM since it seemed like it produced results almost as nice as VSM while having less work (on me and the computer).

@t0neg0d I tested it, and the shadows in the scene stay, but the depth map does the same thing.

I made a simple test case modified from one of the JME tests.

[java]
package something;

import com.jme3.app.SimpleApplication;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.*;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Quad;
import com.jme3.scene.shape.Sphere;
import com.jme3.shadow.DirectionalLightShadowRenderer;
import com.jme3.shadow.EdgeFilteringMode;
import com.jme3.texture.Texture.ShadowCompareMode;

public class Test extends SimpleApplication {

public static void main(String[] args){
    Test app = new Test();
    app.start();
}

public void simpleInitApp() {

    cam.setLocation(new Vector3f(5.700248f, 6.161693f, 5.1404157f));
    cam.setRotation(new Quaternion(-0.09441641f, 0.8993388f, -0.24089815f, -0.35248178f));

    viewPort.setBackgroundColor(ColorRGBA.DarkGray);

    Quad q = new Quad(20, 20);
    q.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(10));
    Geometry geom = new Geometry("floor", q);
    Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
    mat.setFloat("Shininess", 0);
    geom.setMaterial(mat);
    
    geom.rotate(-FastMath.HALF_PI, 0, 0);
    geom.center();
    geom.setShadowMode(ShadowMode.CastAndReceive);
    rootNode.attachChild(geom);

       
    AmbientLight al = new AmbientLight();
    al.setColor(ColorRGBA.White.mult(0.7f));
    rootNode.addLight(al);

    DirectionalLight dl1 = new DirectionalLight();
    dl1.setDirection(new Vector3f(0, -1, 0.5f).normalizeLocal());
    dl1.setColor(ColorRGBA.White.mult(1.5f));
    rootNode.addLight(dl1);

    //rootNode.attachChild(tree);    
    
    /** Uses Texture from jme3-test-data library! */

// ParticleEmitter fire = new ParticleEmitter(“Emitter”, ParticleMesh.Type.Triangle, 30);
// Material mat_red = new Material(assetManager, “Common/MatDefs/Misc/Particle.j3md”);
// mat_red.setTexture(“Texture”, assetManager.loadTexture(“Effects/Explosion/flame.png”));
// //mat_red.getAdditionalRenderState().setDepthTest(true);
// //mat_red.getAdditionalRenderState().setDepthWrite(true);
// fire.setMaterial(mat_red);
// fire.setImagesX(2); fire.setImagesY(2); // 2x2 texture animation
// fire.setEndColor( new ColorRGBA(1f, 0f, 0f, 1f)); // red
// fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
// fire.setInitialVelocity(new Vector3f(0, 2, 0));
// fire.setStartSize(0.6f);
// fire.setEndSize(0.1f);
// fire.setGravity(0, 0, 0);
// fire.setLowLife(0.5f);
// fire.setHighLife(1.5f);
// fire.setVelocityVariation(0.3f);
// fire.setLocalTranslation(1.0f, 0, 1.0f);
// fire.setLocalScale(0.3f);
// fire.setQueueBucket(Bucket.Translucent);
// rootNode.attachChild(fire);

    Material mat2 = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");  


    Geometry ball = new Geometry("sphere", new Sphere(16, 16, 0.5f));
    ball.setMaterial(mat2);
    ball.setShadowMode(ShadowMode.CastAndReceive);
    rootNode.attachChild(ball);
    ball.setLocalTranslation(-1.0f, 1.5f, 1.0f);
     
     
    DirectionalLightShadowRenderer dlShadowRenderer = new DirectionalLightShadowRenderer(assetManager, 1024, 1);
    dlShadowRenderer.setLight(dl1);
    dlShadowRenderer.setLambda(0.55f);
    dlShadowRenderer.setShadowIntensity(0.8f);
    //dlShadowRenderer.setShadowCompareMode(com.jme3.shadow.CompareMode.Software);
    //dlShadowRenderer.setEdgeFilteringMode(EdgeFilteringMode.Bilinear);
    dlShadowRenderer.displayDebug();
     viewPort.addProcessor(dlShadowRenderer);
}

}
[/java]

This (at least on my comp) produces these:


The shadows themselves are okay, but it looks like it produces the same problem with the depth maps. It’s pretty subtle, but if you look at the depths closely, the top one’s a bit darker. Also, you need to be at a certain position to reproduce this problem.
This doesn’t seem to produce problems for the shadows already in the core, since it basically tests if the pixel is or isn’t behind a shadow caster in the light perspective. So if the depth map isn’t that different, there’s no noticeable change in shadows. However, in exponential shadow mapping, the distance between the caster and the tested pixel really matters.

2 Likes

The depth is the hardware depth, there si no fancy things done to create the shadow maps.
How do you compute them?

@nehon I’m pretty sure that it’s the same way AbstractShadowRenderer does it, since it’s mostly copy-pasted code. But even the built-in shadows seems to have that error (?), as seen above. I’m starting to think that if there is something wrong in the code, it’s something to do with cameras or rendering, so I’m looking around that.

Mhh… i think i have an issue the debug shadow maps are completely white (even with the TestDirectionalLights) but shadows still works fine.
I changed my graphic card recently so something must be different…

Think I found the source. DirectionalLightShadowRenderer.getOccludersToRender(…) uses ShadowUtil.updateShadowCamera(…). Method updateShadowCamera’s local variables scaleZ and offsetZ seems to be causing it. If I set scaleZ and offsetZ to static numbers, the depth changing stops. Don’t think I’m gonna look for an actual fix immediately, since I don’t know s**t about matrices. Maybe someone can find a way easily?

2 Likes

Oh nice catch, gonna look into it.