glViewport()函数和glOrtho()函数的理解(转)
转:http://www.cnblogs.com/yxnchinahlj/archive/2010/10/30/1865298.html
摘要:glOrtho相当指定图框的大小,由此会使得图框里的图形形状变化,因为如果图框越宽那么图形的宽度越窄。即可认为glOrtho定义的是剪裁面(图框),是从空间无限坐标面截取的一个剪裁面,那么glViewPort也是类似的,只不过是从glOrtho定义的剪裁面中再剪裁一个区域,显示的内容只在这个区域内显示。这里有点不一样的是glViewPort实际上是指定宽口的实际像素宽度高度。(区别,glOrtho指定世界坐标,glViewPort指定像素)(实际上这两个函数都用于平行投影而非透视投影)。
一、gluOtho()
这个函数是定义剪裁面,何谓剪裁面,我这样理解,我们是在一个无限的空间里绘图,因为坐标是 可以随便指定的,随便在哪个坐标绘图,但是我们可以通过定一个剪裁面,也就是说,有一架照相机,尽管沿途风景很多,但是镜头只能拍到一定的范围,这个范围 就是我们的剪裁面,我们能显示的就是这个剪裁面。
二、glViewPort()
这个函数跟上面的相似,但是我们发现上面的指定一个剪裁面后,是在我们定义的窗口的整个窗口中显示我们剪裁出来的面,而这个函数就是为了在一部分中显我们要显示的剪裁面,即,我们先取景(就是用gluOrtho()剪出来那个),然后在我们定义的窗口中选一个区域来显示这个取好的景。
在OpenGL中有两个比较重要的投影变换函数,glViewport和glOrtho。
glOrtho是 创建一个正交平行的视景体。 一般用于物体不会因为离屏幕的远近而产生大小的变换的情况(图形学中的平行投影和透视投影,glFrustum用于透视投影)。比如,常用的工程中的制图等。需要比较精确的显示。 而作为它的对立情况, 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函数的用法。glOrtho函数只是负责使用什么样的视景体来截取图像,并不负责使用某种规则把图像呈现在屏幕上。(这句话不能理解)
glBegin(GL_QUADS);
glColor3f(1, 0, 0);
glVertex3f(-1, 1, 0);
glVertex3f(-1, -1, 0);
glVertex3f(1, -1, 0);
glVertex3f(1, 1, 0);
glEnd();
比如画一个矩形框,然后glOrtho(-2, 2, -2, 2, -10, 10);如图:
然后glOrtho(-2, 2, -3, 3, -10, 10);如图
可以看到他们的不同,实际上它是按等比例的,比如矩形长度是2,但视图窗口是4,所以占1/2。
glViewport主要完成这样的功能。它负责把视景体截取的图像按照怎样的高和宽显示到屏幕上。
比如:如果我们使用glut库建立一个窗体:glutInitWindowSize(500, 500); 然后使用glutReshapeFunc(reshape); reshape代码如下:
void reshape(int width, int height)
{
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glMatrixModel(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);
....
}
这样是可以看到一个正常的球体的。但是,如果我们创建窗体时glutInitWindowSize(800, 500),那么看到的图像就是变形的。上述情况见图。
因为我们是用一个正方形截面的视景体截取的图像,但是拉伸到屏幕上显示的时候,就变成了 glViewport(0, 0, 800, 500);也就是显示屏变宽了, 倒是显示的时候把一个正方形的图像“活生生的给拉宽了”。就会产生变形。这样,就需要我们调整我们的OpenGL显示屏了。我们可以不用800那么宽,因 为我们是用的正方形的视景体,所以虽然窗体是800宽,但是我们只用其中的500就够了。修改一下程序。
void reshape(int width, int height)
{
int dis = width < height ? width : height;
glViewport(0, 0, dis, dis);
glMatrixModel(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);
.....
}
OK。如果你能看明白我写的内容。你可能对glViewport函数有个大致的了解。
不过,我们采用上面的办法,就是只使用了原来屏幕的一部分(宽度从501到800我们没有用来显示图像)。如果我们想用整个OpenGL屏幕显示图像,但是又不使图像变形怎么办?
那就只能修改glOrtho函数了。也就是说,我们使用一个和窗体一样比例的视景体(而不再 是正方形的视景体)来截取图像。例如,对于(800, 500)的窗体,我们使用glOrtho(-1.5 * 800/500, 1.5 * 800/500, -1.5, 1.5, -10, 10),就是截取的时候,我们就使用一个“扁扁”的视景体截取,那么,显示的到OpenGL屏幕时(800, 500),我们只要正常把这个扁扁的截取图像显示(扁扁的截取图像是指整个截取的图像,包括球形四周的黑色部分。 球形还是正常圆形的),就可以了。如:
void reshape(int width , int height)
{
glViewport(width, height); //按照窗体大小制作OpenGL屏幕
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (width <= height)
glOrtho(-1.5, 1.5, -1.5 * (GLfloat)height/(GLfloat)width, 1.5 * (GLfloat)height/(GLfloat)width, -10.0, 10.0);
else
glOrtho(-1.5*(GLfloat)width/(GLfloat)height, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
....
}
另外,关于glViewport()函数,我们还可以用来调整图像的分辨率。例如,保持目前的窗体大小不变,我们如果用这个size来只显示整个物体的一部分,那么图像的分辨率就必然会增大。例如:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(0, 1.5, 0, 1.5 * (GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho(0, 1.5*(GLfloat)w/(GLfloat)h, 0, 1.5, -10.0, 10.0);
}
可以把分辨率扩大4倍。
而如果再修改一下glViewport(0, 0, 2 * (GLsizei)w, 2 * (GLsizei)h); 则可以把分辨率扩大16倍。
完整的测试程序:
#include
#include
#include
void init(void)
{
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess[] = {50.0};
GLfloat light_position[] = {1.0, 1.0f, 1.0, 0.0};
GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidSphere(1.0, 20, 16);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-1.5, 1.5, -1.5 * (GLfloat)h/(GLfloat)w, 1.5 * (GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho(-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
PROJECT(s5)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
ADD_EXECUTABLE(s5 main.cpp)
FIND_PACKAGE(OpenGL)
FIND_PACKAGE(GLUT)
IF(OPENGL_FOUND)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OPENGL_LIBRARIES})
ELSE(OPENGL_FOUND)
MESSAGE(FATAL_ERROR "OpenGL not found")
ENDIF(OPENGL_FOUND)
IF(GLUT_FOUND)
INCLUDE_DIRECTORIES(${GLUT_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${GLUT_LIBRARIES})
ELSE(GLUT_FOUND)
ENDIF(GLUT_FOUND)
glViewport()函数和glOrtho()函数的理解(转)的更多相关文章
- glViewport()函数和glOrtho()函数的理解
glViewport()函数和glOrtho()函数的理解 OpenGL中有两个比较重要的投影变换函数,glViewport和glOrtho. glOrtho是创建一个正交平行的视景体. 一般 ...
- glViewport()函数和glOrtho()函数的理解(转)
http://www.cnblogs.com/yxnchinahlj/archive/2010/10/30/1865298.html 在OpenGL中有两个比较重要的投影变换函数,glViewport ...
- 深入理解javascript函数定义与函数作用域
最近在学习javascript的函数,函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数.本人把思路整理成文章,一是为了加深自己函数的理解,二是给读者提供学习的途径 ...
- Lua函数以及闭合函数的理解
Lua函数以及闭合函数的理解 来源 http://blog.csdn.net/mydad353193052/article/details/48731467 词法域和第一类型 在C/C++,C#或者J ...
- typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针
首先介绍大家比较熟悉的typedef int i;//定义一个整型变量i typedef myInt int: myInt j;//定义一个整型变量j 上面介绍得是我们常用的比较简单的typedef的 ...
- 深入理解,函数声明、函数表达式、匿名函数、立即执行函数、window.onload的区别.
一.函数声明.函数表达式.匿名函数1.函数声明:function fnName () {…};使用function关键字声明一个函数,再指定一个函数名,叫函数声明. 2.函数表达式 var fnNam ...
- 理解JavaScript普通函数以及箭头函数里使用的this
this 普通函数的this 普通函数的this是由动态作用域决定,它总指向于它的直接调用者.具体可以分为以下四项: this总是指向它的直接调用者, 例如 obj.func() ,那么func()里 ...
- Python关于函数作为返回值的理解(3分钟就看完了)
话不多说,直接看例子,上代码: def line_conf(): def line(x): return 2 * x + 1 return line #return a function object ...
- Sigmoid函数与Softmax函数的理解
1. Sigmod 函数 1.1 函数性质以及优点 其实logistic函数也就是经常说的sigmoid函数,它的几何形状也就是一条sigmoid曲线(S型曲线). 其中z ...
随机推荐
- Android Studio中利用JavaDoc生成项目API文档
1. 在Android Studio中的菜单项中点击Generate JavaDoc
- codeforces 204(Div.1 A) Little Elephant and Interval(贪心)
题意: 有一种个位数与最高位数字相等的数字,求在l,r的范围内,这样的数字的个数. 思路: 找下规律就知道当当n>10的时候除去个位以后的答案等于n/10,然后考虑第一个数字是否小于最后一个.小 ...
- 管理voting disks
管理voting disks 一.关于voting disk 的一些必需要知道的东西: 11g 曾经我们能够使用dd 命令来备份voting disk ,可是在11g 以后 oracle 不再支 ...
- kettle转换之多线程
kettle转换之多线程 ETL项目中性能方面的考虑一般是最重要的.特别是所讨论的任务频繁运行,或一些列的任务必须在固定的时间内运行.本文重点介绍利用kettle转换的多线程特性.以优化其性能. ...
- 再说java final变量
http://blog.csdn.net/axman/article/details/1460544 从jdk1.0到今天,JAVA技术经过十余年的发展,技术上已经发生了巨大的变化.但final变量的 ...
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
- 【iOS开发-51】案例学习:动画新写法、删除子视图、视图顺序、延迟方法、button多功能使用方法及icon图标和启动页设置
案例效果: (1)导入所需的素材,然后用storyboard把上半截位置和大小相对固定的东西布局起来.当然,这些控件也要定义成对应地IBOutlet和IBAction方便兴许使用它们. 注意:本案例在 ...
- UITextView的一些技巧
1.在指定位置插入字符串: NSMutableString *TextViewStr=[[NSMutableString alloc] initWithString:TextView.text ...
- PHP部分--图片上传服务器、图片路径存入数据库,并读取
html页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...
- Asp.Net Mvc: 浅析TempData机制
一. Asp.Net Mvc中的TempData 在Asp.Net Mvc框架的ControllerBase中存在一个叫做TempData的Property,它的类型为TempDataDictiona ...