对OpenGL转换感到困惑

use*_*942 1 opengl

在opengl中,有一个带原点的世界坐标系(0,0,0).

让我感到困惑的是像glTranslate,glRotate等所有的转换呢?他们是在世界坐标中移动物体,还是移动相机?如您所知,通过移动物体或相机可以实现相同的移动.

我猜glTranslate,glRotate,更改对象,gluLookAt更改相机?

dat*_*olf 7

在opengl中,有一个带原点的世界坐标系(0,0,0).

嗯,技术上没有.

让我感到困惑的是像glTranslate,glRotate等所有的转换呢?他们是在世界坐标中移动物体,还是移动相机?

都不是.OpenGL不知道对象,OpenGL不知道相机,OpenGL不知道世界.OpenGL所关心的只是基元,点,线或三角形,每个顶点属性,规范化设备坐标(NDC)和NDC映射到的视口.

当您告诉OpenGL绘制基元时,每个顶点都会根据其属性进行处理.位置是属性之一,通常是在本地"对象"坐标系内具有1到4个标量元素的向量.手头的任务是以某种方式将局部顶点位置属性转换为视口上的位置.在现代OpenGL中,这发生在GPU上运行的一个小程序中,称为顶点着色器.顶点着色器可以以任意方式处理位置.但通常的方法是应用一些非奇异的线性变换.

这种变换可以用同质变换矩阵表示.对于3维向量,具有4个元素的向量中的同质表示,其中第4个元素是1.

在计算机图形学中,3倍转换管道已经成为标准的处理方式.首先,将对象局部坐标变换为相对于虚拟"眼睛"的坐标,因此进入眼睛空间.在OpenGL中,这种转换过去被称为模型视图转换.利用眼睛空间中的顶点位置,可以以通用方式表达诸如照明的若干计算,因此这些计算发生在眼睛空间中.接下来,眼睛空间坐标被转换成所谓的剪辑空间.这个变换映射了一些眼睛空间中的体积到具有特定边界的特定体积,几何体被剪切到该体积.由于这种变换有效地应用了投影,因此在OpenGL中这曾被称为投影变换.

在剪辑空间之后,位置通过其同质分量"标准化",产生标准化的设备坐标,然后将其明确地映射到视口.

概括:

顶点位置从局部变换到剪辑空间

vpos_eye  = MV · vpos_local
eyespace_calculations(vpos_eye);
vpos_clip =  P · vpos_eye

·: inner product column on row vector
Run Code Online (Sandbox Code Playgroud)

然后到达NDC

vpos_ndc = vpos_clip / vpos_clip.w
Run Code Online (Sandbox Code Playgroud)

最后到视口(NDC坐标在[-1,1]范围内

vpos_viewport = (vpos_ndc + (1,1,1,1)) * (viewport.width, viewport.height) / 2 + (viewport.x, viewport.y)

*: vector component wise multiplication
Run Code Online (Sandbox Code Playgroud)

OpenGL函数glRotate,glTranslate,glScale,glMatrixMode只是操纵转换矩阵.OpenGL曾经有四个转换矩阵:

  • 模型观察
  • 投影
  • 质地
  • 颜色

可以使用glMatrixMode设置矩阵操作函数作用于哪一个.每个矩阵操纵函数通过将它们描述的变换矩阵乘以选择矩阵从而替换它来组成新矩阵.函数glLoadIdentity用identity替换当前矩阵,glLoadMatrix用用户定义的矩阵替换它,glMultMatrix将用户定义的矩阵乘以它.


那么modelview矩阵如何模拟对象放置和相机.好吧,正如你已经说过的那样

如您所知,通过移动物体或相机可以实现相同的移动.

你无法真正辨别它们.通常的方法是将局部对象分割为眼睛变换分为两个步骤:

  • 对象到世界 - OpenGL称之为"模型转换"
  • World to eye - OpenGL称之为"视图转换"

它们一起形成模型观察,在由所述的固定功能的OpenGL 模型观察矩阵.现在,因为转换的顺序是

  1. 世界本土,M odel矩阵vpos_world = M · vpos_local
  2. 世界眼,V IEW矩阵vpos_eye = V · vpos_world

我们可以替代

vpos_eye = V · ( M · vpos_local ) = V · M · vpos_local
Run Code Online (Sandbox Code Playgroud)

代替V · M中号 Odel等V IEW矩阵=: MV

vpos_eye = MV · vpos_local
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到V和M的什么是复合矩阵M只是由您在模型视图矩阵中相乘的运算顺序决定,并且您决定"从此处称之为模型变换".

就在我之后

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Run Code Online (Sandbox Code Playgroud)

视图已定义.但在某些时候,你将开始应用模型转换和模型后的所有内容.


请注意,在现代OpenGL中,所有矩阵操作函数都已被删除.OpenGL的矩阵堆栈从未完成功能,并且没有严肃的应用程序确实使用它.大多数程序glLoadMatrix都只使用了自己计算的矩阵,并且没有使用OpenGL内置的矩阵管理例程.

自从着色器被引入以来,整个OpenGL矩阵堆栈使用起来很尴尬,说得好听.

判决:如果您打算以现代方式使用OpenGL,请不要使用内置函数.但请记住我写的内容,因为着色器的作用与OpenGL的固定功能管道非常相似.