Real transparency [code included]

Hey jME developers,



The current implementation of jME does not support nicer translucency. This is something I need, so I thought I would tell you how I do it.



The basic principle is: if you have a translucent object, then you need to prime the z-buffer first, since otherwise you get strange behaviour where two translucent polys overlap. Basically, the z-buffering system does not work with translucent objects. REAL translucency is only achieved by individually sorting each polygon from far to near. A close approximation that works in most circumstances is to draw the object to only the z-buffer first, then draw it normally over the top.



Unfortunately it does require some small changes to the jME code. They are:


  1. either add to the Renderer class an ‘enableColorWrite’ method, or add a BufferState. The LWJGL implementation does something like the following:


            GL11.glDrawBuffer(enabled?GL11.GL_BACK:GL11.GL_NONE);



2. In the RenderQueue, in renderTransparentBucket, do something like the following:


        transparentBucket.sort();
        for (int i = 0; i < transparentBucket.listSize; i++) {
            if (niceTranslucency) {
               renderer.enableColorWrite(false);
               transparentBucket.list[i].draw(renderer);
               renderer.enableColorWrite(true);
               transparentBucket.list[i].draw(renderer);
           else {
               transparentBucket.list[i].draw(renderer);
           }
            transparentBucket.list[i].queueDistance = Float.NEGATIVE_INFINITY;
        }
        transparentBucket.clear();



It looks a lot nicer for situations like where you want to put a translucent atmosphere around a planet, or you have a translucent glass dome under the ocean or whatever else.

If you draw all the meshes to the z-bufer first wouldn’t that make only the topmost one show or is that what you want?

Kind of…



this should be done on a per object basis. I’m not quite familiar enough with how jME works to know how to achieve that, I just assumed that each objet was added to the queue.