[Solved] Transparency issue, whats in front?


#1

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!


#2

other view:

cubes1


#3

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


#4

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:


#5

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

#6

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


#7

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.


#8

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.


#9

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


#10

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.


#11

@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.


#12

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.


#13

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


#14

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.


#15

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.