ORTHO Quad overlaying 3D elements

I have a background Quad node with the render mode set to QUEUE_ORTHO, which fills the screen displaying a star field from a generated Image object (painted using Buffered Image), however any 3D objects or other elements attached to the scene are not displayed.  Having experimented with depth (z) values and removing elements I can tell that the Quad is completely covering the scene.



If I remove QUEUE_ORTHO the problem is resolved, however the Quad no longer runs from corner to corner of the display window, so this isnt ideal.

What I hope to achieve is a Quad/or any 2D object that can display a texture/image from one corner to the other of the display window that sits behind all other scene items.


package influx.client.game;

import com.jme.image.Texture;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import influx.client.game.display.Background;
import influx.client.game.input.InputController;
import influx.client.ship.Ship;

/**
 * <p>Title: Influx</p>
 *
 * <p>Description: 3D Space Game</p>
 *
 * <p>Copyright: Copyright (c) 2006</p>
 *
 * @author Adam Pooley
 * @version 1.0
 */
public class Game extends Node {

   private DisplaySystem display;
   private Background background;
   private TextureState backgroundState;
   private TextureState starFieldState;
   private Quad backgroundQuad;
   private Quad starFieldQuad;
   private int location;
   private Ship player;
   private CameraController cameraController;
   private InputController inputController;

   /**
    * Class constructor.
    *
    * @param name The name of this scene node.
    * @param display The display system of the game window.
    */
   public Game(String name,
            DisplaySystem display) {

      super(name);

      this.display = display;

      initGame();
   }

   /**
    * Initialises all game elements.
    */
   public void initGame() {

      Texture texture;

      // initialise background scene
      background = new Background(display);

      texture = new Texture();
      texture.setApply(Texture.AM_MODULATE);
      texture.setBlendColor(new ColorRGBA(1, 1, 1, 1));
      texture.setFilter(Texture.MM_LINEAR);
      texture.setImage(background);
      texture.setMipmapState(Texture.FM_LINEAR);

      backgroundState = display.getRenderer().createTextureState();
      backgroundState.setTexture(texture);
      backgroundState.setEnabled(true);

      backgroundQuad = new Quad("Background quad", background.getWidth(), background.getHeight());
      backgroundQuad.setRenderState(backgroundState);
      backgroundQuad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      backgroundQuad.setLocalTranslation(new Vector3f(background.getWidth()/2, background.getHeight()/2, 0));
      backgroundQuad.setLightCombineMode(LightState.OFF);
      backgroundQuad.getLocalRotation().set(0, 0, 0, 1);
      backgroundQuad.getLocalScale().set(1, 1, 1);
        backgroundQuad.updateRenderState();

      // initialise player
      player = new Ship("Player node");

      // attach all scene elements
      attachChild(backgroundQuad);
      attachChild(player);

      // initialise controllers
      cameraController = new CameraController(display.getRenderer().getCamera(), player);
      inputController = new InputController(player);

      updateWorldBound();
   }

   /**
    * Updates all elements of the scene.
    *
    * @param time The time elapsed since the last update.
    * @param location The location magnitude of the camera.
    */
   public void update(   float time,
                  int location) {

      boolean backgroundUpdated;

      backgroundUpdated = background.update();

      // refresh images only when camera has moved.
      if(location != this.location) {
         this.location = location;

         background.refreshImage();
         backgroundUpdated = true;
      }

      // force reapplication of image.
      if(backgroundUpdated) {
         backgroundState.deleteAll();
      }

      inputController.update(time);
      player.update(time);
   }
}

Maybe you could render your quad before any other geometry, disabling the z-buffer so that the rest of the geometry is always rendered on top of your starfield.

I had applied a Zbuffer to the root Node scene, but I hadn't applied one to the Quad.

add a new zbufferstate to your ortho quad with a disabled WRITE.

Everything in the ORTHO queue gets rendered last. So first your ship is rendered and then the background.



You can solve this by using renderpasses.

Cheers Tobias.



I had found a thread detailing a similar problem which was resolved by render passes.



Renanse, also tried that briefly but with no luck - although I will give it another go.



Is there any advantage of using Zbuffering over render passes? Or vice versa?

Sorry, I had skybox on the brain.  Ortho is indeed drawn last, so if you're using that queue and a single pass, you don't need to worry about zbuffer writing so much.



I would switch to multiple passes as suggested.  Isolate your background ortho items in a single pass that is early or first in your pass manager.  I would still suggest adding a non-writing / non-testing zbuffer state to those items though.

Thanks lads, it worked a treat. 



I also stumbled upon an example in the JME wiki section which used a pass manager to render multiple textures to geometry. Is there any advantage of using a render pass manager over my simple method, detailed below? (The render pass section of the user guide which I guess would contain these methods was never completed).



display.getRenderer().clearBuffers();

// render backdrop
display.getRenderer().draw(backdrop);
display.getRenderer().renderQueue();

// render 3D plain
display.getRenderer().draw(plain);
display.getRenderer().renderQueue();

display.getRenderer().displayBackBuffer();



Cheers