OpenGL 矩阵变换

转载 2013年12月03日 19:56:20

Overview

几何数据——顶点位置,和标准向量(normal vectors),在OpenGL 管道raterization 处理过程之前可通过顶点操作(Vertex Operation)和基本组合操作改变这些数据。

OpenGL vertex transformation

Object Coordinates

对象的本地坐标系——任何变换之前的最初位置.为了变换(transformation)这些对象,可以调用glRotate(),glTranslatef(),glScalef()这些方法。


Eye Coordinates

使用GL_MODELVIEW矩阵和Object 坐标相乘所得。在OpenGL中用GL_MODELVIEW将对象对象空间(Object Space)变换到视觉空间(eye space)。GL_MODELVIEW

矩阵是模型矩阵(Model Matrix)和视觉矩阵(View Matrix)的组合 (Mview * Mmodel)。其中,Model 变换指的是将Object  Space转换到World Space

(译注:World Space值得是OpenGL中的三维空间),而View 变换是将World space变换到eye space。

OpenGL eye coordinates

注意:在OpenGL中没有单独的camera(view) matrix。因此,为了模拟camera或者view的变换,其中的场景(3D物体和光照)必须通过和view相反的方向变换。也就是说,OpenGL总是将camera定义在(0,0,0)点,并且强制在eye space坐标系的-Z轴方向,而且不能变换。关于GL_MODELVIEW Matrix的详细资料可以查看此处:http://www.songho.ca/opengl/gl_transform.html#modelview


标准向量(Normal vectors)——从对象坐标系(Object coordinates)变换到视觉坐标系(eye coordinates),它是用来计算光照(lighting calculation)的.注意标准向量(Normal vectors)的变换和顶点的不同。其中视觉矩阵(view matrix)是GL_MODELVIEW逆矩阵的转置矩阵和标准向量(Normal vector是)相乘所得,即:

normal vector transformation

更多关于标准向量变换(Normal Vector Transformation)的资料可连接到此处:http://www.songho.ca/opengl/gl_normaltransform.html


剪切面坐标系(Clip Coordinates)

视觉坐标系和GL_PROJECTION矩阵相乘,得到剪切面坐标系。GL_PROJECTION矩阵定义了可视的空间(截头锥体)(译注:关于什么是截头锥体,我还查了下资料,发现它是这个样子的:


,这个就是投影的效果啦)以及顶点数据如何投影到屏幕上(视角或者正交化(orthogonal)),它被称为剪切面坐标系的原因是(x,y,z)变换之后

要和±w比较。更多关于GL_PROJECTION矩阵的资料可见:http://www.songho.ca/opengl/gl_transform.html#projection

OpenGL clip coordinates


标准化设备坐标系(NDC)

将剪切面坐标系除以w所得(关于w的讨论可见此处:,http://www.songho.ca/math/homogeneous/homogeneous.html),它被称为视角除法(perspective division)

.它更像是窗口坐标系,只是还没有转换或者缩小到屏幕像素。其中它取值范围在3个轴向从-1到1标准化了。

OpenGL Normalized Device Coordinates



窗口坐标系(Window Coordinates)/屏幕坐标系(Screen Coordinates)

将标准化设备坐标系(NDC)应用于视口转换。NDC将缩小和平移以便适应屏幕的透视。窗口坐标系最终传递给OpenGL的管道处理变成了fragment。glViewPort()函数

用来定义最终图片映射的投影区域。同样,glDepthRange()用来决定窗口坐标系的z坐标。窗口坐标系由下面两个方法给出的参数计算出来

glViewPort(x,y,w,h);

glDepthRange(n,f);


OpenGL Window Coordinates


视口转换公式很简单,通过NDC和窗口坐标系的线性关系得到:



OpenGL 转换矩阵

OpenGL Transform Matrix


OpenGL使用4x4矩阵变换。注意,这16个元素存储在1D数组中,这些元素按列顺序排列。假如你想以行为顺序排列,你需要转置该矩阵。

OpenGL有4中不用的矩阵:GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE和GL_COLOR.你可以在

代码中使用glMatrixMode()函数改变当前的类型。例如,为了选择GL_MODELVIEW矩阵,可以这样:

glMatrixMode(GL_MODELVIEW);


---------------------------------------------------------------------------------------------------------------------------------------------

Model-View 矩阵(GL_MODELVIEW)

GL_MODELVIEW矩阵在一个矩阵中包含view矩阵和model 矩阵,为了变换view(camera),你需要将整个

场景施以逆变换。gluLookAt()用来设置viewing变换。


最右边的三个矩阵元素 (m12m13m14) 是用作位移变换的。m15元素是齐次坐标。(何为齐次坐标,参见:http://www.songho.ca/math/homogeneous/homogeneous.html),该元素是用来投影变换的。


3个元素集(m0m1m2),(m4, m5, m6)和(m8, m9, m10) 是用作欧拉变换和仿射变换,例如glRotate(),缩放glScalef().

注意这三个元素集实际上指得是3个正交坐标系:

(m0, m1, m2): +X 轴,向左的向量(left vector)(估计是相对屏幕自己来说),默认为(1,0,0)

(m4, m5, m6) :   +Y轴,向上的向量(up vector),默认为(0,1,0)

(m8, m9, m10):  +Z轴,向前的向量,默认为(0,0,1).



Columns of OpenGL ModelView matrix 
4 columns of GL_MODELVIEW matrix

我们能够不使用OpenGL变换函数,直接构造GL_MODELVIEW矩阵。下面有一些有用的代码构建

GL_MODELVIEW矩阵

1. Angles to Axes  

2. Lookat to Axes

3. Matrix4 class

注意,OpenGL在多种变换同时施加到顶点上时以相反的顺序矩阵相乘。例如,假如一个顶点先以MA

 进行变换。OpenGL首先在乘以顶点之前运用MB x MA 。故最后的变换出现在矩阵相乘之前,最先的变换在最后出现。




投影矩阵Projection Matrix(GL_PROJECTION)

GL_PROJECTION矩阵用来定义截锥体。该截锥体决定了那些对象或者对象的哪些部分将会被裁剪掉。同样,它也决定着3D场景怎样投影到屏幕中

(关于怎样构建投影矩阵,请查看

http://www.songho.ca/opengl/gl_projectionmatrix.html


OpenGL提供2个函数用来GL_PROJECTION变换。glFrustum()产生投影视角。glOrtho()产生正交(或者平行)投影。

两个函数都需要6个参数决定6个剪切面:left, right, bottom, top, near, 和far 平面。截锥体的8个顶点如下所示:

OpenGL Perspective Frustum 
OpenGL Perspective Viewing Frustum


远端平面(后面)的顶点能够简单地通过相似三角形的比率计算出来。例如,远端平面的左侧可以如下计算:



对于正交投影,ratio为1,所以远端平面的left,right,bottom和top值都与近端平面的值相同。


同样,你也可以使用gluPerspective()和gluOrtho2D()函数,但是传递更少的参数。gluPerspective()只需要4个参数:视图的垂直区域(vertical field of view(FOV)),

width/height的ratio,还有近端平面和远端平面的距离。下面代码使用gluPerspective()和glFrustum()实现同样的功能:



OpenGL正交的截锥体

OpenGL Orthographic Frustum 
OpenGL Orthographic Frustum


然而,假如你想要一个非对称的视觉空间,你可以直接使用glFrustum()。例如,

假如你想要呈现一个大的场景到2个相邻的屏幕,你可以截断截锥体变成2个不对称的截锥体(左和右)。然后,

呈现每个截锥体场景。

(这句话太不好翻译了,原位如下:

For example, if you want to render a wide scene into 2 adjoining screens, you can break down the frustum into 2 asymmetric frustums (left and right). Then, render the scene with each frustum.


 
An example of an asymmetric frustum


纹理矩阵(GL_TEXTURE)

纹理坐标(s,t,r,q)在任何纹理映射之前乘以GL_TEXTURE矩阵所得,默认是恒等的。所以纹理映射到物体的位置将正好是你赋值给纹理坐标的位置。

通过改变GL_TEXTURE,你可以滑动,旋转,拉伸或者伸缩纹理。



颜色矩阵(GL_COLOR)

颜色部分是通过乘以GL_COLOR矩阵所得。该矩阵用于颜色空间和颜色组件的变换。(原位如下:It can be used for color space conversion and color component swaping)

颜色矩阵并不是通用的,需要GL_ARB_imaging扩展(什么是GL_ARB_imaging扩展?求解)


其他矩阵例子

glPushMatrix()——将当前的矩阵压入矩阵栈

glPopMatrix()——从当前的矩阵栈中弹出当前的矩阵

glLoadIdentity()——设置当前矩阵为等同矩阵

glLoadMatrix{fd}(m)——将当前矩阵替换成矩阵m

glLoadTransposeMatrix{fd}(m)——将当前矩阵换成其转置矩阵

glMultMatrix{fd}(m)——将当前矩阵乘以矩阵m,并且更新当前矩阵

glMultTransposeMatrix{fd}(m)——将当前矩阵乘以其转置矩阵,并且更新当前矩阵

glGetFloatv(GL_MODELVIEW_MATRIX, m) ——将GL_MODELVIEW矩阵的16个值加载到m中


例子1:ModelView Matrix



这个demo应用显示怎样使用glTranslatef()和glRotatef()操作GL_MODELVIEW

下载链接:

matrixModelView.zip:   

http://www.songho.ca/opengl/files/matrixModelView.zip


(OS X 10.6+) matrixModelView_mac.zip:   http://www.songho.ca/opengl/files/matrixModelView_mac.zip

注意所有的OpenGL函数在Mac和Windows下都在ModelGL.h和ModelGL.cpp中实现,在这些包中的这些文件是完全一样的。


该demo应用使用一个定制的4X4类(链接为:http://www.songho.ca/opengl/gl_matrix.html)作为默认的OpenGL矩阵例子,为了指定model和camera变换.

在ModelGL.cpp中有3中矩阵对象:matrixModel,matrixView和matrixModelView.每一种矩阵保存着预先计算好的变换。然后将这些矩阵元素传递给OpenGL的函数——glLoadMatrix().实际的画图程序应该向下面这个样子:



使用OpenGL默认的矩阵函数,相同的代码如下:



投影矩阵例子:



该 demo应用显示了如何使用glFrustum()和glOrtho()函数操作投影变换。

源码和二进制文件下载的链接:

matrixProjection.zip:   

http://www.songho.ca/opengl/files/matrixProjection.zip


matrixProjection_mac.zip(OS X 10.6+):   

http://www.songho.ca/opengl/files/matrixProjection_mac.zip


同样,ModelGL.h和ModelGL.cpp在两者的包中有同样的文件,且所有的OpenGL函数都置于这些文件中。


ModelGL类有一个定制的matrix对象:matrixProjection,两个成员函数:setFrustum()和setOrthoFrustum().

其功能与glFrustum()和glOrtho()函数相同



GL_PROJECTION矩阵构建的16个参数在这可以看到:



http://www.songho.ca/opengl/gl_projectionmatrix.html

OpenGL的矩阵变换详解——有图有真相

OpenGL有个小小的难点,就是矩阵变换的顺序问题。一不小心就会用错,变换后的物体和自己想要的完全不一样。为了自己的理解,也为了帮助别人的理解,我下面对矩阵变换做一个解释。当然,大片大片的文字肯定会让...
  • u013299585
  • u013299585
  • 2017年04月28日 23:22
  • 264

OpenGL ES 矩阵变换及其数学原理

矩阵变换及其数学原理引子推荐这篇文章线性代数的本质,这篇文章挺不错的,揭示了矩阵和向量的内涵。首先概要性的提一下 向量刻画的是线性空间中的对象。 矩阵刻画的是向量在线性空间中的运动(变换,跃迁),相似...
  • cauchyweierstrass
  • cauchyweierstrass
  • 2016年10月24日 10:41
  • 1789

Android OpenGL ES(十四):通用的矩阵变换指令

Android OpenGL ES 对于不同坐标系下坐标变换,大都使用矩阵运算的方法来定义和实现的。这里介绍对应指定的坐标系(比如viewmodel, projection或是viewport) An...
  • jackie03
  • jackie03
  • 2012年02月29日 11:17
  • 4089

opengl 矩阵变换

第四章 矩阵变换    通过前三章的学习,我们知道了如何使用OpenGL在3D空间中绘制基本图元,并把使用图元组成模型。然而,在我们绘制完一个物体或一个场景之后,我们总希望从多个角度观察这个物体,或者...
  • delphiabcd
  • delphiabcd
  • 2008年02月01日 23:48
  • 6014

OpenGL(五) 三维变换之模型视图矩阵

计算机三维图形学中,一个基本的任务是如何描述三维空间中一个物体位置的变化,也就是如何 描述物体的运动。通常情况下,物体位置的变化包含三个基本的变化:平移、旋转和缩放,物体的运动也可以用这三个基本的运动...
  • dcrmg
  • dcrmg
  • 2016年11月08日 23:14
  • 2408

opengl基础知识 关于四个变换的顺序

OpenGL中的gl库是核心库,glu是实用库,glut是实用工具库, gl是核心,glu是对gl的部分封装,glut是OpenGL的跨平台工具库,gl中包含了最基本的3D函数,而glu似乎对gl的...
  • cjneo
  • cjneo
  • 2016年01月12日 15:20
  • 880

OpenGL学习脚印: 投影矩阵和视口变换矩阵(math-projection and viewport matrix)

写在前面 前面几节分别介绍了模型变换,视变换,本节继续学习OpenGL坐标变换过程中的投影变换。这里主要是从数学角度推导投影矩阵。对数学不感兴趣的,可以稍微了解下,或者跳过本节内容。本文主要...
  • ziyuanxiazai123
  • ziyuanxiazai123
  • 2016年06月05日 18:06
  • 13423

opengl 矩阵变换

#include #include #include GLfloat step=0.0,s=0.1; void CALLBACK display(); void CALLBACK dis...
  • u010296979
  • u010296979
  • 2014年08月11日 17:17
  • 833

OPENGL矩阵变换

http://blog.csdn.net/lyx2007825/article/details/8792475 Overview 几何数据——顶点位置,和标准向量(normal vec...
  • u012746763
  • u012746763
  • 2015年05月25日 15:48
  • 447

OpenGL(4)-Opengl矩阵变换

Opengl矩阵变换矩阵变换 Opengl中有很多坐标系,但实际上他们只是思考方式的不同。opengl渲染图形耳朵过程可以和照相机照相的过程类比起来。用照相机照相的过程分为如下几个步骤: 1....
  • youjiaqu
  • youjiaqu
  • 2016年01月05日 14:05
  • 630
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OpenGL 矩阵变换
举报原因:
原因补充:

(最多只允许输入30个字)