【问题标题】:Perspective divide: Why use the w component?透视划分:为什么要使用 w 组件?
【发布时间】:2015-07-29 07:21:21
【问题描述】:

在 OpenGL 中,我读过一个顶点应该用 (x,y,z,w) 表示,其中 w = z。这是为了启用透视分割,其中 (x,y,z) 除以 w 以确定它们的屏幕位置,因为透视效果。如果它们只是除以原始 z 值,那么 z 在任何地方都是 1。

我的问题是:为什么需要将 z 分量除以 w?为什么不能只将x和y分量除以z,使屏幕坐标具有透视效果,然后只使用原始未修改的z分量进行深度测试?这样一来,你就根本不用使用 w 组件了....

显然我错过了什么!

【问题讨论】:

  • 我认为Z轴也需要分割才能正确进行坐标插值。
  • 因为透视变换不是这样工作的。也许你应该看看这个:songho.ca/opengl/gl_projectionmatrix.html
  • 你应该阅读更多关于这个主题的材料——Transform,例如“OpenGLSuperBible”的第 4 章。只要你理解了这些空间和它们对应的变换之间的关系,你就会清楚地了解 w 组件是如何工作的。

标签: opengl graphics glsl


【解决方案1】:

3D 计算机图形通常使用homogeneous coordinatesprojective vector space 处理。这背后的数学原理不仅仅是“除以 w”。

使用 4D 齐次向量和 4x4 矩阵具有很好的优势,即各种仿射变换(尤其包括平移,它也依赖于 w)和投影变换可以用简单的矩阵乘法表示。

在 OpenGL 中,我读过一个顶点应该由 (x, y, z, w),其中 w = z。

那不是真的。一个顶点应该用 (x, y, z, w) 表示,其中 w 就是 w。在您的典型情况下,输入 w 实际上是 1,因此它通常不存储在顶点数据中,而是在着色器等中按需添加。

您的典型投影矩阵将设置为w_clip = -z_eye。但那是另一回事。这意味着您只是在眼睛空间中沿-z 方向投影。您也可以将w_clip=2 *x_eye -3*y_eye + 4 * z_eye 放在那里,您的投影轴将具有方向 (2, -3, 4, 0)。

我的问题是:为什么需要将 z 分量除以 w?为什么不能只将x和y分量除以z,使屏幕坐标具有透视效果,然后直接使用原始未修改的z分量进行深度测试?

从概念上讲,空间在所有 3 个维度上都是扭曲的,而不仅仅是 x 和 y。此外,一开始,GPU 的深度缓冲区只有 16 位或 24 位 整数 精度。在这种情况下,您肯定希望在相机附近有一个更密集的表示,而在远处有一个稀疏的表示。

如今,通过可编程顶点着色器和浮点深度缓冲区格式,您基本上可以将z_eye 值存储在深度缓冲区中,并将其用于深度测试。但是,这通常称为W buffering,因为使用了(剪辑空间)w 组件。

如果你除以 z,还有另一个概念问题:你不能使用正交投影,你总是会强制使用某种透视。现在有人可能会争辩说,除以 z 不必自动发生,但可以在需要时在顶点着色器中应用它。但这也行不通。您不能在顶点着色器中应用透视分割,因为这会将位于相机后面的点投射到相机前面。由于顶点着色器不适用于整个图元,如果至少一个顶点位于相机后面而另一个顶点位于相机前面,这将完全搞砸那里的任何图元。为了处理这种情况,必须在分割之前应用剪辑 - 因此名称为 剪辑空间

通过这种方式,您根本不必使用 w 组件。

这也不对。 w 组件在管道中进一步使用。这对于透视正确的属性插值是必不可少的。

【讨论】:

    猜你喜欢
    • 2013-06-20
    • 2018-03-30
    • 2021-10-06
    • 2014-10-24
    • 2012-05-06
    • 2020-06-13
    • 2017-01-11
    • 2013-07-05
    • 1970-01-01
    相关资源
    最近更新 更多