Transparency in overlapping and colliding sprites

I am not the first person to have problems with transparency, but I could not find another thread with a solution to this exact problem.
I’ll try to keep this short but some slight context.
I want to add trees to my game, I downloaded a gltf of a tree and converted it to a .j3o using JMEC (I did also run it through blender to change the trees to separate models, hence the tree1.glb.j3o). I then added a light to my scene, added my tree, changed its bucket to Transparent and changed the Depth Write to false.

        Spatial tree = Globals.assetManager.loadModel("Models/Tree/tree1.glb.j3o");
        tree.setQueueBucket(Transparent);
        tree.depthFirstTraversal(spatial -> {
            if(spatial instanceof Geometry){
                Geometry g = (Geometry) spatial;
                Material m = g.getMaterial();
                m.getAdditionalRenderState().setDepthWrite(false);
            }
        });
        root.attachChild(tree);

However the sprites of the leaves are not being rendered in the correct order, here is a video of what is happening

and here is an image for when that link expires (it’s hard to see that the sprites in the rear are being rendered in front as an image)


I have tried playing around with the functions in the Materials Overview in the wiki but couldn’t find an easy fix. Is there an easy way to solve this without having to tinker too much with the engine? Do I have to make some adjustments to the mesh itself?

Probably this is not what you want. It means that the leaves will not write depth and anything else in your scene will then effectively stomp all over them whether they are above or below.

Probably what you want is to leave depth test and depth write alone and set an alpha discard threshold.

3 Likes

Yeah that makes more sense, finally got it to work!

For the people in the future looking at this thread the updated code looks like

        Spatial tree = Globals.assetManager.loadModel("Models/Tree/tree1.glb.j3o");
        tree.setQueueBucket(Transparent);
        tree.depthFirstTraversal(spatial -> {
            if(spatial instanceof Geometry){
                Geometry g = (Geometry) spatial;
                Material m = g.getMaterial();
                m.setFloat("AlphaDiscardThreshold", 0.5f);
            }
        });
        geometry.attachChild(tree);

And this wiki page is relevant

2 Likes

A couple more tips.

  1. SceneGraphVisitorAdapter (jMonkeyEngine3)

Slightly simpler:

tree.depthFirstTraverser(new SceneGraphVisitorAdapter() {
    public void visit( Geometry geom ) {
        Material m = g.getMaterial();
        m.setFloat("AlphaDiscardThreshold", 0.5f);
    }
});
  1. Material parameter overrides…

A lot simpler:

tree.addMatParamOverride(new MatParamOverride(VarType.Float, "AlphaDiscardThreshold", 0.5f));

MatParamOverrides are great when you need to change the same material parameter for a whole subgraph.

6 Likes

Wow thanks for the tip @pspeed , I wasn’t aware of the last override method.

2 Likes