Depth texture in shader

Started by
8 comments, last by MGB 17 years, 1 month ago
Hi all, I'm trying to use a rendered depth texture in my shader, but I seem to get a uniform value when I sample the texture in the shader. I've tried LOTS of things to get this working but all have failed so far. The best I can get is some kind of contours that makes me think there may be *some* values in there, but I can't get anything usable. Is there a way to read the 'depth' val of the current fragment? I've also read something about 'DEPTH_TEXTURE_MODE' and 'TEXTURE_COMPARE_MODE' in the GL spec, but it's rather unclear... Can anyone spot any mistakes here..? Relevant code: Init depth texture:

	glBindTexture(GL_TEXTURE_2D, ETxDepthRender);	// Creates a texture object.
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, KRenderedTextureSize, KRenderedTextureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);




Get depth render to texture:

	glBindTexture(GL_TEXTURE_2D, ETxDepthRender);
	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, KRenderedTextureSize, KRenderedTextureSize, 0);




Fragment shader excerpts:

uniform sampler2DShadow WaterDepth2d;
...
{
	// Add sea colour for water depth:
	const float depthVal = shadow2DProj(WaterDepth2d, ProjTexCoord).x;
	float ecWaterPos = -ecPos.z*0.005;  // Looks ok
	float sceneDepth = ZPosFromDepthBufferValue(depthVal);
	float distUnderwater = max(0.0f, sceneDepth - ecWaterPos);
...
        vec3 color = vec3(depthVal, 0.0, 0.0);
}

float ZPosFromDepthBufferValue(float depthBufferValue)
{
	const float f1 = gl_DepthRange.far / (gl_DepthRange.far - gl_DepthRange.near);
	const float f2 = gl_DepthRange.far * gl_DepthRange.near / (gl_DepthRange.near - gl_DepthRange.far);
	return f2 / (depthBufferValue - f1);
}



Ed: I know my texture projection stuff works ok. [Edited by - Aph3x on March 7, 2007 4:30:10 PM]
Advertisement
IIRC u have to set the TEXTURE_COMPARE_MODE (or something) to GL_NONE
thus the texture is treated as color + not as depth values
most likely all the values in the depthtexture are gonna be close to 1.0 eg 0.9945 thus the texture will appear white

one way to see if its working correctly is, raise the number to some power eg 128

const float depthVal = texture2DProj(WaterDepth2d, ProjTexCoord).x;
vec3 color = vec3( pow( depthVal, 128.0 ) );
Hmmm that makes sense I guess - I *am* getting values in there (non-zero).
I'll try the power thing out tonight :)

I made a few changes to the texture setup after my post above... still no joy though:
	glBindTexture(GL_TEXTURE_2D, ETxDepthRender);	// Creates a texture object.	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, KRenderedTextureSize, KRenderedTextureSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);	glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);



[Edited by - Aph3x on March 8, 2007 6:05:54 AM]
Have you considered rendering to an FBO (and attaching a render buffer to catch the depth in a texture?)

If you have never used FBO check out this good write up (FBO 101)

http://www.gamedev.net/reference/articles/article2331.asp

I think FBO would increase performance overall, since you would not have to copy the depth data. I cannot say that with 100% confidence though, since I don't have all of your code.

Check for any GL errors before AND after each snippet of your code, especially these ones:
	glBindTexture(GL_TEXTURE_2D, ETxDepthRender);	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, KRenderedTextureSize, KRenderedTextureSize, 0);


glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, KRenderedTextureSize, KRenderedTextureSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);


[Edited by - WilyCoder on March 8, 2007 11:10:29 AM]
Wily: yer I check all the errors after ops - there are none (after much mucking about to get to this state I can tell you ;))

The FBO article is good - but it seemed to me I'd have to render the scene twice to get colour and depth textures, or can you attach multiple targets?
Zedz: nice one - looks like that power stuff works :) (after a fashion - kludge scale factors etc) - so the depth texture does contain relevant info.

Trouble is now that the sea loses all transparency when I'm anything over '10' units above it. Presume this is the z-buffer losing precision - I just didn't think it'd lose precision *quite* so fast!!
Any ideas/suggestions on that?

Ed: perhaps I should try pushing out my near plane as far as I can when drawing the depth buffer...

[Edited by - Aph3x on March 9, 2007 5:14:47 AM]
Quote:Original post by Aph3x
Wily: yer I check all the errors after ops - there are none (after much mucking about to get to this state I can tell you ;))

The FBO article is good - but it seemed to me I'd have to render the scene twice to get colour and depth textures, or can you attach multiple targets?


Just FYI:You can get color and depth from a single render call using an FBO.

Good luck! :)
Hi Aph3x,

Did you get any further with your problem? I'm having the same issues, which I've also decided are down to some precision problem with my depth textures. I'm using my depth textures for shadows, and as I move shadow casting objects away from the light, their shadows break up very quickly.

I'm using a 16-bit texture as my shadow buffer. If I project this texture onto the scene, or dump it to a file, then the stored values obviously 'wash out' to white (1.0 depth) very close to the light.

I've also tried using a regular FBO depth buffer, and transfering depth to a texture via a fragment shader, but no joy there, either. I think that this route might work if I give it some more thought, but it seems like such a waste, when ARB_depth_buffer is there to be used without any shader malarkey.

If I set the camera frame to be the same as the light frame, and change the frame depth buffer to 16-bit, the scene still renders just fine without any z-fighting, so it's not like I've got crazy scene setup.
hmmm I solved my problem, for anyone who's interested. I stuck with 16bit depth textures in my FBO, using ARB_depth_texture, but changed my depth normalisation (when testing against values from the depth texture) from

depth = pos.z / pos.w;

to

depth = (1.f / nearZ - 1.f / posz) / (1.f / nearZ - 1.f / farZ);

Now my shadow buffers work alright! yay!
Hi Coderfish,
Not really sorted yet - thanks for adding that though - similar to the ZPosFromDepthBufferValue fn I was using, but I'll try yours out :)
Probably try a 16-bit z buff too and see what I get.

/grasping at straws ;)

This topic is closed to new replies.

Advertisement