Shadow

Well, i thing it's a known theme:



What kind of shadow creation is better ?



ShadowMapping or VolumeShadows ?



The next question is: Can jME create shadows itself or am i forced to do that stuff ?



greeting,

Chris

ShadowMapping or VolumeShadows ?

Depends on application, generally static objects use ShadowMapping (or light mapping) while animated use VolumeShadows.

jME can do both (generally)....

Well, i've got question. I use VolumeShadows. When i entered the shadow with my camera, then the shadow is casted in a wrong way. I think the problem is, that the shadow is cast via zPass. Now i want to usw zFail to correct this problem. How can i change this mode ?



Second problem:

i usw jME Physics 2. When i want to create a dynamicNode while the simulation has started i get this exception:



java.lang.NullPointerException

at com.jme.scene.shadow.MeshShadows.createGeometry(Unknown Source)

at com.jme.renderer.pass.ShadowedRenderPass.generateVolumes(Unknown Source)

at com.jme.renderer.pass.ShadowedRenderPass.doRender(Unknown Source)

at com.jme.renderer.pass.Pass.renderPass(Unknown Source)

at com.jme.renderer.pass.BasicPassManager.renderPasses(Unknown Source)

at AppStart.preRender(AppStart.java:53)

at SpecPhysics.render(SpecPhysics.java:178)

at com.jme.app.BaseGame.start(Unknown Source)

at AppStart.main(AppStart.java:183)



At line 53 is this code:



pManager.renderPasses(display.getRenderer());



pManager is BasicPassManager. The whole code comes next:



import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.light.DirectionalLight;
import com.jme.light.PointLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.ShadowedRenderPass;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.StaticPhysicsNode;


public class AppStart extends SpecPhysics {
   StaticPhysicsNode staticNode;
   
   private final ShadowedRenderPass sPass = new ShadowedRenderPass();
   private final BasicPassManager pManager = new BasicPassManager();
   
    AppStart() {
       stencilBits = 4;
    }   
   
   protected void preRender() {
      super.preRender();
      
      pManager.renderPasses(display.getRenderer());
   }
   
   protected void simpleUpdate() {
      super.simpleUpdate();
      
      fpsNode.updateGeometricState(tpf, true);
      pManager.updatePasses(tpf);
   }
   
   
   
    protected void simpleInitGame() {
       display.getRenderer().setBackgroundColor(ColorRGBA.orange.clone());
       
        //Kugel erstellen
        InputAction buttonAction = new InputAction() {
            public void performAction( InputActionEvent evt ) {
               if(evt.getTriggerPressed()) {
                  DynamicPhysicsNode dynamicNode = getPhysicsSpace().createDynamicNode();
                  rootNode.attachChild( dynamicNode );   
                  Box sphere = new Box("lol", new Vector3f(), 2, 2 ,2);
                  dynamicNode.attachChild(sphere);                 
                  dynamicNode.generatePhysicsGeometry();
                  dynamicNode.getLocalTranslation().set( cam.getLocation());
                  dynamicNode.setMass(1000);
                  dynamicNode.addForce(cam.getDirection().mult(10000000));
                 
                  sPass.addOccluder(dynamicNode);
               }
            }
        };
       

        //Input
        KeyBindingManager keyboard = KeyBindingManager.getKeyBindingManager();
        keyboard.set("myCommand", KeyInput.KEY_SPACE);
        input.addAction( buttonAction, InputHandler.DEVICE_MOUSE, 0 /*first/left button*/, InputHandler.AXIS_NONE, false );

       
       
        //Kasten rendern
        staticNode = getPhysicsSpace().createStaticNode();
        rootNode.attachChild( staticNode );
        Box box = new Box( "floor", new Vector3f(), 150, 10f, 150 );
        staticNode.attachChild(box);
       
        box = new Box( "floor", new Vector3f(), 50, 5f, 150 );
        staticNode.attachChild(box);
        box.getLocalTranslation().set(0, -155);
        box.getLocalTranslation().set(1, 45);
        box.getLocalRotation().fromAngleNormalAxis((float)Math.PI/2.0f, new Vector3f(0,0,-1));
       
       
        box = new Box( "floor", new Vector3f(), 50, 5f, 150 );
        staticNode.attachChild(box);
        box.getLocalTranslation().set(0, 155);
        box.getLocalTranslation().set(1, 45);
        box.getLocalRotation().fromAngleNormalAxis((float)Math.PI/2.0f, new Vector3f(0,0,-1));       
       
       
        box = new Box( "floor", new Vector3f(), 150, 5f, 50 );
        staticNode.attachChild(box);
        box.getLocalTranslation().set(2, -155);
        box.getLocalTranslation().set(1, 45);
        box.getLocalRotation().fromAngleNormalAxis((float)Math.PI/2.0f, new Vector3f(1,0,0));
       
        box = new Box( "floor", new Vector3f(), 150, 5f, 50 );
        staticNode.attachChild(box);
        box.getLocalTranslation().set(2, 155);
        box.getLocalTranslation().set(1, 45);
        box.getLocalRotation().fromAngleNormalAxis((float)Math.PI/2.0f, new Vector3f(1,0,0));   
        staticNode.generatePhysicsGeometry();

        staticNode.getLocalRotation().fromAngleAxis(20, new Vector3f(1,1,0));
       
        cam.getLocation().y = 20;

       
        //Hundert Kugeln
        for(int i = 0; i < 100; i++) {
           DynamicPhysicsNode dynamicNode = getPhysicsSpace().createDynamicNode();
           rootNode.attachChild( dynamicNode );
   
           Sphere sphere = new Sphere("lol", new Vector3f(), 10, 10 ,2);
           dynamicNode.attachChild(sphere);
           dynamicNode.getLocalTranslation().set(0, 12 + i*4 , 0 );
           dynamicNode.generatePhysicsGeometry();
          
           sPass.addOccluder(dynamicNode);
        }
       
       // The light that cast shadows.
       DirectionalLight dr = new DirectionalLight();
       dr.setEnabled(true);
       dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
       dr.setAmbient(new ColorRGBA(.6f, .6f, .5f, .5f));
       dr.setDirection(new Vector3f(0.5f, -0.8f, 0.5f).normalizeLocal());
       dr.setShadowCaster(true);
    
       // Another light so there is no full darkness.
       PointLight pl = new PointLight();
       pl.setEnabled(true);
       pl.setDiffuse(new ColorRGBA(.2f, .2f, .23f, 1.0f));
       pl.setAmbient(new ColorRGBA(.25f, .25f, .28f, .25f));
       pl.setLocation(new Vector3f(20, 20, 20));
    
       lightState.detachAll();
       lightState.attach(dr);
       lightState.attach(pl);
       lightState.setGlobalAmbient(new ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f));
       
       
       
       
       rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
       
       sPass.add(rootNode);
       sPass.setRenderShadows(true);
       sPass.setLightingMethod( ShadowedRenderPass.ADDITIVE );
       pManager.add(sPass);
    
       //RenderPass rPass = new RenderPass();
       //rPass.add(staticNode);
       //pManager.add(rPass);
    }


    public static void main( String[] args ) {
        Logger.getLogger( "" ).setLevel( Level.WARNING ); // to see the important stuff
        new AppStart().start();
    }
}




The SpecPhysics class is a light modified version of SimplePhysicsGame. The thing i've changed is, that
i don't call r.draw( rootNode ); in the render function.

Sounds like a “Carmacks reverse” scenario.

I dont know if there have been some posts on the subject here so search for the above - if you find nothing here google it, its a well known issue.



Did a search here myself, and found this one for starters -

http://www.jmonkeyengine.com/jmeforum/index.php?topic=4307.0

Ok, another question:



I create 100 Spheres… This takes a lot of time to initialize… I think the time is used to calc the neighboured edges… But this will be very stupid if i use 100 equal spheres… How can i change this behaviour ?



Greetings,



Chris

Carmacks reverse is not implemented in jME.

Depends on application, generally static objects use ShadowMapping (or light mapping) while animated use VolumeShadows.

Not really correct.. Light mapping is not shadow mapping, light mapping preprocesses the scene and "bakes" lighting information onto the scene itself, because of this it only works for static geometry. Shadow mapping is a completely dynamic effect, the shadow map is rendered in GPU every frame and then depth values in the scene are compared to depth values in the shadow map in light space. Volume shadows is also a dynamic effect but mostly uses the CPU (to update the volumes) and less so the GPU (to apply shadows where the volume intersects the scene).

Now i want to usw zFail to correct this problem. How can i change this mode ?

jME does not support zFail.

I create 100 Spheres... This takes a lot of time to initialize... I think the time is used to calc the neighboured edges... But this will be very stupid if i use 100 equal spheres... How can i change this behaviour ?

Try lockShadows() on the spheres. Also you might want to reconsider using spheres as they can be quite slow if I understand what you're trying to do.. Try a forum search.

I play a little bit with jME Physics 2… Now my target was to add shadows to my scene. I create 100 physics spheres and i want they to cast their shadow via VolumeShadows. The time the application need to initialize depends on the number of spheres. For VolumeShadow the program has to calc the neighboured edges, with these information the program can easily calc the silhouette of a sphere to cast the shadow. But when i use 100 equal spheres with the same radius and the same number of triangles… So there is no need to calc the same for hundred spheres. That is my problem…



Chris