Drawing a spatial after TRANSPARENT, but before ORTHO

Well, this is a very special case… I want to have a transparent geometry with several opaque geometries within… But one of them shall not be "colored" by the transparent surrounding geometry…

Any hints on how to do this??

Thanks in advance!

You could do something like this:


renderer.draw( opaqueAndTransparentNodes );
renderer.renderQueue();
renderer.draw( opaqueNodesInFront );


This may require writing an special Game class that does not extend SimpleGame but BaseGame.

You can also use the Pass system and place the items that should not be colored by the transparency in a second render pass.

Puh!

Thanks for the hints! I have tried both and learned a lot about JME today…Aparently, not enough…  :D  Updated from the CVS too, but still no luck on my topic…



I might as well just paste my testcase here… By the way, I must use the JMECanvas in my project. Does that make any difference?

Also, I do not understand why the box gets to the screen, when it is marked with QUEUE_SKIP…



Thanks for your time!






public class TestCanvasImpl extends JMECanvasImplementor {
    protected Node rootNode;
    protected Timer timer;
    protected float tpf;
    protected Camera cam;
    protected int width, height;
    protected BasicPassManager pManager;
    protected DisplaySystem display;
   
    private Quaternion rotQuat;
    private float angle = 0;
    private Vector3f axis;
    private Box box;
    private Box box2;
   
    private LightState ls;
   
    public TestCanvasImpl(int width, int height) {
        this.width = width;
        this.height = height;
    }
   
    public void doSetup() {
        pManager = new BasicPassManager();
        display = DisplaySystem.getDisplaySystem();
        renderer = new LWJGLRenderer(width, height);
        renderer.setHeadless(true);
        display.setRenderer(renderer);
        DisplaySystem.updateStates(renderer);
        PointLight light = new PointLight();
        light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
        light.setLocation(new Vector3f(100, 100, 100));
        light.setEnabled(true);
        ls = renderer.createLightState();
        ls.setEnabled(true);
        ls.attach(light);
        cam = renderer.createCamera(width, height);
        cam.setFrustumPerspective(45.0f, (float) width / (float) height, 1,
                1000);
        Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f);
        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
        Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);
        cam.setFrame(loc, left, up, dir);
        cam.update();
        renderer.setCamera(cam);
        renderer.setBackgroundColor(ColorRGBA.black);
        timer = Timer.getTimer("lwjgl");
        rootNode = new Node("rootNode");
        rootNode.setRenderState(ls);
        ZBufferState buf = renderer.createZBufferState();
        buf.setEnabled(true);
        buf.setFunction(ZBufferState.CF_LEQUAL);
        rootNode.setRenderState(buf);
        simpleSetup();
        rootNode.updateGeometricState(0.0f, true);
        rootNode.updateRenderState();
        setup = true;
    }
   
    public void doUpdate() {
        timer.update();
        /** Update tpf to time per frame according to the Timer. */
        tpf = timer.getTimePerFrame();
       
        simpleUpdate();
        rootNode.updateGeometricState(tpf, true);
        pManager.updatePasses(tpf);
    }
   
    public void doRender() {
        renderer.clearBuffers();
        renderer.draw(rootNode);
        //renderer.renderQueue();
        pManager.renderPasses(renderer);
        //renderer.draw(box2);
        renderer.displayBackBuffer();
    }
   
    public void simpleSetup() {
        rotQuat = new Quaternion();
        axis = new Vector3f(1, 1, 0.5f);
        axis.normalizeLocal();
        Vector3f max = new Vector3f(5, 5, 5);
        Vector3f min = new Vector3f(-5, -5, -5);
        box = new Box("Box", min, max);
        box.setModelBound(new BoundingBox());
        box.updateModelBound();
        box.setLocalTranslation(new Vector3f(0, 0, -10));
        rootNode.attachChild(box);
       
        box2 = new Box("Box", min, max);
        box2.setModelBound(new BoundingBox());
        box2.updateModelBound();
        box2.setLocalTranslation(new Vector3f(0, 0, -8));
        box2.setLocalScale(0.3f);
        //box2.setRenderState(ls);
        box2.updateRenderState();
        //box2.setCullMode(box2.CULL_NEVER);
        box.setRenderQueueMode(DisplaySystem.getDisplaySystem().getRenderer().QUEUE_SKIP);
        rootNode.attachChild(box2);
        box2.setRandomColors();
        TextureState ts = renderer.createTextureState();
        ts.setEnabled(true);
        ts.setTexture(TextureManager.loadTexture(TestTwoPass.class
                .getClassLoader().getResource(
                "jmetest/data/images/Monkey.jpg"),
                Texture.MM_LINEAR, Texture.FM_LINEAR));
        box2.setRenderState(ts);

        MaterialState ms = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();
       ms.setAmbient(new ColorRGBA(0.4f,0.0f,0f,1f));
       ms.setDiffuse(new ColorRGBA(0.8f,0.0f,0,0.7f));
       ms.setShininess(10);
       ms.setEnabled(true);
       box.setRenderState(ms);
            
       RenderPass rp2 = new RenderPass();
       rp2.add(box2);
       rp2.setEnabled(true);
       pManager.add(rp2);
      
       AlphaState as1 = renderer.createAlphaState();
       as1.setEnabled(true);
       as1.setBlendEnabled(true);
       as1.setTestEnabled(false);
       as1.setSrcFunction(AlphaState.SB_SRC_ALPHA);
       as1.setDstFunction(AlphaState.DB_ONE);
       as1.setTestFunction(AlphaState.TF_ALWAYS);
       box.setRenderQueueMode(DisplaySystem.getDisplaySystem().getRenderer().QUEUE_TRANSPARENT);
       box.setRenderState(as1);
      
       box.updateRenderState();
       box2.updateRenderState();
     
       rotQuat = new Quaternion();
       axis = new Vector3f(0, 1, 1f);
    }
    public void simpleUpdate() {
        // Code for rotating the box... no surprises here.
        if (tpf < 1) {
            angle = angle + (tpf * 25);
            if (angle > 360) {
                angle = 0;
            }
        }
        rotQuat.fromAngleNormalAxis(angle * FastMath.DEG_TO_RAD, axis);
        box.setLocalRotation(rotQuat);
        box2.setLocalRotation(rotQuat.inverse());
    }
}


QUEUE_SKIP means it skips the renderqueue sorting stage, so it draws immediately.

ok! Thanks! I am looking at the source now, to get a grasp of the RenderPass, and the difference in SimpleCanvasImpl and BaseGame… No matter how I set up the example above, I can not get the renderer to paint the inner box AFTER the outer (and not colored by the outer).



Objects placed in the renderqueue are not drawn until

renderer.renderQueue();

is called. So make sure that's called after drawing the "red" box, and before drawing the "monkey" box.



However, since your "monkey" box is behind the front of your "red" box, you should make the "monkey" box has the right ZBufferState.

It works! Thanks…

But I had to remove the monkey box from the rootNode… My explanation is: The 2. monkey got tested in the Z-buffer against the 1. monkey after the RenderQueue.  So none of the test functions gave the correct result…?

I should prefer to have it attatched to the rootNode, but be able to skip it on the RenderQueue…

This is probably a typical newbee question… so thanks again for the hints!!

Rootnode is just there for to make it a bit easier to play around with SimpleGame. What you are doing is a bit more advanced than that.



The reason it went wrong is because the transparant box is always rendered later than the non transparant objects, -which you want for normal your objects in your scene- and it has a normal ZBufferState -which you want for normal objects in your scene-. What you're asking is we make another "bucket" in the renderqueue, for drawing objects after all the others. But let's suppose you want to to draw some transparent objects in that phase. I suppose we'll have to make another bucket for that eh? :wink: etc.



Just think about it like this, what you're doing now is pretty logical: draw a correct scene with correct states etc. Then you tell the renderer to draw another scene after that… (right now you're using a special ZBufferState to draw on top, you could also choose to clear the entire Z-Buffer). I suppose you have reason for wanting it to be attachted to one "rootNode", but keep it mind that eg. having two Nodes that share the same coordinates isn't very hard. They can also share the same RenderStates.



Still not convinced? :smiley: Take a look at the Pass system… with this you should be able to control the order your objects are rendered in, while keeping them attachted to the same Node.