Perhaps the following illustration showing the relationship between the various spaces will help:
取决于您是否使用固定功能管道(如果您调用glMatrixMode()
,例如),或者使用着色器,操作是相同的 - 只是您是否直接在着色器中编码它们,或者 OpenGL 管道辅助您的工作的问题。
虽然人们不喜欢讨论固定功能管道的问题,但它使对话变得更简单,所以我将从这里开始。
在旧版 OpenGL(即 OpenGL 3.1 之前的版本,或使用兼容性配置文件)中,定义了两个矩阵堆栈:模型视图, and 投影,当应用程序启动时,每个堆栈顶部的矩阵是单位矩阵(对角线上为 1.0,所有其他元素为 0.0)。如果您在该空间中绘制坐标,那么您实际上是在渲染标准化设备坐标(NDC),它会剪掉 X、Y 和 Z 中 [-1,1] 范围之外的任何顶点。视口变换(通过调用设置glViewport()
)是将 NDC 映射到窗口坐标(实际上是视口坐标,但大多数情况下视口和窗口的大小和位置相同),以及深度值深度范围(默认为 [0,1])。
Now, in most applications, the first transformation that's specified is the projection transform, which come in two varieties: orthographic and perspective projections. An orthographic projection preserves angles, and is usually used in scientific and engineering applications, since it doesn't distort the relative lengths of line segments. In legacy OpenGL, orthographic projections are specified by either glOrtho
or gluOrtho2D
. More commonly used are perspective transforms, which mimic how the eye works (i.e., objects far from the eye are smaller than those close), and are specified by either glFrustum
or gluPerspective
. For perspective projections, they defined a viewing frustum, which is a truncated pyramid anchored at the eye's location, which are specified in eye coordinates. In eye coordinates, the "eye" is located at the origin, and looking down the -Z axis. Your near and far clipping planes are specified as distances along the -Z axis. If you render in eye coordinates, any geometry specified between the near and far clipping planes, and inside of the viewing frustum will not be culled, and will be transformed to appear in the viewport. Here's a diagram of a perspective projection, and its relationship to the image plane .
眼睛位于视锥体的顶点。
最后要讨论的转换是模型视图变换,它负责移动坐标系(而不是对象;稍后会详细介绍),以便它们相对于眼睛和视锥体处于良好的位置。常见的建模变换是翻译, scales, 旋转, and shears(OpenGL 没有原生支持)。
一般来说,3D 模型是围绕局部坐标系建模的(例如,指定以原点为中心的球体坐标)。建模变换用于将“当前”坐标系移动到新位置,以便在渲染本地建模对象时,它位于正确的位置。
建模变换和查看变换之间没有数学差异。通常,建模变换用于特定模型并由glPushMatrix()
and glPopMatrix()
操作,通常首先指定查看变换,并影响所有后续建模操作。
现在,如果您正在执行这种现代 OpenGL(核心配置文件版本 3.1 及更高版本),您必须自己逻辑地执行所有这些操作(您可能只指定一个转换,将模型视图和投影转换折叠为单个矩阵乘法) 。矩阵通常指定为着色器uniforms
。没有矩阵堆栈、模型视图和投影转换的分离,并且您需要正确的数学才能模拟管道。 (顺便说一句,透视划分视口变换步骤由 OpenGL 在顶点着色器完成后执行 - 你不需要做数学[你可以,它不会伤害任何东西,除非你未能设置w到 1.0 在你的gl_Position
顶点着色器输出)。