OpenGl 之学习笔记 glMatrixMode() 函数以及视图相关知识总结
1.glMatrixMode()函数理解
glMatrixMode()函数的参数,这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项(参数)有3种模式: GL_PROJECTION 投影, GL_MODELVIEW 模型视图, GL_TEXTURE 纹理.
如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。这样,接下来的语句可以是跟透视相关的函数,比如glFrustum()或gluPerspective();
在操作投影矩阵以前,需要调用函数:
glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵
然后把矩阵设为单位矩阵:
glLoadIdentity();
然后调用glFrustum()或gluPerspective(),它们生成的矩阵会与当前的矩阵相乘,生成透视的效果;
如果参数是GL_MODELVIEW,这个是对模型视景的操作,接下来的语句描绘一个以模型为基础的适应,这样来设置参数,接下来用到的就是像gluLookAt()这样的函数;
若是GL_TEXTURE,就是对纹理相关进行操作
顺便说下,OpenGL里面的操作,很多是基于对矩阵的操作的,比如位移,旋转,缩放,所以,这里其实说的规范一点就是glMatrixMode是用来指定哪一个矩阵是当前矩阵,而它的参数代表要操作的目标,GL_PROJECTION是对投影矩阵操作,GL_MODELVIEW是对模型视景矩阵操作,GL_TEXTURE是对纹理矩阵进行随后的操作。
切换当前矩阵.
如.要使用透视(3D).那么先要设置透视投影
glMatrixMode(GL_PROJECTION); //切换到投影矩阵.
//...设置透视投影
设置完成后开始画图,需要切换到 模型视图矩阵 才能正确画图.
glMatrixMode(GL_MODELVIEW);
// 画一个物体A (看起来是3D的),
// 如这时候需画一个 2D效果 的 物体A,那么又需要透视投影
glMatrixMode(GL_PROJECTION); //切换到投影矩阵..
// ..设置正交投影
//..设置完成,切换回模型视图矩阵.....
glMatrixMode(GL_MODELVIEW);
// 再画一个物体A (看起来是2D的)
// 如从头到尾都是画3D/2D, 只需初始化时设置一次.
// 如果有交替,那么就需要glMatrixMode() 切换
// 因这样设置很烦人,所以又有glPushMatrix() 保存当前矩阵
视图相关知识
OpenGL中的视图可以利用照相机来进行比拟。产生目标的场景的变过过程类似于相机拍照。此步骤大概分为三个:
1)把相机固定在三角架上,并让它对准场景(视图变换)
2)对场景安排,使得各个物体在招片中的位置是我们所希望的(模型变换)
3)选择照相机的镜头,并调整放大的倍数(投影变换)
4)确定最终照片的大小,放大(视口变换)
完成这些步骤就可以进行场景的绘制了。
在这个过程中,我们可以把场景长中的物体的坐标变换关系表示为如下情况:
物体坐标(顶点)——模型视图矩阵(视觉坐标)——投影矩阵(剪裁坐标)——透视除法(规范化设备坐标)——视口变换(窗口坐标)
视图变换
视图变化相当于对照相机进行操作。首先利用glLoadIdentity()函数对矩阵进行初始化,将当前的矩阵设定为单位矩阵。然后再把它与视图变换矩阵相乘。视图变换矩阵利用函数gluLookAt()函数进行指定。
void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,
GLdouble centerx,GLdouble centery,GLdouble centerz,
GLdouble upx,GLdouble upy,GLdouble upz);
该函数定义一个视图矩阵,并与当前矩阵相乘。
第一组eyex, eyey,eyez 相机在世界坐标的位置
第二组centerx,centery,centerz 相机镜头对准的物体在世界坐标的位置
第三组upx, upy, upz 相机向上的方向在世界坐标中的方向。
通过此函数的设定,能够把相机的位置确定下来。详细的介绍见链接:http://blog.****.net/wangqinghao/article/details/14002077
视图变换函数必须要在调用任何模型变换函数之前调用,以确保首先作用于模型的是模型变换。可以这里利用矩阵的结合性质来理解。
视图变换矩阵A,模型变换矩阵B,视景体的坐标系统矩阵C。(A*B)*C=A*(B*C).
模型变化
有三个函数能够设定模型变换矩阵。glTranslate(),glRotate(),glScale().这些函数通过移动,旋转,拉伸,收缩或者反射对物体进行变换。
glMatrixMode()函数的参数有3种模式: GL_PROJECTION 投影, GL_MODELVIEW 模型视图, GL_TEXTURE 纹理。
GL_PROJECTION 投影:
投影变换:相当于为照相机选择镜头,这种变换的目的是为照相机选择视野(或者视景体)。因此确定哪些物体位于视野之内以及他们能够被看到的程度。投影变换决定了物体如何被投影到屏幕上。有两种投影。透视投影(perspective projection),它使得远处的物体看上去更小一些。透视投影有两个操作函数,glFrustum()或gluPerspective()。
通过它们生成的矩阵与当前的矩阵相乘生成相应的透视效果。
1.glFrustum()
这个函数原型为:
void glFrustum(GLdouble left, GLdouble Right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
创建一个透视型的视景体。其操作是创建一个透视投影的矩阵,并且用这个矩阵乘以当前矩阵。这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的离视点的距离值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值(near/far 必须>0)。
2.gluPerspective()
这个函数原型为:
void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);
创建一个对称的透视型视景体,但它的参数定义于前面的不同,如图。其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在Y-Z平面的角度,范围是[0.0, 180.0],可以理解为眼睛上下睁开的幅度,角度值,值越小,视野范围越狭小(眯眼),值越大,视野范围越宽阔(睁开铜铃般的大眼);参数aspect是投影平面宽度与高度的比率,这个影响到视野的截面有多大;参数Near和Far分别是近远裁剪面到视点(沿Z负轴)的距离,它们总为正值。
以上两个函数缺省时,视点都在原点,视线沿Z轴指向负方向。
另一类投影叫做正投影(orthographic projection),它把物体直接映射到屏幕上而不影响它们的大小。和透视投影不同,正投影的物体的两端的大小没有不同,物体和照相机的距离并不影响它们看上去的大小。这种类型的投影用于建筑蓝图和计算机辅助设计的应用程序。
glOrtho()函数创建一个正交平行的视景体。
glOrtho(left, right, bottom, top, near, far), left表示视景体左面的坐标,right表示右面的坐标,bottom表示下面的,top表示上面的。
关于此函数可以理解为通过设定参数,对视景体进行剪裁。
glOrtho是创建一个正交平行的视景体。 一般用于物体不会因为离屏幕的远近而产生大小的变换的情况。比如,常用的工程中的制图等。需要比较精确的显示。 而作为它的对立情况, glFrustum则产生一个透视投影。这是一种模拟真是生活中,人们视野观测物体的真实情况。例如:观察两条平行的火车到,在过了很远之后,这两条铁轨是会相交于一处的。还有,离眼睛近的物体看起来大一些,远的物体看起来小一些。
glOrtho(left, right, bottom, top, near, far), left表示视景体左面的坐标,right表示右面的坐标,bottom表示下面的,top表示上面的。这个函数简单理解起来,就是一个物体摆在那里,你怎么去截取他。这里,我们先抛开glViewport函数不看。先单独理解glOrtho的功能。 假设有一个球体,半径为1,圆心在(0, 0, 0),那么,我们设定glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽高都是3的框框把这个球体整个都装了进来。 如果设定glOrtho(0.0, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽是1.5, 高是3的框框把整个球体的右面装进来;如果设定glOrtho(0.0, 1.5, 0.0, 1.5, -10, 10);就表示用一个宽和高都是1.5的框框把球体的右上角装了进来。
glOrtho函数只是负责使用什么样的视景体来截取图像,并不负责使用某种规则把图像呈现在屏幕上。
glViewport主要完成这样的功能。它负责把视景体截取的图像按照怎样的高和宽显示到屏幕上。