对OpenGL转换感到困惑

时间:2012-11-04 20:48:07

标签: opengl

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

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

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

5 个答案:

答案 0 :(得分:7)

  

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

嗯,技术上没有。

  

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

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

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

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

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

在剪辑空间之后,位置得到"标准化"通过它们的同质组件,产生规范化的设备坐标,然后将其明确地映射到视口。

概括说明:

通过

将顶点位置从局部变换到剪辑空间
vpos_eye  = MV · vpos_local
eyespace_calculations(vpos_eye);
vpos_clip =  P · vpos_eye

·: inner product column on row vector

然后到达NDC

vpos_ndc = vpos_clip / vpos_clip.w

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

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

*: vector component wise multiplication

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

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

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


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

  

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

你无法真正辨别出它们之间的关系。通常的方法是将局部对象分为两个步骤:

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

它们一起形成模型视图,在 modelview 矩阵描述的固定函数OpenGL中。现在,因为转换的顺序是

  1. 本地世界, M odel矩阵vpos_world = M · vpos_local
  2. 世界眼, V iew矩阵vpos_eye = V · vpos_world
  3. 我们可以用

    代替
    vpos_eye = V · ( M · vpos_local ) = V · M · vpos_local
    

    M odel V iew矩阵V · M替换=: MV

    vpos_eye = MV · vpos_local
    

    因此,您可以看到,对于矩阵M的V和什么M只是由您乘以模型视图矩阵的运算顺序决定,以及您决定在哪一步"从这里称为模型转换"。

    即。

    之后
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    

    视图已定义。但在某些时候,你将开始应用模型转换,之后的一切都是模型。


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

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

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

答案 1 :(得分:3)

OpenGL是一个低级API,“场景”中没有像“对象”和“相机”这样的高级概念,因此只有两种矩阵模式:MODELVIEW(“相机”的乘法)矩阵通过“对象”转换)和PROJECTION(从世界空间到后透视空间的投影转换)。

“模型”和“视图”(对象和相机)矩阵之间的区别取决于您。 glRotate / glTranslate函数只是将当前选定的矩阵乘以给定的矩阵(甚至不区分ModelView和Projection)。

答案 2 :(得分:1)

这些函数乘以(变换)由glMatrixMode()设置的当前矩阵,因此它取决于您正在处理的矩阵。 OpenGL有4种不同类型的矩阵; GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE和GL_COLOR,这些函数中的任何一个都可以更改任何这些矩阵。所以,基本上,你不会将你操纵不同矩阵的对象转换为“伪造”那种效果。

请注意glulookat()只是一个方便的功能,相当于翻译后跟一些旋转,没什么特别的。

答案 3 :(得分:0)

所有转换都是对象的转换。甚至gluLookAt只是一个变换来转换对象,就好像相机是你告诉它的那样。从技术上讲,它们是顶点上的变换,但这只是语义。

答案 4 :(得分:0)

这是真的,glTranslate,glRotate在渲染之前改变对象坐标,gluLookAt改变了摄像机坐标。