Throwing shadows onto another object not working

Hello folks,



I tried to create a simple 3d scene with JME and like it so far. But I have failed to cast dynamic shadows: My scene creates four boxes which rotate, two lights in front of them and one big box behind the rotating cubes. I tried to cast the shadows from the rotation cubes onto the bix "plane" in the background but I have not yet succeeded. I also tried to search the forums and tried various ways as described in the forums, but still no success. So: I made sure I update and initialize everything correctly, and if I test the ShadowPassRenderer with the ShadowTweaker I can change the behaviour of the shadows; but still I do ont have the shadows I want.



Source code:



import com.jme.app.*;
import com.jme.math.*;
import com.jme.light.*;
import com.jme.scene.*;
import com.jme.animation.*;
import com.jme.scene.shape.*;
import com.jme.renderer.*;
import com.jme.renderer.pass.*;

public class JMETest extends BaseSimpleGame
{
   private ShadowedRenderPass pass;
   private BasicPassManager manager;

   public JMETest ()
   {
   }

   public static void main ( String[] args ) throws Exception
   {
      JMETest app = new JMETest();
      app.setDialogBehaviour(SimpleGame.ALWAYS_SHOW_PROPS_DIALOG);
      app.start(); // Start the program      
   }
   
   protected void update ( float i)
   {
      super.update(i);
      rootNode.updateGeometricState(tpf, true);
      manager.updatePasses(tpf);
   }
      
   protected void render ( float i )
   {
      super.render(i);
      
      display.getRenderer().clearBuffers();
      display.getRenderer().draw(rootNode);
      display.getRenderer().draw(fpsNode);
   
      manager.renderPasses(display.getRenderer());
   }

   protected void simpleInitGame()
   {
        /*
       * Box 1
       */
      
      Node node = new Node();
      node.setRenderState(lightState);
      node.setLocalTranslation(new Vector3f(0, 0, 0));
      rootNode.attachChild(node);
      
      Box b = new Box("box1", new Vector3f(0, 0, 0), 2, 2, 2);
       node.attachChild(b);
      
      SpatialTransformer st = new SpatialTransformer(2);
      st.setObject(node, 0, -1);
      st.setObject(b, 1, 0);
      
      Vector3f rot = new Vector3f(0, 0, 1);
      Quaternion x0 = new Quaternion();
      x0.fromAngleAxis(0, rot);
       st.setRotation(1, 0, x0);
      
       Quaternion x180 = new Quaternion();
      x180.fromAngleAxis(FastMath.DEG_TO_RAD*180, rot);
      st.setRotation(1, 1, x180);
      
      Quaternion x360 = new Quaternion();
      x360.fromAngleAxis(FastMath.DEG_TO_RAD*360, rot);
       st.setRotation(1, 2, x360);
      
       st.setRepeatType(Controller.RT_WRAP);
       st.setSpeed(1);
       st.interpolateMissing();
       rootNode.addController(st);
      
      /*
       * Box 2
       */
      
      node = new Node();
      node.setRenderState(lightState);
      node.setLocalTranslation(new Vector3f(0, 4, 0));
      rootNode.attachChild(node);
      
      b = new Box("box2", new Vector3f(0, 0, 0), 2, 2, 2);
      node.attachChild(b);
      
      st = new SpatialTransformer(2);
      st.setObject(node, 0, -1);
      st.setObject(b, 1, 0);
      
      rot = new Vector3f(-2, 0, 0);
      x0 = new Quaternion();
      x0.fromAngleAxis(0, rot);
       st.setRotation(1, 0, x0);
      
      x180 = new Quaternion();
      x180.fromAngleAxis(FastMath.DEG_TO_RAD*180, rot);
      st.setRotation(1, 1, x180);
      
      x360 = new Quaternion();
      x360.fromAngleAxis(FastMath.DEG_TO_RAD*360, rot);
       st.setRotation(1, 2, x360);
      
       st.setRepeatType(Controller.RT_WRAP);
       st.setSpeed(1);
       st.interpolateMissing();
       node.addController(st);
      
       /*
        * Box 3
        */     
      
      node = new Node();
      node.setRenderState(lightState);
      node.setLocalTranslation(new Vector3f(4, 2, 0));
      rootNode.attachChild(node);
   
      b = new Box("box3", new Vector3f(0, 0, 0), 2, 2, 2);
      node.attachChild(b);
      
      st = new SpatialTransformer(2);
      st.setObject(node, 0, -1);
      st.setObject(b, 1, 0);
      
      rot = new Vector3f(-2, 3, 0);
      x0 = new Quaternion();
      x0.fromAngleAxis(0, rot);
       st.setRotation(1, 0, x0);
      
      x180 = new Quaternion();
      x180.fromAngleAxis(FastMath.DEG_TO_RAD*180, rot);
      st.setRotation(1, 1, x180);
      
      x360 = new Quaternion();
      x360.fromAngleAxis(FastMath.DEG_TO_RAD*360, rot);
       st.setRotation(1, 2, x360);
      
       st.setRepeatType(Controller.RT_WRAP);
       st.setSpeed(1);
       st.interpolateMissing();
       node.addController(st);
      
       /*
        * Box 4
        */
      
      node = new Node();
      node.setRenderState(lightState);
      node.setLocalTranslation(new Vector3f(-4, 2, 0));
      rootNode.attachChild(node);
      
      b = new Box("box4", new Vector3f(0, 0, 0), 2, 2, 2);
      node.attachChild(b);
      
      st = new SpatialTransformer(2);
      st.setObject(node, 0, -1);
      st.setObject(b, 1, 0);
      
      rot = new Vector3f(0, -0.2f, 0);
      x0 = new Quaternion();
      x0.fromAngleAxis(0, rot);
       st.setRotation(1, 0, x0);
      
      x180 = new Quaternion();
      x180.fromAngleAxis(FastMath.DEG_TO_RAD*180, rot);
      st.setRotation(1, 1, x180);
      
      x360 = new Quaternion();
      x360.fromAngleAxis(FastMath.DEG_TO_RAD*360, rot);
       st.setRotation(1, 2, x360);
      
       st.setRepeatType(Controller.RT_WRAP);
       st.setSpeed(1);
       st.interpolateMissing();
       node.addController(st);
            
       node = new Node("plane");
       node.setRenderState(lightState);
       node.setLocalTranslation(new Vector3f(-20, -15, -6));
       rootNode.attachChild(node);
      
       b = new Box("myplane", new Vector3f(0, 0, 0), new Vector3f(40, 40, 2));
       node.attachChild(b);
    
      cam.setLocation(new Vector3f(0, 20, 20));
      cam.lookAt(new Vector3f(0, 0, -10), new Vector3f(0, 1, 0));
      cam.update();
      
      lightState.detachAll();
      
      // Create some lights
      PointLight pl = new PointLight();
      
      pl.setShadowCaster(true);
      pl.setLocation(new Vector3f(10, 5, 3));
      //pl.setDirection(new Vector3f(0, 0, -1));
      pl.setAmbient(new ColorRGBA(1, 1, 1, 1));
      pl.setDiffuse(new ColorRGBA(1, 1, 1, 1));
      pl.setEnabled(true);
      
      //lightState.setEnabled(true);
      lightState.attach(pl);
      
      pl = new PointLight();
      
      pl.setShadowCaster(true);
      pl.setLocation(new Vector3f(8, -10, 0));
      //pl.setDirection(new Vector3f(0, 0, -1));
      pl.setAmbient(new ColorRGBA(0, 1, 1, 0));
      pl.setDiffuse(new ColorRGBA(0, 1, 1, 0));
      pl.setEnabled(true);
      
      lightState.attach(pl);
      rootNode.setRenderState(lightState);
      
      pass = new ShadowedRenderPass();
      
      pass.add(rootNode);
      pass.setShadowColor(ColorRGBA.black);
      pass.setRenderShadows(true);
      pass.setEnabled(true);
      pass.setLightingMethod(ShadowedRenderPass.ADDITIVE);
      pass.addOccluder(rootNode);
               
      RenderPass rpass = new RenderPass();
      rpass.setEnabled(true);
      rpass.add(rootNode);
      
      manager = new BasicPassManager();
      manager.add(rpass);
      manager.add(pass);
   }
}



Screenshot:



And how the shadows should look like:

First, you are drawing the scene twice, so remove the line:


display.getRenderer().draw(rootNode);  // (remove this line)



Next, your code will work fine, you just need to ensure that the rendering context has a stencil buffer attached.  In BaseSimpleGame classes, you can do so by setting the stencilBits field.  Make sure you do it in the constructor so that it is set prior to display creation.  In other words, make your constructor look something like:

    public JMETest ()
    {
        stencilBits = 4;
    }



Finally, you might consider only adding the boxes as occluders instead of the entire rootNode as that will be cheaper and from where your lights are, the plane does not cast any meaningful shadows anyhow.

Thank you for your help; highly appreciated! It was indeed the stencil buffers and the lights were misplaced too.







I also tried your performance tweak and it did not change much. I think because the proportion of non-shadow casting objects and shadow-casting objects is rather small in my scene. Though I removed the line:


display.getRenderer().clearBuffers();



Which increased the FPS and did not make the FPS-Label disappear behind my plane-box.

Again: Thank you!
display.getRenderer().clearBuffers()
  :-o

That has the effect of accumulating the contents of the graphics buffer, which will work but only if it's a completely static scene with no camera movement.

well the topic is a bit old, but i've the same problem. but the setinc of stencilbits wasnt the solution. May somone have another idea?

Start a new thread and post some code. That's the easiest way for us to give you a hand.