Concentric translucent domes

SkyControl uses concentric translucent domes with the camera at the center. For reasons I don’t understand, the inner dome (with clouds) fades or disappears at certain camera positions. I created a test app using quads which failed to reproduce the issue. When I replaced the quads with com.jme3.scene.shape.Dome meshes, however, I reproduced the issue.

Here’s the test app:
[java]
package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Dome;

public class Main extends SimpleApplication {

Node node = new Node("skyNode");
String assetPath = "Common/MatDefs/Misc/Unshaded.j3md";

public static void main(String[] args) {
    Main app = new Main();
    app.start();
}

@Override
public void simpleInitApp() {
    cam.setLocation(new Vector3f(-44.79285f, 225.27647f, -953.6865f));
    flyCam.setMoveSpeed(10f);

    rootNode.attachChild(node);

    Mesh shape = new Dome(20, 20, 1f);

    Material blue = new Material(assetManager, assetPath);
    blue.setColor("Color", new ColorRGBA(0f, 0f, 1f, 0.9f));
    blue.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
    blue.getAdditionalRenderState().setDepthWrite(false);

    Geometry blueDome = new Geometry("blue dome", shape);
    node.attachChild(blueDome);
    blueDome.setLocalScale(900f);
    blueDome.setMaterial(blue);
    blueDome.setQueueBucket(Bucket.Translucent);

    Material red = new Material(assetManager, assetPath);
    red.setColor("Color", new ColorRGBA(1f, 0f, 0f, 0.9f));
    red.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
    red.getAdditionalRenderState().setDepthWrite(false);

    Geometry redDome = new Geometry("red dome", shape);
    node.attachChild(redDome);
    redDome.setLocalScale(500f, 500f, 500f);
    redDome.setMaterial(red);
    redDome.setQueueBucket(Bucket.Translucent);
}

@Override
public void simpleUpdate(float unused) {
    Vector3f position = cam.getLocation().clone();
    node.setLocalTranslation(position);
}

}
[/java]

The outer blue dome is 10% transparent, and so is the inner red one. The domes translate on every update to keep the camera centered, so (apart from roundoff error) I wouldn’t expect camera translation to have any effect on the render. And yet it does. At the initial camera position, only blue is visible, even though the red dome is nearer to the camera:

My reading of https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:intermediate:how_to_use_materials and RenderState.java led me to expect that the two domes would be alpha blended, resulting in a color with red=0.9 and blue=0.09 – that is, mostly red.

Even stranger, after I jiggle the mouse and press ‘W’ to translate the camera, the domes do turns reddish:

As the camera moves through some regions of world-space, the dome color flickers rapidly between red and blue. (Not recommended for those vulnerable to epileptic seizures.)

Moving the blue dome out of Bucket.Translucent would resolve the issue, but imagine if there were something (stars) beyond the blue dome which I wanted to see through both domes.

Any ideas what’s going on here? I’m guessing something to do with the depth buffer, which is a mystery I’ve so far not fathomed.

It has to be something with big numbers. Centering cemera at 0,0,0 works. Making domes 50 and 90 instead of 500 and 900 also works. Can it be floating point/zbuffer fights?

Render order will be a constant pain in this setup.

Is there a reason you aren’t just using the sky bucket? My recollection is that sky bucket things are always drawn in the order they appear in the scene graph.

P.S.: and if you use the sky bucket then you also don’t have to worry about moving the domes all the time. You will want to turn off depth write, though.

1 Like

Putting all the domes into Bucket.Sky seems to solve the problem. Thanks, @pspeed!

I’m still curious why the domes were fighting each other. Are geometries sorted based on the distances to their centers? If so, that’ll fail for pretty much any geometry that’s inside out, since the distances to the centers will often be ordered differently from the distances to the vertices.

@sgold said: Putting all the domes into Bucket.Sky seems to solve the problem. Thanks, @pspeed!

I’m still curious why the domes were fighting each other. Are geometries sorted based on the distances to their centers? If so, that’ll fail for pretty much any geometry that’s inside out, since the distances to the centers will often be ordered differently from the distances to the vertices.

There is no solution. No matter what scheme you come up with, I can trivially come up with cases that will fail to sort properly. Such is the nature of object-based sorting. In fact, it’s trivial to come up with cases for which there is no sorting solution at all.

As I recall, it sorts based on “nearest point on the bounding volume”… and I have no idea what that would be when you are inside.

Welcome to transparency.

1 Like

Lasciate ogne speranza, voi ch’intrate, eh? Thanks for the warning. My college textbook devoted all of two paragraphs to the subject of transparency, so I have lots of catching up to do.

The realization of the 3D graphics transparency limitations is one of those “achievement unlocked” moments.

1 Like