OGL glViewport glFrustum gluPerspective gluLookAt glTranslatef glRotatef glScalef感悟

原创 2016年05月31日 10:55:32

通过分析代码可以得到如下感悟:
1.变换顺序:OGL中因为是列主序矩阵,需要左乘下一步变换才得到矩阵变换结果。所以视口变换,投影变换,视图变换,模型变换的顺序进行设置的;所以变换顺序一定要和D3D区分好。
2.变换设置:OGL中是用视图模型矩阵堆栈,投影矩阵堆栈进行变换的,每个矩阵的设置其实包含了生成一个矩阵,以及和当前栈顶矩阵相乘,得到当前变换;所以变换设置glLoadIdentify,glPushMatrix,glPopMatrix很重要。
3.变换细节:Ogl变换和glu变换函数的细节区分,见下面。gluLookAt只是封装了平移旋转变换(OGL可以用本地坐标系思考)封装了下。glFrustum是透视投影,用了近裁剪面的参数。其它细节见代码。变换矩阵函数都是先生成一个矩阵,然后和当前矩阵堆栈栈顶矩阵相乘,作为当前矩阵如果有物体绘制网格就要和当前矩阵相乘作为顶点变换结果。

4.裁剪阶段:裁剪是在4D 坐标系中进行,4D是为了表达更多形式和统一x,y,z方便裁剪透视投影矩阵也是到这里,后面硬件进行透视除法到NDC坐标系(设备坐标系)OGL x在[-1,1], y在[-1,1], z在[-1,1];D3D x在[-1,1], y在[-1,1], z在[0,1]);,虽然硬件裁剪掉了但是也浪费了提交到GPU Vertex, Shader进行的变换消耗和裁剪消耗;所以对于大型场景场景管理渲染技术是很重要的。gluPerspective只是变换到4D空间,硬件会进行裁剪和透视除法到DNC,正交投影直接变换到DNC坐标系中

5.深度缓存存储阶段:在视口变换期间会将NDC坐标中的z坐标存入深度缓存中,OGL中在设备坐标[-1,1]中的z值也要经过glDepthRange(near,far),near默认是0,far默认是1,将其变换到[0,1]放入深度缓存中,用于后面的深度检测剔除背面。

代码实例:


#include <GL/glut.h>
#include <stdlib.h>

void init(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_FLAT);
   GLint modelViewMatrixStacks;
// 32 都是4X4的列式矩阵,视图矩阵可以不用glLoadIdentity ();但一般使用避免窗口变化导致异常。
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &modelViewMatrixStacks);
// 4 一定需要glLoadIdentity (),当需要绘制2D文本时候,可以Push当前Load单位,然后使用2D投影。当投影变换时,很可能需要调整模型视图矩阵得到想要结果。
GLint perspectiveMatrixStacks; glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, &perspectiveMatrixStacks);

}

void display(void)
{
   glClear (GL_COLOR_BUFFER_BIT);
   glColor3f (1.0, 1.0, 1.0);
   //OGL中都是和当前矩阵相乘作为变换矩阵,所以这里要清理下;
   //虽然模型视图矩阵栈中调用gluLookAt会初始化单位矩阵但是屏幕大小改变时候,还是会出现错乱所以视图变换前glLoadIdentity是好习惯。
   //glLoadMatrix指定的矩阵,glMultMatrix是乘以当前矩阵作为结果矩阵;
   //glLoadTransposeMatrix,glMultTransposeMatrix是行主序矩阵类似D3D,转置矩阵刚好把列主序矩阵变换为行主序矩阵。
   glLoadIdentity ();             /* clear the matrix */
           /* viewing transformation  */
   // gluLookAt是将摄像机的平移旋转的逆进行了封装,可以定义自己的视图转换矩阵。
   // 因为OGL是列式矩阵,所以矩阵乘法顺序变反,所以投影变换,视图转换矩阵要在前面设置。左乘下一步变换才得到结果。
   gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
   //glTranslatef( .0, .0f, -5.0f); // 变换坐标系等于相反的方向变换物体,故这里模型和视图变换放到一起
   // glTranslate glRotate glScale生成恰当的矩阵,且调用了glMulteMatrix作为结果;
   // 这些变换矩阵放置到display list中比每帧计算更快
   glRotatef(45, 0, 0, 1); // 绕原点到指定点的直线(指定轴),逆时针旋转45度
   glPushMatrix();
   // 若当前物体点用局部坐标系统刻画那么在局部坐标系中缩放
   // 使用缩放会降低光照计算效率,因为要重新计算物体表面的法向量; 一般不缩放为0而是使用投影矩阵而不是模型视图矩阵(例如平面阴影)
   glScalef (1.0, 2.0, 1.0);      /* modeling transformation */ 
   // OGL的矩阵乘法,默认是列主序矩阵,M[i][j]是i列j行,矩阵乘法是左乘当前矩阵或向量
   glutWireTeapot(1);
   glPopMatrix();
   glTranslatef(-2.0, -2.0f, 0);
   glScalef(-1.0, 2.0, 1.0);
   glutWireTeapot(1);
   glFlush ();
}

void reshape (int w, int h)
{
	// 视口变换,将[-1,-1,-1]->[1,1,1]空间变换到OGL左下角[0,0]右上角[1,1]中
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
   // 透视投影变换到裁剪4D空间(裁剪掉视景体外的),变换到视口变换前硬件会进行透视除法/w,建筑师需要实际大小用gluOrtho2D
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   // glFrustum上的left, right, bottom, top是近裁剪面的坐标参数,zNear,zFar是距离坐标的相反数;该函数会生成透视矩阵且和当前矩阵相乘。
   //glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
   // gluPerspective是glu提供的函数沿x,y轴均是对称的,没有glFrustum灵活,但是更好用。fovy在[0,180]内VR却要360度,aspect是宽比高。
   // zNear,zFar是近截面,远截面距离(视图坐标中的距离);创建透视投影矩阵和乘以当前矩阵,变换到4D裁剪空间中,硬件除以w变换到NDC坐标中。
   gluPerspective(90.0, w / h, 1, 1000.0);
   
   // 在建筑绘图或CAD中需要的2D投影,是一个长方体的左右,上下,前后边界线值;zNear,zFar不需要一定是正数,负数,0都可以但是不要相同。
   // 因为正交投影中生成的正交矩阵,将物体直接变换到NDC 3D坐标系中,不需要到4D裁剪空间中和进行透视除法到3D。
   // gluOrtho2D是glu提供的版本,和glOrtho相比,只是zNear默认指定为-1,zFar默认指定为1.
   //glOrtho(-10.0, 10.0, -10.0, 10.0, 1.5, 20.0);

   // 所有物体变换到NDC坐标后(无论是透视还是正交投影),在OGL中x属于[-1,1],y属于[-1,1],z属于[-1,1]
   // 不在此区间内的物体都会被硬件快速裁剪掉(而不是视锥体中裁剪),D3D中也类似的只是z属于[0,1]。
   // 所以变换和裁剪都是消耗性能的,大场景中需要场景管理技术。
   
   // 切换到模型视图变换
   glMatrixMode (GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize (500, 500); 
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   init ();
   glutDisplayFunc(display); 
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0;
}


版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/blues1021。

(5)gluLookAt、glViewport()、glOrtho和gluPerspective参数分析

记性不好 ,学习opengl的时候,总是忘记视口和投影变换函数配合时需要注意的地方,导致窗口内看不到三维物体。所以写在这以方便提醒自己。 一、 gluLookAt和投影      void...
  • ysu341341
  • ysu341341
  • 2016年08月30日 17:04
  • 355

OpenGL 函数 gluLookAt() glScalef() glTranslatef() glRotatef() glFrustum() glPerspective() 的使用

OpenGL 函数 gluLookAt() glScalef() glTranslatef() glRotatef() glFrustum() glPerspective() 的使用 ...
  • wslidandan
  • wslidandan
  • 2013年12月19日 11:21
  • 508

OpenGL 函数 gluLookAt() glScalef() glTranslatef() glRotatef() glFrustum() glPerspective() 的比较

1.gluLookAt()——视图变换函数 把自己的眼睛当成是照相机,前三个参数表示眼睛的坐标,中间三个参数表示要拍照的物体的中心位置,可以理解成焦点吧, 后三个参数表示头顶的朝向...
  • qq_33663749
  • qq_33663749
  • 2017年03月10日 10:49
  • 117

【读书笔记】gluLookAt和glOrtho,gluPerspective

void gluLookAt (   eyex,   eyey,   eyez,   centerx,   centery,   centerz,   upx,   upy,  upz); void...
  • versuna
  • versuna
  • 2013年03月05日 20:08
  • 2218

opengl之glScalef()函数

glScalef是openGL中的模型缩放函数,就是把当前矩阵与一个表示延各个轴对物体进行拉伸、压缩、反射的矩阵相乘。这个物体的每个点的x,y,z坐标与对应的xyz参数相乘。 先看函数定义 v...
  • code_AC
  • code_AC
  • 2017年03月14日 20:32
  • 742

OpenGL 入门纪录--透视函数glFrustum(), gluPerspective()函数用法和glOrtho()函数用法

在OpenGL中,如果想对模型进行操作,就要对这个模型的状态(当前的矩阵)乘上这个操作对应的一个矩阵. 如果乘以变换矩阵(平移, 缩放, 旋转), 那相乘之后, 模型的位置被变换; 如果乘以投影矩阵...
  • u010579736
  • u010579736
  • 2016年07月11日 15:00
  • 613

glFrustum()和gluPerspective()详解

1、void glFrustum(GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,GLdouble zNear,GLdouble z...
  • bladeandmaster88
  • bladeandmaster88
  • 2017年02月28日 11:56
  • 764

glOrtho,gluOrtho2D,glFrustum,glViewport解释说明

glOrtho glOrtho函数生成矩阵与当前矩阵相乘 void glOrtho(   GLdoubleleft,   GLdoubleright,   GLdoublebottom, ...
  • zhouschina
  • zhouschina
  • 2013年11月28日 21:21
  • 3968

glOrtho,glFrustum,gluPerspective的理解,很清楚

glOrtho:正交投影,摄像机可以位于裁剪体内,所以near和far可以取两个正值或者一正一负          glFrustum:透视投影,摄像机不可以位于裁剪体内,所以near和far都...
  • Tan_HandSome
  • Tan_HandSome
  • 2015年08月06日 19:06
  • 1951

GL学习笔记(2) - 终于搞明白gluPerspective和gluLookAt的关系了(zz)

文章来源:http://cowboy.1988.blog.163.com/blog/static/751057982010101574732212/ 函数原型 gluLookAt(GLdoble ...
  • y601500359
  • y601500359
  • 2014年11月14日 16:41
  • 929
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OGL glViewport glFrustum gluPerspective gluLookAt glTranslatef glRotatef glScalef感悟
举报原因:
原因补充:

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