PDA

View Full Version : How to dump the depth to float texture?



Ryan47
02-27-2008, 01:42 AM
Hello all:
In order to avoid the depth precision problem during perspective projection. I try to dump the depth in viewing space to a float texture with CgFx & FBO. However, I find the depth value is always clamped to [0,1]. I've try to set the state DepthClampEnable to false, but it doesn't work. Is there any way to disable the depth clamp in CgFx?

Besides, so far, I use the depth texture with DEPTH_COMPONENT24 which attaches to the FBO(is it the problem?) Since I only need one float channel, which kind of texture format is recommended with CgFx? (ALPHA_16F_ARB?)

Thanks in advance, any ideas are welcome!! Thank you! :)

Ryan47

Korval
02-27-2008, 02:20 AM
I've try to set the state DepthClampEnable to false

What is "DepthClampEnable"? That certainly isn't a GL call.


ALPHA_16F_ARB

Do you really expect a 16-bit floating-point buffer to provide more precision than a 24-bit buffer?

-NiCo-
02-27-2008, 02:34 AM
I believe he is referring to
glEnable(GL_DEPTH_CLAMP_NV);



Do you really expect a 16-bit floating-point buffer to provide more precision than a 24-bit buffer?

Excellent point :)

N.

Zengar
02-27-2008, 04:04 AM
Depth value is always in [0..1] range (with a usual depth buffer, at least -- don't know what happens with a floating-point depth buffer), where 0 corresponds to the near plane and 1 to the far plane. This way, 24-bit depthbuffer has 24 bits of mantissa (vs. 11 bits of fp16).

Xmas
02-27-2008, 04:51 AM
Hello all:
In order to avoid the depth precision problem during perspective projection. I try to dump the depth in viewing space to a float texture with CgFx & FBO. However, I find the depth value is always clamped to [0,1].
Values written from the fragment shader to a float texture shouldn't be clamped unless you explicitly enable color clamping (see the ARB_color_buffer_float (http://www.opengl.org/registry/specs/ARB/color_buffer_float.txt) spec). But it seems to me that is not what you're referring to. Maybe you could explain your FBO configuration and fragment shader in more detail.



Depth value is always in [0..1] range (with a usual depth buffer, at least -- don't know what happens with a floating-point depth buffer), where 0 corresponds to the near plane and 1 to the far plane.
More precisely, the depth value is in the [n, f] range, where n and f are the parameters to glDepthRange(n, f). These parameters are both of type GLclampd and thus clamped to [0, 1]. n, f correspond to -1, 1 in normalized device coordinates. n may be larger than f.

NV_depth_buffer_float adds a new entry point glDepthRangedNV which allows you to define n and f as doubles, i.e. unclamped. Unfortunately it does not allow you to change the definition of clip space Z to the range [0, w].

Ryan47
02-28-2008, 03:06 AM
At first, I wanna say thank you, I really appreciate all your replies!! :)


What is "DepthClampEnable"? That certainly isn't a GL call.

It's the OpenGL State Manager States for CgFX render pass. As Nico said, it equals to the GL statement glEnable(GL_DEPTH_CLAMP_NV);. ^^a


Do you really expect a 16-bit floating-point buffer to provide more precision than a 24-bit buffer?
Actually, the original problem I ran into comes from the second pass of depth peeling. I found if I discard the pixel upon the depth in clip space within some threshold, it lost the precision dramatically(I could only get the expected result very close to near plane of the camera). Therefore, I try to discard the pixel according to the depth in viewing space to minimize the numerical error from matrix multiplication(if I could dump the depth without clamping). However, the depth value I dump to 24-bit buffer is always clamped, so I want to experiment with other floating texture to examine the tradeoff. Currently, I'm not sure this way works or not...


Values written from the fragment shader to a float texture shouldn't be clamped unless you explicitly enable color clamping (see the ARB_color_buffer_float (http://www.opengl.org/registry/specs/ARB/color_buffer_float.txt) spec). But it seems to me that is not what you're referring to. Maybe you could explain your FBO configuration and fragment shader in more detail.
I've tried the case to write the value with type float4 to a float texture, and it works fine. But it fails when I write a float value to a depth texture in my fragment shader. :(

Here is my FBO configuration:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_uiFBO);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_uiRBOs[uiDepthRBO]);

glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_uiWidth, m_uiHeight);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_uiRBOs[uiDepthRBO]);

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, eTexTarget, uiTexHnd, 0);

and my pixel shaders...

// Pass 1, write the value to a depth texture
float WRITE_DEPTH_PS(float4 Pos : TEXCOORD0) : DEPTH
{
return 10.0;
}

// Pass 2, read the value from the texture
float4 READ_DEPTH_PS(float4 Pos : TEXCOORD0, uniform sampler2D InputDepthSampler) : COLOR
{
// Pos : The position in projection space
Pos /= Pos.w;
Pos = Pos * 0.5f + 0.5f;
float fDepth = tex2D(InputDepthSampler, Pos.xy).a;
if( fDepth > 1.0 )
{
return float4(1,0,0,1);
}
else
{
return float4(0,1,0,1);
}
}

Xmas
02-28-2008, 04:11 AM
It's the OpenGL State Manager States for CgFX render pass. As Nico said, it equals to the GL statement glEnable(GL_DEPTH_CLAMP_NV);. ^^a
It's something completely different though. It effectively disables near and far clipping and instead clamps depth values outside the valid range to the range endpoints. It's useful for "automatic capping" of shadow or light volumes.


Actually, the original problem I ran into comes from the second pass of depth peeling. I found if I discard the pixel upon the depth in clip space within some threshold, it lost the precision dramatically(I could only get the expected result very close to near plane of the camera).
Then maybe your far/near ratio is too large. FP16 view space depth will only become more precise at the far plane than 24 bit fixed point screen space depth if the far/near ratio is larger than 8197. Move your near plane as far out as possible without causing clipping artifacts.


I've tried the case to write the value with type float4 to a float texture, and it works fine. But it fails when I write a float value to a depth texture in my fragment shader. :(
That's because a texture of type DEPTH_COMPONENT24 can't represent values outside [0, 1]. When you "write a float value" to a non-float texture it will be converted to the target format, including clamping to the representable range. Just like what happens when you render to an RGBA8 texture.

Besides, writing gl_FragDepth (or the equivalent in Cg) in the fragment shader is extremely inefficient since it disables all early Z optimizations.

Ryan47
02-28-2008, 07:48 PM
It's the OpenGL State Manager States for CgFX render pass. As Nico said, it equals to the GL statement glEnable(GL_DEPTH_CLAMP_NV);. ^^a
It's something completely different though. It effectively disables near and far clipping and instead clamps depth values outside the valid range to the range endpoints. It's useful for "automatic capping" of shadow or light volumes.
Thanks for correcting me!! I'm sorry for the misunderstanding! :)


Then maybe your far/near ratio is too large. FP16 view space depth will only become more precise at the far plane than 24 bit fixed point screen space depth if the far/near ratio is larger than 8197. Move your near plane as far out as possible without causing clipping artifacts.
I've moved my near plane as far as possible, and the ratio of near/far is not that large(about 23/300). Maybe there is some problem about my depth texture. I will check it out! ^^a


That's because a texture of type DEPTH_COMPONENT24 can't represent values outside [0, 1]. When you "write a float value" to a non-float texture it will be converted to the target format, including clamping to the representable range. Just like what happens when you render to an RGBA8 texture.

Besides, writing gl_FragDepth (or the equivalent in Cg) in the fragment shader is extremely inefficient since it disables all early Z optimizations.

Thanks for reminding me, I will keep it in mind!!
Thank you, Xmas! :)