[Solved] Transparency issue, whats in front?

Hi, I just started using jme on Android and ran into a problem when I played around with transparency:
I have a simple .obj file with two cubes, this is my code:

ColorRGBA sky = new ColorRGBA(1f, 1f, 1f,1f);
viewPort.setBackgroundColor(sky);
Spatial cubes = assetManager.loadModel("models/cubes.obj");

Material cubesmat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
cubesmat.setColor("Color", new ColorRGBA(0f, 0f, 0f, 0.25f));
cubes.setMaterial(cubesmat);
cubesmat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);

//stuff i tried to fix the problem
cubes.setQueueBucket(RenderQueue.Bucket.Translucent);
cubesmat.setFloat("AlphaDiscardThreshold", 0.05f);
renderManager.setAlphaToCoverage(true);

rootNode.attachChild(cubes);

When I look at it from one side it looks fine:

(Sorry, new users can only put one image in a post.) - see reply

But when I rotate the view and put the other cube in front the transparency doesnt work as expected:

cubes2

Any help would be appreciated!

other view:

cubes1

I highly suggest to do first the beginners tutorials in the wiki which is linked above, it is really really worth the time.

Here the tutorial for materials and transparency stuff https://wiki.jmonkeyengine.org/jme3/beginner/hello_material.html

Maybe it is worth the effort to put a direct link above beside ā€œMath for Dummiesā€?! Ah and there is as well a ā€œTransparency for dummiesā€ :smile:

Thank you for your reply @ia97lies.

I already read that tutorial and I thought I followed its instructions.

Even when I use a Texture like in the tutorial I get the same result.

ColorRGBA sky = new ColorRGBA(1f, 1f, 1f,1f);
viewPort.setBackgroundColor(sky);
Spatial cubes = assetManager.loadModel("models/cubes.obj");

Material cubesmat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
cubesmat.setTexture("ColorMap", assetManager.loadTexture("textures/gray_25alpha.png"));
cubesmat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
cubes.setQueueBucket(RenderQueue.Bucket.Transparent);
cubes.setMaterial(cubesmat);
rootNode.attachChild(cubes);

flyCam.setEnabled(false);
ChaseCamera chaseCam = new ChaseCamera(cam, cubes, inputManager);

gray_25alpha.png:
gray_25alpha

cubes.obj:

cube.obj

#
 
g cube
 
v  0.0  0.0  0.0
v  0.0  0.0  1.0
v  0.0  1.0  0.0
v  0.0  1.0  1.0
v  1.0  0.0  0.0
v  1.0  0.0  1.0
v  1.0  1.0  0.0
v  1.0  1.0  1.0

v  0.0  0.0  3.0
v  0.0  0.0  4.0
v  0.0  1.0  3.0
v  0.0  1.0  4.0
v  1.0  0.0  3.0
v  1.0  0.0  4.0
v  1.0  1.0  3.0
v  1.0  1.0  4.0

vn  0.0  0.0  1.0
vn  0.0  0.0 -1.0
vn  0.0  1.0  0.0
vn  0.0 -1.0  0.0
vn  1.0  0.0  0.0
vn -1.0  0.0  0.0
 
f  1//2  7//2  5//2
f  1//2  3//2  7//2 
f  1//6  4//6  3//6 
f  1//6  2//6  4//6 
f  3//3  8//3  7//3 
f  3//3  4//3  8//3 
f  5//5  7//5  8//5 
f  5//5  8//5  6//5 
f  1//4  5//4  6//4 
f  1//4  6//4  2//4 
f  2//1  6//1  8//1 
f  2//1  8//1  4//1 

f  9//2  15//2  13//2
f  9//2  11//2  15//2 
f  9//6  12//6  11//6 
f  9//6  10//6  12//6 
f  11//3  16//3  15//3 
f  11//3  12//3  16//3 
f  13//5  15//5  16//5 
f  13//5  16//5  14//5 
f  9//4  13//4  14//4 
f  9//4  14//4  10//4 
f  10//1  14//1  16//1 
f  10//1  16//1  12//1

Ooops :slight_smile:

I guess both cubes are transparent, right? I guess it has to do with z-sorting, but I donā€™t know how to solve, maybe this link helps: https://wiki.jmonkeyengine.org/jme3/intermediate/transparency_sorting.html

In that link the suggestion is to use

cubesmat.setFloat("AlphaDiscardThreshold", 0.05f);

I tried that already (see my first post).
I guess the problem is that the z buffer of the cubes object is static.

This will explain it all:

There are some problems with no solutions. Transparency is a fake effect and will always have one limitation or another.

Thanks @pspeed, not the answer I was hoping for, but at least a definitive one. Seems like I have to rethink my visualization.

By the way, Bucket.Translucent is definitely not what you want. Bucket.Transparent would at least sort the objects back to front which reduces the issues.

@pspeed and anybody interested:

    ColorRGBA sky = new ColorRGBA(1f, 1f, 1f,1f);
    viewPort.setBackgroundColor(sky);
    Spatial cubes = assetManager.loadModel("models/cubes.obj");

    Material cubesmat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    cubesmat.setColor("Color", new ColorRGBA(0f, 0f, 0f, 0.25f));
    cubes.setQueueBucket(RenderQueue.Bucket.Transparent);
    cubesmat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
    cubesmat.getAdditionalRenderState().setDepthTest(true);
    cubesmat.getAdditionalRenderState().setDepthWrite(false);
    cubes.setMaterial(cubesmat);
    rootNode.attachChild(cubes);

    flyCam.setEnabled(false);
    ChaseCamera chaseCam = new ChaseCamera(cam, cubes, inputManager);

Setting depthTest to true and depthWrite to false solves the issue.

1 Like

In your case, I guess maybe this worksā€¦ as long as you arenā€™t adding anything else to the scene.

ā€¦but then you can also just turn off depth test for both of the cubes as you are effectively ignoring the zbuffer completely.

No, disabling the depth test is not the same, imho.
Add a box:

    ColorRGBA sky = new ColorRGBA(1f, 1f, 1f,1f);
    viewPort.setBackgroundColor(sky);
    Spatial cubes = assetManager.loadModel("models/cubes.obj");

    Material cubesmat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    cubesmat.setColor("Color", new ColorRGBA(0f, 0f, 0f, 0.25f));
    cubes.setQueueBucket(RenderQueue.Bucket.Transparent);
    cubesmat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
    cubesmat.getAdditionalRenderState().setDepthTest(true);
    cubesmat.getAdditionalRenderState().setDepthWrite(false);
    cubes.setMaterial(cubesmat);

    Geometry box = new Geometry("ego", new Box(0.5f,0.5f,0.5f));
    Material boxmat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    boxmat.setColor("Color", new ColorRGBA(1f, 0f, 0f, 1f));
    box.setLocalTranslation(0f,0f,2f);
    box.setMaterial(boxmat);

    rootNode.attachChild(box);
    rootNode.attachChild(cubes);

    flyCam.setEnabled(false);
    ChaseCamera chaseCam = new ChaseCamera(cam, cubes, inputManager);

from one side:
one_side

from the other side:
other_side

This is a different scene than the one you showed before that only had two boxes.

Anyway, turning off depth write will have artifacts alsoā€¦ essentially you are saying ā€œdonā€™t depth test this box with any othersā€. So depending on order you can get issues.

Yes, it is because:

And it works. Also, this works in the real app with a lot of different transparent Geometries.
setDepthWrite(false) is not the same as setDepthTest(false).
I just posted my solution if anybody has the same problem, maybe its worth a try.