OpenGL Glut剖析(2)--平行投影及其显示范围
2013-06-15 20:50
706 查看
http://anony3721.blog.163.com/blog/static/51197420114282720194/
OpenGL Glut剖析(2)--平行投影及其显示范围
2011-05-02 22:11:46| 分类: 默认分类 | 标签:opengl |字号 订阅首先强调一个看似废话的概念:OpenGL中无论是平行投影还是透视投影,只有位于视景体中的物体才能被看到,即显示到窗口显示区。
这个概念很基础同样很重要,网上几乎没有人愿意解释此概念。但是初学者的程序出现“黑屏”往往是由于对此概念没有理解。[b]OpenGL提供了两种基本类型的投影,1、透视投影:远大近小;2、正投影(平行投影):不影响相对大小,一般用于建筑和CAD应用程序中。[/b]
(一)glOrtho平行投影下,如何将物体显示在窗口区域上?
glOrtho是创建一个正交平行的视景体。一般用于物体不会因为离屏幕的远近而产生大小的变换的情况。比如,常用的工程中的制图等。这里不讲glOrtho的函数详细说明,用实例说话!不懂的读者请参考我的博客其他文章或自己Google。
1. glOrtho平行投影下,二维物体的显示情况
结论:①平行投影下,要将物体现实在屏幕上只要将物体放置在glOrtho创建的视景体中即可。
②glutInitWindowSize窗口中所现实的仅仅是该平行视景体的成比例缩放的像。也就是说不可能通过改变glutInitWindowSize的尺寸而看到原来看不到的物体。
OpenGL中世界窗口以当前显示窗口中心为原点,水平向右为+x轴,竖直向上为+y轴,垂直于屏幕指向我们为+z轴。长度单位这样来定:平面窗口范围按此单位恰好是左下角(-1,-1) 到右上角(1,1)。OpenGL默认的glOrtho创建的平行视景体就是这种情况。
1)First 程序及运行结果
将下面代码中的橙色部分代码加上对显示结果没有影响,证明OpenGL glut中的默认平行投影视景体是个(-1,-1,-1)到(1,1,1)的立方体。
#include <GL/glut.h> void display(void) { glClear (GL_COLOR_BUFFER_BIT); /* clear all pixels */ glColor3f (1.0, 1.0, 1.0); //设置当前绘制颜色 //glTranslated(0,0,-1.1); // 物体位于视景体之外,黑屏 glTranslated(0,0,-1.0); // 可以看到右上角的白色正方形 //glTranslated(0,0,1.0); // 可以看到右上角的白色正方形 //glTranslated(0,0,1.1); //物体位于视景体之外,黑屏 glRectf(0.25f, 0.25f, 0.75f, 0.75f); //可以看出位于视景体内 //glRectf(1.25f, 1.25f, 1.75f, 1.75f); // 位于视景体外,所以显示不出来 glFlush (); //don't wait! start processing buffered OpenGL routines } void init (void) { glClearColor (0.0, 0.0, 0.0, 0.0); /* select clearing olor */ // glMatrixMode(GL_PROJECTION); /* initialize viewing values */ // glLoadIdentity(); // glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); //注意该视景体的范围和几何中心 } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); //改为glutInitWindowSize (250, 250); 可以看出变换的仅仅是物体按比例大小的变换 glutInitWindowPosition (100, 100); glutCreateWindow ("First"); init (); glutDisplayFunc(display); glutMainLoop(); return 0; }
2)Second 程序及运行结果
#include <GL/glut.h> void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); /* select clearing color */ glMatrixMode(GL_PROJECTION); /* initialize viewing values */ glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); //与上面1)的First的glOrtho 对比可以看出视景体的范围和几何中心对绘图结果的影响 } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glRectf(0.25f, 0.25f, 0.75f, 0.75f); //注意正方形的几何中心在(0.5,0.5) glFlush(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250); //glutInitWindowSize (500, 500); //可以看出物体的比例没变,仅仅是大小的改变 glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
2. glOrtho平行投影下,三维物体的显示情况
1) 半径为1的球体默认的显示
将下面代码中的橙色部分代码加上对显示结果没有影响,证明OpenGL glut中的默认投影是个平行投影,并且平行投影视景体是个(-1,-1,-1)到(1,1,1)的立方体。
#include <GL/glut.h> void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); // glMatrixMode(GL_PROJECTION); /* initialize viewing values */ // glLoadIdentity(); // glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); //注意该视景体的范围和几何中心 } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glTranslatef(0,0,-1.0); //向-z方向移动1个单位后,球显示的尺寸没变,因球心移到视景体的后平面 //glTranslatef(0,0,-1.5); // 为什么球变小了,球心移动到视景体之外,看到的是被视景体后平面截取的部分 //glTranslatef(0,0,-2); //黑屏,此时球与平行视景体的后面相切 //glTranslatef(0,0,1); //此时球心位于平行视景体的"前面" //glTranslatef(0,0,1.5); //此时球心位于平行视景体的"前面",结果与glTranslatef(0,0,-1.5)相同 //glTranslatef(0,0,2); //黑屏,此时球与平行视景体的前面相切 glutSolidSphere(1.0, 20, 16); //半径为1的球体 glFlush(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); //换成glutInitWindowSize(300, 300);对比下结果 glutInitWindowPosition(100, 100); glutCreateWindow("a 3D Shpere with radius = 1"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
//由上图物体的显示可以看出,视景体的大小和中心位置。
glutSolidSphere是GLUT工具包中的一个函数 该函数用于渲染一个球体。球体球心位于原点。在OpenGL中默认的原点就是窗口客户区的中心。 函数原型 void glutSolidSphere(GLdouble radius , GLint slices , GLint stacks); void glutWireSphere(GLdouble radius, GLint slices, GLint stacks ); radius 球体的半径 slices 围绕在Z轴周围的细小部分的数量(类似于地球上经线把地球表面分成的一块块“细小部分”) stacks 沿y轴分布的细小部分的数量(类似于纬线) 一般而言, 后两个参数赋予较大的值, 渲染花费的时间要长, 效果更逼真。
2) glOrtho设置平行视景体的范围和大小对物体显示的影响-----视景体的范围在(-1,-1,-1)~(1,1,1)
#include <GL/glut.h> void init(void) { glClear (GL_COLOR_BUFFER_BIT);// glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); /* initialize viewing values */ glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, -1.0, -1.0, 1.0); //注意y的范围应该是bottom < top,这里说明bottom和top都用的绝对值 } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /*注意该视景体的范围和几何中心 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); // in the first quadrant glOrtho(-1.0, 0.0, 0.0, 1.0, -1.0, 1.0); // in the second quadrant glOrtho(-1.0, 0.0, -1.0, 0.0, -1.0, 1.0); // in the third quadrant glOrtho(0.0, 1.0, -1.0, 0.0, -1.0, 1.0); // in the fourth quadrant glOrtho(0.0, 1.0, 0.0, -1.0, -1.0, 1.0); //注意y的范围应该是bottom < top,这里说明bottom和top都用的绝对值 */ glutSolidSphere(1.0, 20, 16); // glFlush(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("a 3D Shpere with radius = 1"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
3)视景体的范围对物体显示的影响---------视景体的范围超出(-1,-1,-1)~(1,1,1)
#include <GL/glut.h> void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); /* initialize viewing values */ glLoadIdentity(); glOrtho(-2.0, 2.0, -2.0, 2.0, -1.0, 1.0); //注意该视景体的范围和几何中心 } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSolidSphere(1.0, 20, 16); //半径为1的球体 glFlush(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); //换成glutInitWindowSize(300, 300);对比下结果 glutInitWindowPosition(100, 100); glutCreateWindow("a 3D Shpere with radius = 1"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
(二)glutInitWindowSize对物体显示的影响
实际上glutInitWindowSize的大小对物体在显示区域中显示的大小是有影响的,如下代码中所示。前边说OpenGL中显示物体仅仅需要将物体放在视景体中是为了让大家抓住主要矛盾。其实物体的最终形状还与显示屏中窗口区域的大小有关。要在一个非正方形的窗口内现实出“正球”此时就涉及到一个纵横比锁定的问题。
1) 纵横比不等于1的窗口下“单位球”的显示
int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 200); glutInitWindowPosition(100, 100); glutCreateWindow("a 3D Shpere with radius = 1"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
2)通过将平行投影视景体的纵横比设置为显示窗口的纵横比来校正窗口的纵横比不为一所带来的影响
#include <GL/glut.h> void init(void) { int aspectRatio; aspectRatio = 500/200; glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); /* initialize viewing values */ glLoadIdentity(); // glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); //注意该视景体的范围和几何中心 glOrtho(-1.0*aspectRatio, 1.0*aspectRatio, -1.0, 1.0, -1.0, 1.0); // w > h } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSolidSphere(1.0, 20, 16); //半径为1的球体 glFlush(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 200); glutInitWindowPosition(100, 100); glutCreateWindow("aspect ration not equal to 1"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
相关文章推荐
- (转)使用OpenGL显示图像(四)运用投影与相机视角
- VS2012下基于Glut OpenGL显示一些立体图形示例程序:
- 深入剖析Java集合框架及其显示应用(上)
- OpenGL: Glut显示立体图形
- OpenGL(二)之使用GLUT进行显示窗口管理
- VS2012下基于Glut OpenGL显示一个窗口
- OpenGL Glut剖析(3)--重绘回调函数的使用
- OpenGL Glut剖析(3)--重绘回调函数的使用
- VS2012下基于Glut OpenGL显示一些立体图形示例程序
- OPENGL 游戏编程 第四章 投影 glut
- VS2012下基于Glut OpenGL显示一些立体图形示例程序:
- 【OpenGL编程指南】之投影和视口变换
- 在VS2010里MFC对话框中使用OpenGL绘图,添加的控件不显示的一种解决方法
- Qt环境下利用OpenGL显示三维模型
- NVIDIA Geforce GT 730 OpenGL 图形显示异常花屏
- 显示字数在指定的范围内,多出来以....显示
- OpenGL中文本的显示
- [ActionScript 3.0] AS3.0 对象在一定范围随机显示不重叠
- php关联数组与索引数组及其显示
- OpenGL学习笔记:Console工程下怎么不显示控制台黑窗口只显示Windows窗口(VS2015)