OpenGL ES 2.0坐标系统的含义

3
在OpenGL(我正在使用Android的OpenGL ES 2.0,但现在主要是想了解理论...)3D世界中,坐标实际上代表什么?
比如说,如果我将我的模型矩阵转换为x、y、z,那么模型会去哪里?有多远?一个单位是多少?
此外,如果我从顶点缓冲区对象中显示点,定义每个点具有任意的x、y和z值,范围从(-∞,∞)。当MVP乘以这个位置时,这意味着什么?
2个回答

4
一个3D点(x,y,z)实际上被表示为4D的齐次点(x,y,z,1),因此我们可以使用4x4矩阵来表示所有所需的变换——具体来说,这允许平移和透视投影。
然后使用4x4的模型视图投影(Model-View-Projection,MVP)矩阵将该点转换为(x',y',z',w')。
模型矩阵将点从其局部建模坐标转换到世界坐标。非常有用,可以实例化单个对象的多个版本。
视图矩阵将该点转换为相机坐标系。在这个坐标系中,相机实际上是朝向-z轴方向看。
投影矩阵将该点转换为裁剪坐标,并最终定义特定的投影方式(例如正交或透视)。
MVP矩阵就是这三个矩阵相乘形成的组合变换。
对于处于裁剪坐标中的点而言,如果它投影后位于裁剪空间内,则它才会可见。裁剪空间是一个轴对齐的立方体,其角落点为(-1,-1,-1)和(+1,+1,+1)。通过除以w'来投影点,即(x',y',z',w')映射为(x'/w', y'/w', z'/w')。如果这三个值都在区间[-1,+1]内,则它可见,我们称该点位于标准化设备坐标中。这种除法是透视投影产生透视效果的原因。
有趣的部分在于,裁剪实际上发生在4D中(在进行透视划分之前)。因此,为了使点可见,x'、y'、z'的大小必须小于w'的大小。如果点经过裁剪,则进行透视划分。
最后,一个存活下来的点被映射到实际的设备坐标中,通过视口变换。这里有一个实际的设备坐标(x,y),它是帧缓冲区中的2D地址,而z是深度缓冲区范围内的深度值。然后将该点发送到光栅化器。
总之,OpenGL管道的第一部分如下所示:
  1. 在顶点着色器中,每个顶点 (x,y,z,1) 乘以 MVP 矩阵得到裁剪坐标 (x',y',z',w')。
  2. 顶点被组装成给定的基本图元(例如三角形)。
  3. 基本图元在四维空间中进行剪裁。
  4. 透视除法将点转换为 归一化设备坐标
  5. 视口变换将点映射到设备坐标并发送给光栅化器。

建模变换是仿射变换,可以用如下矩阵表示:

     _       _
    | a b c d |
M = | e f g h |
    | i j k l |
    | 0 0 0 1 |
     -       -

一个点P = (x,y,z,1) 实际上被视为列向量[x y z 1]的转置,并通过右乘P' = M P进行变换(至少在概念上是这样的——硬件可能会转置所有内容,但仍然是同一件事)。通过仿射变换,我可以缩放、旋转、剪切、平移...任何保持平行线的东西。请注意,M的最后一行是恒等的——这很重要,因为我们不希望M干扰w坐标——我们将在投影矩阵中处理它。

请注意,我们可以使用w = 0来表示方向向量(例如,表面法线),这有效地忽略了平移分量。实际上,为了正确地变换表面法线,我们使用M上部3x3矩阵的逆转置所关联的法线矩阵

        _     _  ^ -T
       | a b c |
N =    | e f g |
       | i j k |
        -     -

这样可以保持法线与它们各自平面的正交性。

例如,下面是一个矩阵,它通过s均匀缩放对象,逆时针绕z轴旋转theta,并将结果平移(4,5,6):

  _                                    _
 | s * cos(theta)  -s * sin(theta) 0  4 |
 | s * sin(theta)   s * cos(theta) 0  5 |
 |      0                0         1  6 |
 |      0                0         0  1 |
  -                                    -

视图变换V是一种刚性变换,它只是一个旋转和平移,可以改变坐标系,使摄像机位于原点并“向外看”-z轴。

投影矩阵P在透视投影方面有些奇怪。在这里,我们必须将视锥体扭曲成规范裁剪立方体。这不是一个仿射变换。这就是最终乘以1/w的好处所在。这里使用以下形式的矩阵:

 P = | a 0  0 0  |
     | 0 b  0 0  |
     | 0 0  c d  |
     | 0 0 -1 0  |

请注意,最后一行不是身份矩阵。点 (x,y,z,1) 被映射为 (a*x, b*y, c*z + d, -z)。之后,在透视除法后,得到的结果为:
 (-a*x/z, -b*y/z, -(c*z + d)/z)

注意到除以 -z 的部分吗?这就是透视缩短的来源。因为被裁剪的顶点将会有 z < 0,所以这实际上是一个正除法。

无论如何,我就说到这里了....


2
当您创建一个图形世界,无论是3D还是2D,都需要定义一个在该世界中一致的坐标系统。您定义它的方式并不重要,只要保持一致即可。
这如何应用到OpenGL?
每个3D元素的位置将由其顶点及您对其进行的任何变换(例如缩放、平移等)来定义。例如,如果您正在渲染一个以{2,3,4}为中心、半径为1的球体,则这些信息可以让您知道球体在世界中的位置,以及是否应该渲染它。
在OpenGL中,您定义一个相机,它本质上是用户视口。这个相机位于某个位置,指向某个方向,并以某个角度旋转。此外,相机具有一个投影角度,它通过某个角度接收它所看到的视觉信息(从某种意义上来说,这可以被看作是相机的“镜头”)。
一旦所有世界都存在于相同一致的坐标系统中,您就可以让相机准确地捕捉浮动在您的世界中的3D元素,因为元素的位置和大小相对于相机的位置和属性而言。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接