Problem with ZBuffer and SkyBox

Hey all,



I've got a little problem: my skybox (size 10) is not painted behind the other scene elements but is cutting/hiding them like a normal object. I've taken almost all jme related code from the FlagRush example (except I use a GameState instead of a Game). The Skybox has its own ZBuffer settings in Skybox.initialize(). What did I wrong?



import java.util.HashMap;
import com.jme.input.ChaseCamera;
import com.jme.input.thirdperson.ThirdPersonMouseLook;
import com.jme.light.PointLight;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.Skybox;
import com.jme.scene.shape.Box;
import com.jme.scene.state.LightState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jmex.game.StandardGame;
import com.jmex.game.state.BasicGameState;
import com.jmex.game.state.GameStateManager;

public class SkyboxTestGameState extends BasicGameState
{
   private Node dummy;
   private ChaseCamera chaseCamera;
   private Skybox skybox;
   
   public SkyboxTestGameState(String name)
   {
      super(name);
      dummy = new Node( "dummy" );
   }

   public void initSkyBox()
   {
      float size = 10f;
      
        skybox = new Skybox("skybox", size, size, size);
        getRootNode().attachChild(skybox);          
        getRootNode().updateRenderState();
       
        skybox.setLocalTranslation(DisplaySystem.getDisplaySystem().getRenderer().getCamera().getLocation() );
   }
   
   public void initLight()
   {
      ZBufferState buf = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
      buf.setEnabled(true);
      buf.setFunction(ZBufferState.CF_LEQUAL);
      getRootNode().setRenderState(buf);

      PointLight light = new PointLight();
      light.setDiffuse(new ColorRGBA(1.00f, 1.00f, 1.00f, 1.00f));
      light.setAmbient(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));
      light.setLocation(new Vector3f(10000, 10000, 10000));
      light.setEnabled(true);

      LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
      lightState.setEnabled(true);
      lightState.attach(light);
      getRootNode().setRenderState(lightState);
      getRootNode().updateRenderState();
   }
   
   public void init()
   {
      getRootNode().attachChild( dummy );

      int i = -40;
      
      while( i <= 40 ) {
         if( i != 0 ) {
            getRootNode().attachChild( new Box( "Box", new Vector3f( i, 0f, 0f ), new Vector3f( i+1, 1f, 1f ) ) );         
            getRootNode().attachChild( new Box( "Box", new Vector3f( 0f, i, 0f ), new Vector3f( 1f, i+1, 1f ) ) );         
            getRootNode().attachChild( new Box( "Box", new Vector3f( 0f, 0f, i ), new Vector3f( 1f, 1f, i+1 ) ) );         
         }
         i += 2;
      }
      
      HashMap<String, Object> props = new HashMap<String, Object>();

        props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "20");
        props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "3");
        props.put(ThirdPersonMouseLook.PROP_MAXASCENT, 80 * FastMath.DEG_TO_RAD);
        props.put(ThirdPersonMouseLook.PROP_MINASCENT, -80 * FastMath.DEG_TO_RAD);
        props.put(ThirdPersonMouseLook.PROP_MOUSEBUTTON_FOR_LOOKING, 1 );
        props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(5, 0, 30 * FastMath.DEG_TO_RAD));
        props.put(ChaseCamera.PROP_DAMPINGK, "6");
        props.put(ChaseCamera.PROP_SPRINGK, "9");
       
      chaseCamera = new ChaseCamera(DisplaySystem.getDisplaySystem().getRenderer().getCamera(), dummy, props );
      
       ZBufferState buf = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
       buf.setEnabled(true);
       buf.setFunction(ZBufferState.CF_LEQUAL);
       getRootNode().setRenderState(buf);      
   }

   @Override
   public void update(float tpf)
   {
      super.update(tpf);
      
      if( chaseCamera != null ) {
         chaseCamera.update( tpf );
      }
      getRootNode().updateGeometricState( tpf, true );
   }
   
   public static void main( String[] args )
   {
      StandardGame app = new StandardGame( "StandardGame" );
        app.start();
       
        SkyboxTestGameState gameState = new SkyboxTestGameState( "skyboxtest" );
        gameState.init();
        gameState.initLight();
        gameState.initSkyBox();
        GameStateManager.getInstance().attachChild( gameState );
        gameState.setActive( true );
   }
}

Perhaps I'm missing it, but it looks like you aren't setting a render queue mode for root node, which would mean that it would immediately render.  Try grabbing the root node and setting it to the opaque queue.

Indeed, a


getRootNode().setRenderQueueMode( Renderer.QUEUE_OPAQUE );



solves the problem, thanks!

Update: I found http://www.jmonkeyengine.com/wiki/doku.php?id=renderqueue and tried to understand it. One question: The text says:


Draw the opaque objects first (front to back)
front/back means the distance from the camera, front being close, back being far



but isnt this the wrong way to do? I would first paint the far away objects and then the near ones on top of them... :?

You don't need to do that, depth testing automatically discards pixels which are behind other objects. You render front to back so that the least amount of colorbuffer changes are made (more pixels fail the depth test).

For the benefit of anyone who encounters this issue after me…



I was having the exact same problem as the original poster:    SkyBox blocking out my other objects (instead of being drawn "behind" them) in a game based on StandardGame.  I had also followed the FlagRush tutorials.



In my case, it didn't go away when I added the call to…


getRootNode().setRenderQueueMode( Renderer.QUEUE_OPAQUE );



I needed to add the GameState that renders the SkyBox to my world before other GameStates;  that fixed it for me.