Sign in to follow this  

GLSL access depth buffer from shader

This topic is 2851 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guys, I want to read the depth buffer of my FBO in one of my shaders so I can run some DOF equation. I am having trouble reading the buffer however. I setup the depth texture with GL_DEPTH_STENCIL_EXT so I have the stencil value to play with too, but thats another issue for another day.
glBindTexture(GL_TEXTURE_2D, textures[depth]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, wWidth, wHeight, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

then..

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, textures[depth], 0);



I don't how I access just the depth component of the texture from a shader (if it is possible at all?). Can I pass the the depth texture as a sampler? If anyone can help, then thanks.

Share this post


Link to post
Share on other sites
Quote:
Original post by idinev
The texture2D() automatically gives you values in the [0;1] range. The value is (z/w+1)/2
To expand on that answer, you just sample the red component of the depth buffer, and you get the full 24 bit value as a float.
float depth = texture2D( depthBuf, texCoords ).r;

Share this post


Link to post
Share on other sites
Quote:
Original post by Hodgman
Quote:
Original post by idinev
The texture2D() automatically gives you values in the [0;1] range. The value is (z/w+1)/2
To expand on that answer, you just sample the red component of the depth buffer, and you get the full 24 bit value as a float.
float depth = texture2D( depthBuf, texCoords ).r;


Awesome, I'm just on my way to work so i'll give this a blast later. If this is the case as you say, can you access the stencil value with .b?

Share this post


Link to post
Share on other sites
float depth = texture2D(depthImg, gl_TexCoord[0].xy).r;

this doesn't work after all. Always seems to equate to 1 :S. I can't work it out. Here is what I got to try and just output the depth as colour...


uniform sampler2D depthImg;

void main()
{
float depth = texture2D(depthImg, gl_TexCoord[0].xy).r;

gl_FragColor = vec4(depth, depth, depth, 1.0);
}




and in the c++ code...


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[depth]);
shaderDepthColour.UseProgram();
RenderFullscreenQuad();



seems like I am only getting a white screen though :(


Share this post


Link to post
Share on other sites
Yes, it "seems"

Try this in your shader, to convert to linear:

float LinearizeDepth(float zoverw){
float n = 1.0; // camera z near
float f = 20000.0; // camera z far
return (2.0 * n) / (f + n - zoverw * (f - n));
}


uniform sampler2D depthImg;

void main()
{
float depth = texture2D(depthImg, gl_TexCoord[0].xy).r;
depth = LinearizeDepth(depth)*77;

gl_FragColor = vec4(depth, depth, depth, 1.0);
}




Share this post


Link to post
Share on other sites
Quote:
Original post by idinev
Yes, it "seems"

Try this in your shader, to convert to linear:
*** Source Snippet Removed ***


This doesn't work either... is it potentially because I am using the wrong format for my texture?

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, wWidth, wHeight, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);

perhaps when using float data type in the shader the value is getting clamped because it is a 24 uint in the texture?

Share this post


Link to post
Share on other sites
Hopefully you simply didn't change the "n" and "f" vars to match your persp-proj values. Also toy with the "77" value .

Or check if really the depth==1.0 :

float depth = texture2D(depthImg, gl_TexCoord[0].xy).r;
depth = depth==1.0 ? 0 : 1;
gl_FragColor = vec4(depth, depth, depth, 1.0);



The other stuff is: glTexParami(gl_texture_compare_mode) - has to be gl_none, otherwise the sampler will be doing shadowmap comparison (which will result in the exact problem you currently describe).

Share this post


Link to post
Share on other sites
still no joy on this :/ seems like I'm doing something really wrong, or I am missing something so stupid... If I write the depth value from the shader to just the red channel, then the screen is infact red. So depth is clamping to 1.0.

I'll break it all down, maybe someone can see my school boy error.

Vertex shader:

// shaderDepthColour.vs
void main()
{
gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
gl_Position = gl_Vertex;
}



Fragment Shader:
// shaderDepthColour.fs

float LinearizeDepth(float zoverw)
{
float n = 1.0; //
float f = 20000.0;

return(2.0 * n) / (f + n - zoverw * (f - n));
}

uniform sampler2D depthImg;

void main()
{
float depth = texture2D(depthImg, gl_TexCoord[0].xy).r;
depth = LinearizeDepth(depth)*77;

gl_FragColor = vec4(depth, depth, depth, 1.0);
}



CPP code:

////////////buffer setup
//
//
enum TypesTexure
{ colour, normal, depth, texTypeCount, };

glGenTextures(texTypeCount, textures);

// colour buffer texture
glBindTexture(GL_TEXTURE_2D, textures[colour]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, wWidth, wHeight, 0, GL_RGBA, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

// normal buffer texture
glBindTexture(GL_TEXTURE_2D, textures[normal]);
glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, wWidth, wHeight, 0, GL_RGBA, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

// depth buffer
glBindTexture(GL_TEXTURE_2D, textures[depth]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, wWidth, wHeight, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

// framebuffer
glGenFramebuffersEXT(1, &frameBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textures[colour], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, textures[normal], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, textures[depth], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, textures[depth], 0);

////////// render pass 1 (write textures)
////

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBuffer);
const GLenum buffersToUse[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
glDrawBuffers(2, buffersToUse);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderColour.UseProgram();
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);

/// render as normal

glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);

glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

////////// render pass 2 draw depth
////
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
shaderDepthColour.UseProgram();
glBindTexture(GL_TEXTURE_2D, textures[depth]);

RenderFullscreenQuad();



I can render the normal colour just fine, but no depth :/

Sorry for wall of text

Share this post


Link to post
Share on other sites
But did you try the "n, f" and depth==1.0 suggestions?

You _must_ set both "n" and "f" to the zNear and zFar values you passed in the gluPerspective() .

Separately, try the "depth= depth==1.0 ? 0:1;" approach, to have the gpu check whether the values are constant 1.0 , or it's just the RGBA8 precision tricking you into thinking it's all pure white. (in most scenes, most pixels will have values around [0.9996;0.9999999] )

Share this post


Link to post
Share on other sites
Quote:
Original post by idinev
But did you try the "n, f" and depth==1.0 suggestions?

You _must_ set both "n" and "f" to the zNear and zFar values you passed in the gluPerspective() .

Separately, try the "depth= depth==1.0 ? 0:1;" approach, to have the gpu check whether the values are constant 1.0 , or it's just the RGBA8 precision tricking you into thinking it's all pure white. (in most scenes, most pixels will have values around [0.9996;0.9999999] )


I set the values to my gluperspective (0.01 and 100.0) and I also tried the "depth= depth==1.0 ? 0:1;" approach, that still just results in a white screen, (or red if i send it to just the alpha channel). Really don't know what the hell is going on. The scene when rendered as geom colour or normal colour or indeed fully shaded looks like it should in terms of depth, so there must be actual values in the buffer, right?

Share this post


Link to post
Share on other sites
^^"

"depth= depth==1.0 ? 0:1;" -> if this results in white, then depth!=1.0

Also, again:


float LinearizeDepth(float zoverw)
{
float n = 0.01; // You had to change this
float f = 100.0; // and this

return(2.0 * n) / (f + n - zoverw * (f - n));
}


Share this post


Link to post
Share on other sites
Quote:
Original post by idinev
"depth= depth==1.0 ? 0:1;" -> if this results in white, then depth!=1.0


oh of course xD. But then if I run it through the LinearizeDepth func it still give white screen :S


Share this post


Link to post
Share on other sites
Omg you are an absolute hero..

I did mess with the '77' value, but not enough :P. If i put in in the range of 1 - to 5, the I can actually see the depth! anything above 6 and its all white.

Thanks for sticking with this and helping me even though i'm such a dunce xD.

Share this post


Link to post
Share on other sites

This topic is 2851 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this