OpenGL Glut剖析(2)--平行投影及其显示范围

http://anony3721.blog.163.com/blog/static/51197420114282720194/

OpenGL Glut剖析(2)--平行投影及其显示范围  

2011-05-02 22:11:46|  分类: 默认分类 |  标签:opengl  |字号 订阅

首先强调一个看似废话的概念:OpenGL中无论是平行投影还是透视投影,只有位于视景体中的物体才能被看到,即显示到窗口显示区。

这个概念很基础同样很重要,网上几乎没有人愿意解释此概念。但是初学者的程序出现“黑屏”往往是由于对此概念没有理解。OpenGL提供了两种基本类型的投影,1、透视投影:远大近小;2、正投影(平行投影):不影响相对大小,一般用于建筑和CAD应用程序中。

(一)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; 
}

OpenGL Glut剖析(2)--平行投影及其显示范围 - 阿英 - Mr.Right

 

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

OpenGL Glut剖析(2)--平行投影及其显示范围 - 阿英 - Mr.Right

 

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

OpenGL Glut剖析(2)--平行投影及其显示范围 - 阿英 - Mr.Right

 //由上图物体的显示可以看出,视景体的大小和中心位置。

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



OpenGL Glut剖析(2)--平行投影及其显示范围 - 阿英 - Mr.Right

 

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

OpenGL Glut剖析(2)--平行投影及其显示范围 - 阿英 - Mr.Right

(二)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;
}


OpenGL Glut剖析(2)--平行投影及其显示范围 - 阿英 - Mr.Right

 


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 Glut剖析(2)--平行投影及其显示范围 - 阿英 - Mr.Right

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值