Unshaded geometry gets shadowed even with ShadowMode.Off

Since I switched from PSSM to DirectionalLight shadows, I’ve noticed an odd quirk where some geometries receive shadows even though their shadow mode is Off or Cast. I assumed I was doing something wrong, but now I’m not so sure.

Below is a simple test app in which a box casts a shadow onto yellow ground. However, the same box appears to cast a shadow onto the gray sphere, for which shadows are turned off. My expectation is that the sphere (which happens to have an unshaded material) should have uniform color all around. Can anyone explain why it doesn’t?

[java]
package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.EdgeFilteringMode;
import com.jme3.texture.Texture;
/**

  • A simple JME3 app to demonstrate shadow rendering issues.
    */
    public class Main
    extends SimpleApplication{

    static final int shadowMapSize = 1024;
    static final int nbSplits = 3;
    static final float lambda = 0.55f;
    static final float intensity = 0.6f;

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

    @Override
    public void simpleInitApp() {
    Vector3f startLocation = new Vector3f(-5f, 6f, -2f);
    cam.setLocation(startLocation);
    Quaternion startRotation = new Quaternion(0.2f, 0.7f, -0.3f, 0.6f);
    cam.setRotation(startRotation);
    flyCam.setMoveSpeed(10f);

     viewPort.setBackgroundColor(ColorRGBA.Gray);
    
     DirectionalLight mainLight = new DirectionalLight();
     mainLight.setColor(ColorRGBA.White);
     Vector3f lightDirection = new Vector3f(2f, -9f, -2f).normalize();
     mainLight.setDirection(lightDirection);
     mainLight.setName("main");
     rootNode.addLight(mainLight);
     /*
      * two lit geometries: yellow ground and logo box
      */
     Material yellow = new Material(assetManager,
             "Common/MatDefs/Light/Lighting.j3md");
     yellow.setBoolean("UseMaterialColors", true);
     yellow.setColor("Diffuse", ColorRGBA.Yellow);
     Box groundMesh = new Box(8f, 0.2f, 8f);
     Geometry ground = new Geometry("ground", groundMesh);
     ground.setMaterial(yellow);
     ground.setLocalTranslation(0f, -0.2f, 0f);
     ground.setShadowMode(RenderQueue.ShadowMode.Receive);
     rootNode.attachChild(ground);
    
     Material logoMaterial = new Material(assetManager,
             "Common/MatDefs/Light/Lighting.j3md");
     Texture logo = assetManager.loadTexture("Interface/Logo/Monkey.png");
     logoMaterial.setTexture("DiffuseMap", logo);
     Box boxMesh = new Box(0.3f, 0.3f, 0.3f);
     Geometry logoBox = new Geometry("box", boxMesh);
     logoBox.setLocalTranslation(0f, 2f, -3f);
     logoBox.setMaterial(logoMaterial);
     logoBox.setShadowMode(RenderQueue.ShadowMode.Cast);
     rootNode.attachChild(logoBox);
     /*
      * one unshaded geometry: gray ball
      */
     Material gray = new Material(assetManager, 
             "Common/MatDefs/Misc/Unshaded.j3md");
     gray.setColor("Color", ColorRGBA.Gray);
     int zSamples = 32;
     int radialSamples = 32;
     float radius = 0.3f;
     Sphere sphereMesh = new Sphere(zSamples, radialSamples, radius);
     Geometry sphere = new Geometry("sphere", sphereMesh);
     sphere.setLocalTranslation(0f, 1f, -3f);
     sphere.setMaterial(gray);
     sphere.setShadowMode(RenderQueue.ShadowMode.Off);
     rootNode.attachChild(sphere);
     /*
      * Add shadow filter and preprocessor.
      */
     DirectionalLightShadowFilter filter =
             new DirectionalLightShadowFilter(assetManager, shadowMapSize,
             nbSplits);
     filter.setEdgeFilteringMode(EdgeFilteringMode.Nearest);
     filter.setEnabled(true);
     filter.setLambda(lambda);
     filter.setLight(mainLight);
     filter.setShadowIntensity(intensity);
    
     FilterPostProcessor postProcessor = 
             new FilterPostProcessor(assetManager);
     postProcessor.addFilter(filter);
     viewPort.addProcessor(postProcessor);
    

    }
    }
    [/java]

I can’t remember if you were on that other thread or not… but in that thread it was pretty clear that the post-process filter version of shadows doesn’t pay attention to the receive shadows stuff since it applies to screen space.

To which thread are you referring, @pspeed?

http://hub.jmonkeyengine.org/forum/topic/directionallight-shadows/#post-247343

1 Like

I was definitely on that thread, but I overlooked the limitation of shadow mode with ShadowFilter. I’ll add a mention of that limitation to the wiki and try again with ShadowRenderer.

2 Likes

DirectionalLightShadowRenderer works as expected in this case.