让我们从基础开始。
通常,您希望通过以下步骤来变换局部三角形顶点:
local-space coords-> world-space coords -> view-space coords -> clip-space coords
在标准 GL 中,前 2 个转换是通过 GL_MODELVIEW_MATRIX 完成的,第三个是通过 GL_PROJECTION_MATRIX 完成的
当我们在homogeneous coordinates 中表示顶点时,对于我们通常想要应用的许多有趣的转换(例如平移、缩放和旋转),这些模型视图转换恰好可以表示为向量矩阵乘法.通常,顶点V = (x, y, z) 在此系统中表示为(x, y, z, 1)。
好的。假设我们想通过平移、旋转、平移来变换顶点 V_local。每个变换都可以表示为一个矩阵*,我们称它们为 T1、R1、T2。
我们想将变换应用到每个顶点:V_view = V_local * T1 * R1 * T2。矩阵乘法是关联的,我们可以一劳永逸地计算M = T1 * R1 * T2。
这样,我们只需将 M 传递给顶点程序,并计算 V_view = V_local * M。最后,典型的顶点着色器将顶点位置乘以单个矩阵。计算一个矩阵的所有工作就是如何将对象从本地空间移动到剪辑空间。
好的...我浏览了一些重要的细节。
首先,到目前为止我所描述的只是真正涵盖了我们通常想要对视图空间进行的转换,而不是剪辑空间。但是,硬件期望顶点着色器的输出位置在那个特殊的剪辑空间中表示。没有重要的数学很难解释剪辑空间坐标,所以我将把它省略,但重要的是,将顶点带到剪辑空间的变换通常可以表示为相同类型的矩阵乘法。这就是旧的 gluPerspective、glFrustum 和 glOrtho 计算的内容。
其次,这是您应用于顶点位置的方法。转换法线的数学有些不同。那是因为您希望法线在变换后保持垂直于表面(作为参考,在一般情况下,它需要乘以模型视图的反转置,但在许多情况下可以简化)
第三,您永远不会将 4-D 坐标发送到顶点着色器。一般来说,你会通过 3-D 的。 OpenGL 会将这些 3-D 坐标(或 2-D,顺便说一句)转换为 4-D 坐标,这样顶点着色器就不必添加额外的坐标。它扩展每个顶点以添加 1 作为w 坐标。
所以...要将所有这些重新组合在一起,对于每个对象,您需要根据要应用于对象的所有变换来计算那些神奇的 M 矩阵。在着色器内部,您必须将每个顶点位置乘以该矩阵并将其传递给顶点着色器位置输出。典型代码或多或少(这是使用旧命名法):
mat4 MVP;
gl_Position=MVP * gl_Vertex;
* 实际矩阵可以在网络上找到,尤其是在每个函数的手册页上:rotate、translate、scale、perspective、ortho