glViewport()函数和glOrtho()函数的理解

   

OpenGL中有两个比较重要的投影变换函数,glViewport和glOrtho.

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():

glOrtho函数只是负责使用什么样的视景体来截取图像,并不负责使用某种规则把图像呈现在屏幕上。

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);

.....

}

另外,关于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 <GL/gl.h>

#include <GL/glu.h>

#include <GL/glut.h>

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()函数的理解的更多相关文章

  1. glViewport()函数和glOrtho()函数的理解(转)

    http://www.cnblogs.com/yxnchinahlj/archive/2010/10/30/1865298.html 在OpenGL中有两个比较重要的投影变换函数,glViewport ...

  2. glViewport()函数和glOrtho()函数的理解(转)

    转:http://www.cnblogs.com/yxnchinahlj/archive/2010/10/30/1865298.html 摘要:glOrtho相当指定图框的大小,由此会使得图框里的图形 ...

  3. 深入理解javascript函数定义与函数作用域

    最近在学习javascript的函数,函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数.本人把思路整理成文章,一是为了加深自己函数的理解,二是给读者提供学习的途径 ...

  4. Lua函数以及闭合函数的理解

    Lua函数以及闭合函数的理解 来源 http://blog.csdn.net/mydad353193052/article/details/48731467 词法域和第一类型 在C/C++,C#或者J ...

  5. typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针

    首先介绍大家比较熟悉的typedef int i;//定义一个整型变量i typedef myInt int: myInt j;//定义一个整型变量j 上面介绍得是我们常用的比较简单的typedef的 ...

  6. 深入理解,函数声明、函数表达式、匿名函数、立即执行函数、window.onload的区别.

    一.函数声明.函数表达式.匿名函数1.函数声明:function fnName () {…};使用function关键字声明一个函数,再指定一个函数名,叫函数声明. 2.函数表达式 var fnNam ...

  7. 理解JavaScript普通函数以及箭头函数里使用的this

    this 普通函数的this 普通函数的this是由动态作用域决定,它总指向于它的直接调用者.具体可以分为以下四项: this总是指向它的直接调用者, 例如 obj.func() ,那么func()里 ...

  8. Python关于函数作为返回值的理解(3分钟就看完了)

    话不多说,直接看例子,上代码: def line_conf(): def line(x): return 2 * x + 1 return line #return a function object ...

  9. Sigmoid函数与Softmax函数的理解

    1. Sigmod 函数 1.1 函数性质以及优点 其实logistic函数也就是经常说的sigmoid函数,它的几何形状也就是一条sigmoid曲线(S型曲线).               其中z ...

随机推荐

  1. 学不懂Netty?看不懂源码?不存在的,这篇文章手把手带你阅读Netty源码!

    阅读这篇文章之前,建议先阅读和这篇文章关联的内容. 1. 详细剖析分布式微服务架构下网络通信的底层实现原理(图解) 2. (年薪60W的技巧)工作了5年,你真的理解Netty以及为什么要用吗?(深度干 ...

  2. Redis基本数据类型底层数据结构

    Redis数据类型底层数据结构 Redis目前基本的数据类型有String.List.Set.ZSet.Hash五种,首先Redis是C语言开发的,所以底层就是用C语言封装数据结构或者C语言本身提供的 ...

  3. 【GS文献】基因组选择在植物分子育种应用的最新综述(2020)

    目录 1. 简介 2. BLUP类模型 3. Bayesian类模型 4. 机器学习 5. GWAS辅助的GS 6. 杂交育种 7. 多性状 8. 长期选择 9. 预测准确性评估 10. GS到植物育 ...

  4. jumpserver——脚本安装

    CentOS Linux release 7.7.1908 (Core) 3.10.0-1062.4.1.el7.x86_64 Initialize(){ yum update -y systemct ...

  5. Linux 软件安装位置选择指南

    Linux 软件安装   Linux 下安装软件不像 Windows 下安装这么简单,Windows 下会自动选择合适安装路径,而 Linux 下安装路径大部分完全由自己决定,我可以将软件安装到任意可 ...

  6. C语言中不用 + 和 - 求两个数之和

    (二)解题 题目大意:不用+或者-实现两个整数的加法 解题思路:不用+或者-,就自然想到位运算,无非就是与或非来实现二进制的加法 首先,我们来看一位二进制的加法和异或运算 A B A&B A^ ...

  7. 零基础学习java------day9------多态,抽象类,接口

    1. 多态 1.1  概述: 某一个事务,在不同环境下表现出来的不同状态 如:中国人可以是人的类型,中国人 p = new  中国人():同时中国人也是人类的一份,也可以把中国人称为人类,人类  d  ...

  8. Shell学习(八)——dd命令

    一.dd命令的解释 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512:c=1:k=1024:w=2 参数注释: 1. ...

  9. Git的使用-一个分支完全替换另一个分支

    之前公司git分支混乱,今天花时间整理了一下,在合并分支的时候遇到一个问题: 一个很久没有拉取远程代码的分支与master分支合并时,出现冲突之外,还会丢失文件,很头疼,然后找到了下面的方法,可以直接 ...

  10. mybatis-插件开发

    在Executor.StatementHandler.parameterHandler.resultSetHandler创建的时候都有一步这样的操作xxxHandler=interceptorChai ...