Issue with shadows showing through solid objects

It’s very hard to explain so I made a mini slideshow showing the problem : http://imgur.com/a/7n5ht

Bassically there are times when you shouldnt be able to see a shadow because it is behind a solid object. but the shadow gets drawn “through” the object.

To make this problem even harder to troubleshoot. it only happens SOMETIMES. Theres been times where I thought I fixed this issue but really it just stopped happening.

I’m using JM3 RC2, and I’m using PSSM shadows. Some of the geoms are in different “render buckets” because they contain transparency. (which is what I think the problem is related to but its hard to tell since it works fine sometimes).

Has anyone else ever had this issue, or know what I should look in to fix it?

Without code it’s gonna be hard to debug.
How do you setup your scene? what is in what bucket? do you have post filters?
Did you somehow disable depth write on some of your models?

I wasn’t really sure where I should have started posting code. my project is quite large I felt like I would just be bombarding the thread with code no one wants to read.

All the game assets (including the scene) are made in blender, then exporter to ogre before imported into jmonkey. Everything is directly added to the rootNode. I don’t do anything like add the plane to the node that holds the scene model or anything, as far as I can tell it doesnt make a difference.

I use 2 renders in my game, i create them with this code:

[java]PssmShadowRenderer shadowRenderer = new PssmShadowRenderer(assetManager, 1024, 3);
Vector3f dir = UtJme.convertBlenderVectorToJmeVectorLocal(new Vector3f(107, -24, 160));
shadowRenderer.setDirection(dir);
shadowRenderer.setLambda(0.7f);
shadowRenderer.setShadowIntensity(.3f);
shadowRenderer.setCompareMode(PssmShadowRenderer.CompareMode.Hardware);
shadowRenderer.setFilterMode(PssmShadowRenderer.FilterMode.Dither);

FilterPostProcessor filterPostProcessor = new FilterPostProcessor(assetManager);
CartoonEdgeFilter cef = new CartoonEdgeFilter();
cef.setEdgeIntensity(.5f);
cef.setEdgeWidth(.6f);
filterPostProcessor.addFilter(cef);[/java]

Everything in the game is in the opaque render bucket. except for the propellers of the airplanes, which are in the transparent bucket (the propellers are just plane meshes with a texture that lookings like whirring blades)

this is the code I use to load the airplane model:

[java]Node node = (Node) assetManager.loadModel(“Models/Aircraft/c130/c130.mesh.j3o”);

        Geometry c130 = (Geometry) node.getChild("c130");
        c130.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
        Geometry prop = (Geometry) node.getChild("prop");
        c130.setShadowMode(RenderQueue.ShadowMode.Cast);

        Material mat;
        RenderState renderState;

        mat = prop.getMaterial();
        ColorRGBA diffuseColor = (ColorRGBA) mat.getParam("Diffuse").getValue();
        diffuseColor = diffuseColor.clone();
        diffuseColor.a = 1;
        mat.setFloat("AlphaDiscardThreshold", .08f);
        mat.setColor("Diffuse", diffuseColor);
        mat.setBoolean("UseAlpha", true);
        mat.setBoolean("UseMaterialColors", true);
        prop.setQueueBucket(RenderQueue.Bucket.Transparent);
        renderState = mat.getAdditionalRenderState();
        renderState.setBlendMode(RenderState.BlendMode.Alpha);[/java] 

The desert scene is just a regular model, except for the foliage which are flat planes with textures that use alpha. The rocks and cactuses are regular models. The code I use to go through the desert scene and modify the foliage to use alpha looks like this:

[java]private static Geometry applyAlpha(Spatial spatial) {
if (spatial instanceof Geometry) {
Geometry geom = (Geometry) spatial;
Material mat = geom.getMaterial();
ColorRGBA diffuseColor = (ColorRGBA) mat.getParam(“Diffuse”).getValue();
if (diffuseColor.a == 0) {
diffuseColor = diffuseColor.clone();
diffuseColor.a = 1;
mat.setColor(“Diffuse”, diffuseColor);
mat.setFloat(“AlphaDiscardThreshold”, .08f);
mat.setBoolean(“UseMaterialColors”, true);
geom.setQueueBucket(RenderQueue.Bucket.Opaque);
}
return geom;
} else {
Node node = (Node) spatial;
Geometry geom = null;
for (Spatial s : node.getChildren()) {
geom = applyAlpha(s);
}
return geom;
}
}[/java]

so to use this I would load the desert scene with this code:

[java]Node scene = (Node) assetManager.loadModel(“Scenes/DesertScene_05/DesertScene_05.j3o”);
scene.setShadowMode(ShadowMode.Receive);
scene.move(0, .2f, -280);

        rootNode.attachChild(scene);

        applyAlpha(scene);[/java]

the scene is just an ambient light and a directional light (in the same direction as the shadow)

[java]
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(0.5f));
rootNode.addLight(al);

        DirectionalLight sun;
        sun = new DirectionalLight();
        sun.setDirection(dir);                                   //this is the same dir used in the shadow renderer.
        sun.setColor(ColorRGBA.White.mult(1.4f));
        rootNode.addLight(sun);

[/java]

Can’t argue that it’s weird.

Is there any way that depth write could get turned off on the objects?

Does it only happen from certain angles?

DepthWrite is definitly on. ive never expiemented with turning it off for any reason. Just for a sanity check I used a scene graph visitor to check all the geoms to make sure DepthWrite is on.

If the issue happens, it happens at all angles. either the game has weird see through shadows or it doesnt when I run it, i’d say it happens 50% of the time either way.

Because it only happens sometimes I feel like it would be an issue related to performing some action outside of the main game loop. Though I don’t really have any kind of outside threads that modifies the game. the whole scene is loaded in an initialize() of an app state, and the code that spawns the plane is in the update() method.

It might be worth trying to create a simple test case that illustrates the issue. On the one hand, it might narrow down what it is about your app that triggers the issue… on the other hand, it makes a good test case for finding a bug in the engine if the problem is there.

I think i might try to put one together today, this is really bugging me.

do you switch the order of the processors at some point?
the shadows processor needs to be before the filter post processor. (trying to rule out the easy things)

3 Likes

Ah! that turned out to be the issue.

I stored my SceneProcessors in a Set so i could quickly add and remove them on the fly (for testing/expirementing). Since sets dont have a defined order when I iterate over them it was randomly picking one or the other to be the “first” processor.

That completely explains why it only happened “sometimes” when restarting the game.

I changed my code to make sure it adds the shadow first., and it stopped happening.

thanks!