6
\$\begingroup\$

I try to implement order-independet transparency sticking to the pseudo code in the linked paper (page 4). I can't figure out how they are able to do this in OpenGL.

I am rendering the scene two times in two different framebuffers and then want to blend the two. The first rendering uses the normal depth test GL_LESS. So I receive the nearest fragments in the first framebuffer.

I want to render the second nearest fragments in the second framebuffer. In the pseudo code they use the depth test GL_GREATER for this. But this would result in having the "farest" fragments in the second framebuffer, right?

So how can I render the "second nearest" pixels to a framebuffer? Which depth test would be right and how to apply it in OpenGL?

\$\endgroup\$
3
\$\begingroup\$

You should perform the depth test in the fragment shader "manually". OpenGL doesn't support multiple depth tests, and that its just what you need to render the second nearest pixels, because:

  • You need the second front pixels (GL_LESS over the actual depth buffer)
  • You need the second front pixels (GL_GREATER over the depth buffer of the first framebuffer).

This can't be done without the help of a shader, as you can only choose one of those two depth tests to be performed at once.

So:

  • You will need to read from the depth buffer of the first framebuffer. This can be done "making" the first framebuffer use a texture as a depth buffer and reading values from it later using texture(). You can assign a texture as depth buffer to a framebuffer using:
//I'm using Java and LWJGL in the example, C++ implementation should be pretty similar.
    int texture=glGenTextures();
    //Set active texture, bind it, etc.
    glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT24, X_RES, Y_RES, 0,GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, (FloatBuffer)null);
//Hey you active framebuffer, use this texture as your depth buffer from now on
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
  • Set the depth test to GL_LEQUAL or GL_LESS (the default depth test)
  • Draw the scene again into the second framebuffer, but performing a second depth test over the first framebuffer depth texture in the fragment shader, like so:


uniform sampler2D depthTexture; 
//current projected position, being z the depth. //Assuming x and y coordinates normalized, in [0..1] range. //To transform from standard [-1..1] coordinates to [0..1] //coordinates, you can do (pos.x+1)/2, for example. in vec3 pos;
void main() { if(pos.z<=texture(depthTexture,vec2(pos.x,pos.y))) discard; //Manually performing the GL_GREATER depth test for each pixel
//Rest of your shader code, if needed }

  • Done!
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.