[solved] Importing a complex model containg transparency

Hello,

I’m trying to load a complex model (a house), which have some transparent elements in it (window glass with an alpha of 0.5) and also some PNG textures with transparency in it (plants, decals of damages onto the wall etc …).
The model is made with Google Sketchup and i use Collada format to import.

The model loads well except the transparent elements:

  • Window glass is opaque
  • PNG’s transparent part is black

I suppose i have to change the bucket of the transparents elements, but what is the best method to do that ?
I see three possible way to do it :

  1. Dividing the model into two models : one containing only opaque elements and one containing only transparent ones.
    This is the method i want to avoid.

  2. Setting a parameter during import of model or at the root node of it to tells JMe that this node contains transparent geometry which should be moved in transparent bucket.
    Is it possible ?

  3. Using a SceneGraphVisitorAdapter or something similar to detect myself the transparent elements or PNG textures and change by myself the bucket of it.
    Is this method feasible ?

Thanks in advance,

Ga3L

Have you tried setting the transparent materials’ alpha discard threshold to something like .1?

And also make sure that the model is set to “BlendMode.Alpha” under “AdditionalRenderState” in the material editor. Or if you edit your materials by code, use material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);

This is the general approach you will want. Detecting this without some kind of naming convention may be hard in your particular asset pipeline.

1 Like

Thanks for the answser !

@BigBob and @yaRnMcDonuts I already knew i had to properly set the getAdditionnalRenderState to make it works, i was just wondering if there was an automatic detection of transparent/transluscent materials and png in a loaded model.

So i followed the Graph Visitor approach as advised by @pspeed and it work’s !

Here is the minimal code if someone encounter the same issue:

public class TransparencyRepairer extends SceneGraphVisitorAdapter {
    @Override
    public void visit(Geometry c) {
        if(c.getMaterial().getTextureParam("DiffuseMap") != null) {
            if(c.getMaterial().getTextureParam("DiffuseMap").getTextureValue().getKey().getExtension().compareTo("png") == 0) {
                c.getMaterial().getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
                c.setQueueBucket(RenderQueue.Bucket.Transparent);
            }
            else if(c.getMaterial().getTextureParam("DiffuseMap").getTextureValue().getKey().getName().contains("Translucent")) {
                c.getMaterial().getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
                c.setQueueBucket(RenderQueue.Bucket.Transparent);
                c.getMaterial().setColor("Diffuse", new ColorRGBA(1, 1, 1, 0.5f));
            }
        }
    }
}

Notice that there is the word “Tranluscent” in my texture’s URL, this is how i detect which element should be transparent.

Translucent mean something else in JME, its like render-over-everything state(similar to transparent, but nothing non-translucent can hide it).

here i think you should rather use just “Transparent” name

btw. i am using something similar to you(using in visitor):

public static void transparencyFixer(Geometry geom){
    for (String name : Arrays.asList(new String[] { "ColorMap", "DiffuseMap", "BaseColorMap" })) {
        MatParam tex = geom.getMaterial().getParam(name);
        String texName = tex != null ? tex.getValueAsString() : "";
        if(texName.contains("Transparent")){
            geom.getMaterial().setFloat("AlphaDiscardThreshold", 0.5f);
            geom.setQueueBucket(RenderQueue.Bucket.Transparent);
            geom.getMaterial().getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
        }
    }
}

That’s not true. Amongst other things it primarily dictates the order it’s drawn. Opaque, translucent, transparent.

Ignoring depth results in drawing over everything.

if something is last in order, then other render order states cant hide it…

thats exactly what i said…

btw. you should tell just more how it work exactly, not negate it in first words.

There’s a link in the header. I only know slightly more than that in truth but it becomes something one needs to understand the concept of once you start using transparent and translucent objects.

Transparent is almost always what you want.

Translucent will render over everything as if you have depth write or depth test turned off… if you don’t have a special filter post processing setup. I use it all the time for this exact thing because it’s easy.

What it was designed for is the case where objects (especially transparent ones) needed to be rendered at a specific point in the filter post-processing pipeline… say for example if you needed something transparent rendered in line with the water filter.

In that case, for the translucent bucket to render properly then you need a translucent filter added to the post processor where you want that bucket rendered.

…else the translucent filter will just render over the top of everything as if depth has been cleared.

So, oxplay2 is right that Bucket.Transparent is probably what is needed in this case.

1 Like

So I am wrong in thinking they are ordered as I thought. I live and learn.

They are ordered as you thought. And without intervention, the translucent bucket is rendered exactly where filter post processing would be. If you have filtered post processing enabled then it may not be rendered at all.

This statement was essentially correct in the same way. You stated that it was incorrect.

The translucent bucket ignores depth, basically… unless it’s part of a filtered post processor change that has depth available.

2 Likes