OpenGL - How to create Order Independent transparency?
Asked Answered
N

4

15

I've been working on a game engine for educational purposes and I came across this issue I cannot seem to find an answer for:

Alpha channel only works for objects that have already been drawn before the object that has the alpha channel (For example: in a scene with 3 objects, let's say a cat, a dog and a bottle(transparent). both the cat and the dog are behind the bottle; the dog is drawn first, the bottle second, the cat third. only the dog will be seen through the bottle).

Here's a picture of this issue: The objects are drawn in the order they appear in the list box

I used C++ for the engine, Win32 API for the editor and GLSL for shading:

// some code here
vec4 alpha = texture2D(diffuse, texCoord0).aaaa;
vec4 negalpha = alpha * vec4(-1,-1,-1,1) + vec4(1,1,1,0);

vec4 textureComponentAlpha = alpha*textureComponent+negalpha*vec4(1,1,1,0);//(texture2D ( diffuse, texCoord0 ) ).aaaa;

gl_FragColor = (textureComponentAlpha + vec4(additiveComponent.xyz, 0)) * vec4(lightingComponent.xyz, 1);

In C++:

glEnable(GL_ALPHA_TEST);
glDepthFunc(GL_EQUAL);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

I assume it has something to do with the way the alpha test is made, or something like that.

Could anyone help me fix this, please?

Nicolella answered 13/6, 2016 at 0:10 Comment(4)
I'm not sure what you are asking for. Order independent transparency is neither cheap nor easy to implement, certainly beyond the scope of an answer on this site.Corycorybant
I have faced the same problem, and my solution involved recursive multi-pass rendering, stencilling, clipping, and a lot of maths. Books could be written on such techniques, and indeed may have been. OpenGL doesn’t just magically do it all for you. If you’re looking for a simple solution, I’m afraid there isn’t one.Palliasse
I wrote an overview of some simple transparency rendering approaches in an answer here: #23281192.Diffuse
here link to new related question about Dual depth peelingCamillacamille
C
21

I am using something similar to that answer linked by @RetoKoradi comment but I got double layered transparent models with textures (glass with both inner and outer surface) with fully solid machinery and stuff around.

For such scenes I am using also multi pass approach and the Z-sorting is done by sequence of setting front face.

  1. render all solid objects
  2. render all transparent objects

    This is the tricky part first I set

    glGetIntegerv(GL_DEPTH_FUNC,&depth_funct);
    glDepthFunc(GL_ALWAYS);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_CULL_FACE);
    

    I got the geometry layers stored separately (inner outer) so The Z-sorting is done like this:

    • Render outer layer back faces with glFrontFace(GL_CW);
    • Render inner layer back faces with glFrontFace(GL_CW);
    • Render inner layer front faces with glFrontFace(GL_CCW);
    • Render outer layer front faces with glFrontFace(GL_CCW);

    And lastly restore

    glDisable(GL_BLEND);
    glDepthFunc(depth_funct);
    
  3. render all solid objects again

It is far from perfect but enough for my purposes it looks like this:

example

Camillacamille answered 13/6, 2016 at 6:28 Comment(0)
M
9

I cannot encourage you enough to have a look at this NVidia paper and the related blog post by Morgan McGuire.

This is pretty easy to implement and has great results overall.

Mccary answered 13/6, 2016 at 11:9 Comment(1)
These are great links, but the answer is supposed to contain the main information in itself.Mundford
T
2

Im not entirely sure this will help your situation, but do you have blending and alpha enabled? As in :

glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Tanka answered 13/6, 2016 at 0:23 Comment(1)
I already use this setup. I updated the question to contain this. Thank you thought!Nicolella
M
2

The method to get correct transparency of rendered objects independently from the order in which they are drawn is named Order Independent Transparency (OIT).

There is a great presentation from Nvidia summarizing the latest solutions in this area: Order Independent Transparency In OpenGL 4.x

"OpenGL 4.x" in the title is not accidental, because only in OpenGL 4.2 core appears Atomic Counters, which are important for OIT implementation.

One of the algorithms of OIT is as follows:

  1. During the first pass of rendering, store each fragment in a buffer, and collect all fragments for a single screen pixel in a linked list. Atomic Counters are used both to store new fragments in a buffer and to maintain linked list in each screen pixel.
  2. During the second pass of rendering, each linked list is sorted according to z-depth and fragments are alpha-blended in correct order.

A simple alternative to OIT is to discard every second (odd) fragment in a fragment shader:

    if (onlyOddFragments && ((int(gl_FragCoord.x) + int(gl_FragCoord.y)) % 2) == 1)
      discard;

So you will see the objects farther from the camera in the discarded fragments. If multisample antialiasing (MSAA) is activated, then no checkboard pattern is visible even in lowest resolution.

Here is a video comparing the standard transparency approach where all triangles are output simply in order, as well as two above approaches. The implementation can be found in some open-source GitHub projects, e.g. here.

Mundford answered 26/2, 2023 at 11:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.