Opengl Depth Value Transformation

出自 http://www.opengl.org/archives/resources/faq/technical/depthbuffer.htm 


老是忘记。。于是干脆直接粘到这里方便自己找。


Why is my depth buffer precision so poor?

The depth buffer precision in eye coordinates is strongly affected by the ratio of zFar to zNear, the zFar clipping plane, and how far an object is from the zNear clipping plane.

You need to do whatever you can to push the zNear clipping plane out and pull the zFar plane in as much as possible.

To be more specific, consider the transformation of depth from eye coordinates

xe, ye, ze, we

to window coordinates

xw, yw, zw

with a perspective projection matrix specified by

glFrustum(l, r, b, t, n, f);

and assume the default viewport transform. The clip coordinates of zc and wc are

zc = -ze* (f+n)/(f-n) - we* 2*f*n/(f-n)

wc = -ze

Why the negations? OpenGL wants to present to the programmer a right-handed coordinate system before projection and left-handed coordinate system after projection.

and the ndc coordinate:

zndc = zc / wc = [ -ze * (f+n)/(f-n) - we * 2*f*n/(f-n) ] / -ze

= (f+n)/(f-n) + (we / ze) * 2*f*n/(f-n)

The viewport transformation scales and offsets by the depth range (Assume it to be [0, 1]) and then scales by s = (2n-1) where n is the bit depth of the depth buffer:

zw = s * [ (we / ze) * f*n/(f-n) + 0.5 * (f+n)/(f-n) + 0.5 ]

Let's rearrange this equation to express ze / we as a function of zw

ze / we = f*n/(f-n) / ((zw / s) - 0.5 * (f+n)/(f-n) - 0.5)

= f * n / ((zw / s) * (f-n) - 0.5 * (f+n) - 0.5 * (f-n))

= f * n / ((zw / s) * (f-n) - f) [*]

Now let's look at two points, the zNear clipping plane and the zFarclipping plane:

zw = 0 => ze / we = f * n / (-f) = -n

zw = s => ze / we = f * n / ((f-n) - f) = -f

In a fixed-point depth buffer, zw is quantized to integers. The next representable z buffer depth away from the clip planes are 1 and s-1:

zw = 1 => ze / we = f * n / ((1/s) * (f-n) - f)

zw = s-1 => ze / we = f * n / (((s-1)/s) * (f-n) - f)

Now let's plug in some numbers, for example, n = 0.01, f = 1000 and s = 65535 (i.e., a 16-bit depth buffer)

zw = 1 => ze / we = -0.01000015

zw = s-1 => ze / we = -395.90054

Think about this last line. Everything at eye coordinate depths from -395.9 to -1000 has to map into either 65534 or 65535 in the z buffer. Almost two thirds of the distance between the zNear andzFar clipping planes will have one of two z-buffer values!

To further analyze the z-buffer resolution, let's take the derivative of [*] with respect to zw

d (ze / we) / d zw = - f * n * (f-n) * (1/s) / ((zw / s) * (f-n) - f)2

Now evaluate it at zw = s

d (ze / we) / d zw = - f * (f-n) * (1/s) / n

= - f * (f/n-1) / s [**]

If you want your depth buffer to be useful near the zFar clipping plane, you need to keep this value to less than the size of your objects in eye space (for most practical uses, world space).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值