1
\$\begingroup\$

I'm Work ing on a minecraft-like game (in OpenGL with c++) and I'm tryping to Implement Transparency for Blocks like windows, ice, leafs and water. I've tried to implement Weighted Blended Order-Independent Transparency as it's explained at LearnOpenGL. It basicly seems to work, but all Textures, rendered with the transparent Shader lose their opaqueness, even the Texels with Alpha=1.0.

So my Question is: Is this the normal behavior of this OIT technique?

And do you have any Ideas how I could work around this?

The gray glas frames should be opaque, but you can see the leafs from behind. (Ice, leafs and glass are all rendered using the transparent shader) Scene from my game, with transpanet Blocks

This is the Fragmentshader im using to dispaly transparent Textures.

#version 400 core
layout(location = 0) out vec4 accum;
layout(location = 1) out float reveal;

in float v_lightValue;
in vec2 v_texCoord;
uniform sampler2D u_texture;
uniform vec4 u_color;
const vec4 fogcolor = vec4(0.6, 0.7, 1.0, 1.0);
const float fogdensity = 0.0003;

void main(){    
// Calculation of the Colors including 'fog' if the fragment are further away
    vec4 texColor = texture(u_texture, v_texCoord);
    float z = gl_FragCoord.z / gl_FragCoord.w;
    float fog = clamp(exp(-fogdensity * z * z+1)/2, 0.0, 1.0);
    vec4 color = mix(fogcolor, vec4(texColor.xyz * v_lightValue, texColor.w), fog);

// the weight function from learnopengl.com 
    float weight =
        max(min(1.0, max(max(color.r, color.g), color.b) * color.a), color.a) *
        clamp(0.03 / (1e-5 + pow(z / 200, 4.0)), 1e-2, 3e3);
    // blend func: GL_ONE, GL_ONE
    // switch to pre-multiplied alpha and weight
    accum = vec4(color.rgb * color.a, color.a) * weight;
    // blend func: GL_ZERO, GL_ONE_MINUS_SRC_ALPHA
    reveal = color.a;
}

Please tell me if there is any further information needed to answer this question. As you can see, I'm new to StackExchange :)

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

As documented in the link you cite:

Both new methods guarantee correct coverage of background

ie. they promise that the right amount of the opaque pixels behind all the transparent objects will be obscured. Note that they make no such promise that the foreground will be correct. There, they only say it's "improved", not correct:

...and strictly improve color representation over the previous methods.

This is an obvious and necessary consequence of the way this solution works:

...alter the compositing operator so that it is order independent...

At the time that you draw the translucent-but-full-alpha glass frame, it does not know whether the colour values/weights already in the buffer came from objects behind it or in front of it. And when you draw the foliage, if does not know whether the colour values and weights written by the glass frame came from something in front or behind. So either way, they have to hedge, and assume some fraction - but not all - of the colour in the buffer is between them and the viewer. This assumption is often wrong, but by construction, the operator has no way to discern this and correct for it.

You will never get correct sorting of opaque foreground objects using this method, and should consider rendering these parts with alpha testing rather than blending, or using conventional sorting and blending.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much for your answer. At first I wasn't really shure what you meant by alpha testing, but I realized the I already tried it some days ago, but scraped the Idea , because it couldn't render semi transparent textures like ice or tinted glass. \$\endgroup\$
    – TheBaum
    Commented Mar 22, 2022 at 22:28
2
\$\begingroup\$

I found a suprisingly simple solution for my Problem. Now I don't add my Texures that have either fully transparent or opaque Pixels to the transparent mesh/buffer, but instead to the mesh for solid blocks and use ALPHA_TESTING as suggested by DMGregory♦(just use discard; in my fragment shader if the transparency is smaller then 0.5 or so). After the semi transparent Faces are rendered and the blocks appear in the correct order. (for the semi transparent Blocks i can continue to use the OIT i implemented previously:))

Image of correct transparency

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .