为什么我要在OpenGL的透视投影中除以W ?

时间:2022-09-10 18:05:04

I guess this is more a math question than it is an OpenGL one, but I digress. Anyways, if the whole purpose of the perspective divide is to get usable x and y coordinates, why bother dividing z by w? Also how do I get w in the first place?

我想这是一个数学问题,而不是OpenGL的问题,但我跑题了。不管怎样,如果透视的全部目的是为了得到可用的x和y坐标,为什么要把z除以w呢?我怎么得到w呢?

1 个解决方案

#1


12  

Actually, the explanation has much more to do with the limitations of the depth buffer than it does math.

实际上,这个解释与深度缓冲的局限性有关,而不是数学。

At its simplest, "the depth buffer is a texture in which each on-screen pixel is assigned a grayscale value depending on its distance from the camera. This allows visual effects to easily alter with distance." Source

在最简单的情况下,“深度缓冲是一种纹理,每个屏幕上的像素根据其与摄像机的距离来分配灰度值。这使得视觉效果可以轻易地改变距离。源

More accurately, a depth buffer is a texture containing the value of z/w for each fragment, where:

更准确地说,深度缓冲是一个包含每个片段的z/w值的纹理,其中:

  • Z is the distance from the near clipping plane to the fragment.
  • Z是距离近剪切面到碎片的距离。
  • W is the distance from the camera to the fragment.
  • W是距离摄像机到碎片的距离。

In the following diagram illustrating the relationship between z, w, and z/w, n is equal to the zNear parameter passed to gluPerspective, or an equivalent function, and f is equal to the zFar parameter passed to the same function.

下图说明了z、w和z/w之间的关系,n等于传递给gluPerspective的zNear参数,或等效函数,f等于传递给相同函数的zFar参数。

为什么我要在OpenGL的透视投影中除以W ?

At a glance, this system look unintuitive. But as a result, z/w is always a floating-point value between 0 and 1 (0/n and f/f), and can therefore be represented as a single channel of a texture.

乍一看,这个系统看起来不太直观。但是,z/w始终是0到1 (0/n和f/f)之间的浮点值,因此可以表示为纹理的单个通道。

A second important note: the depth buffer is nonlinear, meaning an object exactly in between the near and far clipping planes is nowhere near a value of 0.5 in the depth buffer. As shown above, it would correlate to a value of 0.999 in the depth buffer. Depending on your view, this could be good or bad; you may want the depth buffer to be more detailed close-up (which it is), or offer even detail throughout (which it doesn't).

另一个重要的注意事项:深度缓冲是非线性的,这意味着在深度缓冲中,近距离和远剪切面之间的距离远小于0.5。如上所示,它与深度缓冲区中的0.999的值相关。根据你的观点,这可能是好是坏;您可能希望深度缓冲是更详细的特写(它是),或者提供更详细的(它没有)。

TL;DR:

TL;博士:

  • You divide z by w so it is always in the range [0, 1].
  • 你把z除以w,所以它总是在范围[0,1]。
  • W is the distance from the camera to the fragment.
  • W是距离摄像机到碎片的距离。

#1


12  

Actually, the explanation has much more to do with the limitations of the depth buffer than it does math.

实际上,这个解释与深度缓冲的局限性有关,而不是数学。

At its simplest, "the depth buffer is a texture in which each on-screen pixel is assigned a grayscale value depending on its distance from the camera. This allows visual effects to easily alter with distance." Source

在最简单的情况下,“深度缓冲是一种纹理,每个屏幕上的像素根据其与摄像机的距离来分配灰度值。这使得视觉效果可以轻易地改变距离。源

More accurately, a depth buffer is a texture containing the value of z/w for each fragment, where:

更准确地说,深度缓冲是一个包含每个片段的z/w值的纹理,其中:

  • Z is the distance from the near clipping plane to the fragment.
  • Z是距离近剪切面到碎片的距离。
  • W is the distance from the camera to the fragment.
  • W是距离摄像机到碎片的距离。

In the following diagram illustrating the relationship between z, w, and z/w, n is equal to the zNear parameter passed to gluPerspective, or an equivalent function, and f is equal to the zFar parameter passed to the same function.

下图说明了z、w和z/w之间的关系,n等于传递给gluPerspective的zNear参数,或等效函数,f等于传递给相同函数的zFar参数。

为什么我要在OpenGL的透视投影中除以W ?

At a glance, this system look unintuitive. But as a result, z/w is always a floating-point value between 0 and 1 (0/n and f/f), and can therefore be represented as a single channel of a texture.

乍一看,这个系统看起来不太直观。但是,z/w始终是0到1 (0/n和f/f)之间的浮点值,因此可以表示为纹理的单个通道。

A second important note: the depth buffer is nonlinear, meaning an object exactly in between the near and far clipping planes is nowhere near a value of 0.5 in the depth buffer. As shown above, it would correlate to a value of 0.999 in the depth buffer. Depending on your view, this could be good or bad; you may want the depth buffer to be more detailed close-up (which it is), or offer even detail throughout (which it doesn't).

另一个重要的注意事项:深度缓冲是非线性的,这意味着在深度缓冲中,近距离和远剪切面之间的距离远小于0.5。如上所示,它与深度缓冲区中的0.999的值相关。根据你的观点,这可能是好是坏;您可能希望深度缓冲是更详细的特写(它是),或者提供更详细的(它没有)。

TL;DR:

TL;博士:

  • You divide z by w so it is always in the range [0, 1].
  • 你把z除以w,所以它总是在范围[0,1]。
  • W is the distance from the camera to the fragment.
  • W是距离摄像机到碎片的距离。