现代OpenGL+Qt学习笔记之五:OpenGL矩阵变换

现代OpenGL+Qt学习笔记之五:OpenGL矩阵变换

主要内容

   主要是关于OpenGL中的矩阵变换,通过介绍一个点的变换过程,也可以帮助理解OpenGL的管线的执行过程。没有非常详细的数学和几何变换内容的介绍,好在QMatrix4x4已经帮我们实现了所有的矩阵变换功能。

概述

  在OpenGL管线中,顶点位置、法向等几何数据在进行光栅化过程之前会通过顶点操作和图元装配进行变换。在了解这些变换之前,需要先了解几个不同的坐标系统。
几何变换

物体坐标

  所谓物体坐标,就是物体的局部坐标系,在进行变换之前,它具有初始的位置和初始朝向。在OpenGL固定管线中,要对物体进行变换,通常是通过glRotatef()、glTranslatef()和glScalef(),分别实现对物体的旋转、平移和缩放。

视点坐标

  视点坐标时通过模型视图矩阵(GL_MODELVIEW matrix)和物体坐标相乘得到的。即通过模型视图矩阵将物体空间转换到视点空间中。在OpenGL中,模型视图矩阵是模型矩阵(Mode)和视图(View)矩阵的结合( MviewMmodel ),其中模型矩阵是将物体从物体空间变换到世界空间中,而视图矩阵是将世界空间变换到视点空间中。

这里写图片描述

  注意到,在OpenGL中是没有独立的矩阵的,因此为了模拟相机变换。那么场景(三维物体和光照)的变换应该是视图变换的逆变换。换句话说,在OpenGL中定义的相机在视点空间的位置总是在(0, 0, 0),且朝向z轴内部,且不能被改变。关于这部分更加详细的介绍见后文 模型视图矩阵

  为了在变换后能够计算光照等,法向量也需要从物体坐标变换为视点坐标。注意到法向量的变换和物体位置的变换是不同的,不能直接乘以模型视图矩阵,而是要左乘模型视图矩阵的逆的转置矩阵。

这里写图片描述

裁切坐标

  视点坐标再通过投影矩阵(GL_PROJECTION matrix)变换后就得到了裁切坐标。投影矩阵定义了视景体和顶点数据投影的方式(垂直投影或透视投影)。该坐标系叫做裁切坐标的原因是变换后的顶点数据(x, y, z)通过和±w比较后,可能会有部分数据会被裁切。有关这部分更加详细的介绍见后文投影矩阵

投影变换

归一化设备坐标(NDC)

  归一化设备坐标是将裁切坐标除以w后得到的,该过程被称为透视除法(perspective division)。改坐标和窗口坐标或屏幕坐标相似,只是还没有平移和缩放到屏幕像素中。所有3坐标轴上数据范围全部被缩放到-1到1之间。

归一化

窗口坐标(屏幕坐标)

  窗口坐标是由NDC经过视口变换得到的。NDC通过平移和缩放刚好放入到渲染屏幕当中。在OpenGL管线中,窗口坐标随后会被传递到光栅化过程中,成为一个片元。glViewport()函数是用来设置渲染区域的范围的,glDepthRange()可以指定窗口坐标的z值。窗口坐标就是通过上述两个函数提供的数据计算得到的。

glViewport(x, y, w, h); 
glDepthRange(n, f);

透视除法

  视口变换公式可以通过NDC和窗口坐标之间的线性关系得到。
NDC和窗口坐标之间的线性关系

OpenGL变换矩阵

4x4变换矩阵

  如上,OpenGL中的变换矩阵是4x4的,且16个元素的存储顺序是列主序的,Qt中的QMatrix4x4矩阵也是一样。OpenGL中有4种不同类型的矩阵,即模型视图矩阵、投影矩阵、纹理矩阵和颜色矩阵。在固定管线中,通常通过glMatrixMode()函数切换当前的矩阵类型,但是在目前的可编程渲染管线中,矩阵因为都是自己定义并传递给渲染器,所以基本上不存在矩阵类型的切换问题。

模型视图矩阵

  模型视图矩阵是视图矩阵和模型矩阵的结合。要模拟视图(相机)的变换,需要对整个场景进行逆变换。幸运的是,很多库中都有方便的函数接口,实现这样的逆变换。如glu库中的gluLookAt()函数。Qt中的QMatrix4x4::LookAt()函数等。

模型视图矩阵的4列

  如上,将模型视图矩阵分为4列来分别考虑。其中最右边一列是平移变换,其中元素 m15 是齐次坐标,在投影变换中会用到该元素。

  3元集 (m0,m1,m2) , (m4,m5,m6) (m8,m9,m10) 是欧氏变换和仿射变换,如旋转和缩放,注意到这3个3元集分别对应3个相互垂直的坐标轴。
- (m0,m1,m2) : X轴,默认值是 (1,0,0)
- (m4,m5,m6) : Y轴,默认值是 (0,1,0)
- (m8,m9,m10) : Z轴,默认值是 (0,0,1)

  要通过改变矩阵中的元素实现变换需要非常多的线性代数和几何学内容,要介绍和实现起来也需要一定的内容。好在很多矩阵库已经帮我们实现了这些功能,在实际用时,只要调用简单的函数即可。如QMatrix4x4类就是专门为这些变换设计的类,除了前面介绍的LookAt()函数外,还有translate()、rotate()、scale()和perspective()函数等,分别实现平移矩阵、旋转矩阵、缩放矩阵和投影矩阵的构建和变换,还有setToIdentity()可以对矩阵进行单位化。

  还有一点需要注意,在对几何数据进行变换时,通常是左乘一个变换矩阵,而要对一个数据进行多次变换时,其矩阵相乘的顺序是和变换顺序相反的,如要对一个点v先进行 MA 变换,再进行 MB 变换,则最终的变换公式为。

v=MB(MAv)=(MBMA)v.

投影矩阵

  可以这么说,投影矩阵主要功能有两个:一是定义视景体,视景体决定了哪些变换后的几何数据需要被裁切;二是定义了几何数据投影到屏幕中的方式,即正交投影和透视投影,其中透视投影更加接近我们真实的视觉感觉,因此也更加常用。

视景体

  如图是透视投影下的视景体示意图,其中有6个裁切平面,分别是上、下、左、右、远、近、平面,8个视景体中的顶点也如图所示。

  其中远平面的顶点可以通过相似三角形比计算得到,如对于远平面的左边:

远平面左边顶点

  对于正交投影,其相似比是1,因此远平面的上下左右值是和近平面相同的。

纹理矩阵

  在纹理映射之前,纹理坐标(s, t, r, w)会乘以一个纹理矩阵。在默认情况下纹理矩阵是单位矩阵,纹理会直接映射到物体对应的给定的纹理坐标上。通过定义不同的纹理坐标矩阵,可以实现对纹理的滑动、旋转、伸展和褶皱等。

颜色矩阵

  颜色矩阵作用于(r, g, b, a)颜色上,用来实现颜色空间之间的转换,因为不是很常用,我也不太懂。。

小结

  本文主要介绍了OpenGL中的矩阵变换过程,包括各种坐标系统和变换矩阵。本文的内容主要参考自OpenGL Transformation,其中关于矩阵变换的内容的介绍更加具体和详细,注重细节,且还有一个可以下载的示例程序,包括源码。虽然其实现是在固定管线的基础上实现的,但程序仍然值得一读,要想了解更加具体的矩阵变换理论也可以参考该网页。

  有关这部分内容的程序示例,将和后面要介绍的OpenGL光照结合一起介绍,还将在前面固定不动的程序中加入鼠标时间处理功能,实现通过使用鼠标控制物体的旋转和缩放。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值