阳光VIP

少壮不努力,老大徒伤悲。平日弗用功,自到临期悔。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

用UBuntu开发OpenGL程序5

Posted on 2012-02-05 12:01  阳光VIP  阅读(174)  评论(0编辑  收藏  举报

本文不少资料来自网络,经过我的整理加工,尽量在一篇文章中讲清楚一小部分程序需要的基本概念,下面是参考列表:
<<OpenGL教程>>
http://old.blog.edu.cn/user1/20928/archives/2007/1863585.shtml
http://blog.163.com/zhaoxin851055@126/blog/static/8112929820092116249704/
http://blog.csdn.net/firefly_liu/archive/2009/05/08/4160296.aspx

glutInitWindowPosition(0, 0);
设置窗口的起始位置,默认值为-1。

glutInitWindowSize(300, 300);
设置初始大小,单位是像素,默认值为300,该参数必须大于0

注意,上面两个函数是建议而不是强迫系统在指定的位置和用指定的尺寸创建窗口。所以,我们需要一种方法去判断真正的窗口位置和尺寸。下面这段话提供了答案:

The intent of the initial window position and size values is to provide a suggestion to the window system for a window's initial size and position. The window system is not obligated to use this information. Therefore, GLUT programs should not assume the window was created at the specified size or position. A GLUT program should use the window's reshape callback to determine the true size of the window.


glutCreateWindow("OpenGL 3D View");
创建顶层窗口,参数是窗口Name.该窗口将成为应用程序的当前窗口。创建成功的窗口显示状态为有效,但是还需要glutDisplayFunc函数才能真正显示出来。
返回>=1的整数,代表该窗口。

glutDisplayFunc(display);
设置绘图的回调函数,glut会自动判断是否需要调用该函数进行重新绘制,也可以通过函数glutPostRedisplay()强制通知glut重绘。


glClearColor(0.0, 0.0, 0.0, 0.0);设置清除色(也就是背景色)
四个参数实际上都是float类型,参数值范围是0和1之间,默认值为0。这个函数不能在glBegin和glEnd之间执行。
第四个参数是Alpha,代表透明度,0是完全透明,1是不透明。

glMatrixMode(GL_PROJECTION);
glOrtho(-5, 5, -5, 5, 5, 15);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
这几个函数涉及到矩阵,三维到二维的变换知识。先介绍一下背景知识,然后再看这几个函数的用法。


    在真实世界里,所有的物体都是三维的。但是,这些三维物体在计算机世界中却必须以二维平面物体的形式表现出来。那么,这些物体是怎样从三维变换到二维的呢?下面我们采用相机(Camera )模拟的方式来讲述这个概念,如图8-1所示。

 

 

实际上,从三维空间到二维平面,就如同用相机拍照一样,通常都要经历以下几个步骤 (括号内表示的是相应的图形学概念):
  第一步,将相机置于三角架上,让它对准三维景物(视点变换,Viewing Transformation )。
  第二步,将三维物体放在适当的位置(模型变换,Modeling Transformation )。
  第三步,选择相机镜头并调焦,使三维物体投影在二维胶片上(投影变换,Projection Transformation )。
  第四步,决定二维像片的大小(视口变换,Viewport Transformation )。
  这样,一个三维空间里的物体就可以用相应的二维平面物体表示了,也就能在二维的电脑屏幕上正确显示了。注意,上图中的投影是透视投影。

 

投影变换 相当于摄像机的调焦,包括正交投影和透视投影,区别在于:
正交投影,摄像机可以位于裁剪体内,也可以在外。所以near和far可以取两个正值或者一正一负。使用函数glOrtho。
透视投影,摄像机不可以位于裁剪体内,所以near和far都必须去正值,使用函数glFrustum。它的参数矩阵定义了裁剪体以及投影的类型,但是未定义摄像机的方位。摄像机位于原点,并面对Z轴的负方向。函数glFrustum只是修改了摄像机的透镜(焦距),并非位置。glFrustum对参数 far和near非常敏感,修改near和far则远景可能就影响很大,所以常用于观察近景。

    真实世界里的物体都有三维坐标,称之为世界坐标系。世界坐标系以屏幕中心为原点(0, 0, 0)。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。计算机屏幕采用一个二维坐标系。将世界坐标系中的物体绘制到屏幕坐标系,需要经过一系列步骤。

 




结合现在的知识,看看下面这段代码:
glMatrixMode(GL_PROJECTION);//glMatrixMode指定后续矩阵操作所使用的matrix stack。
glOrtho(-5, 5, -5, 5, 5, 15);
第一行指定矩阵操作的后续操作为投影变换(PROJECTION)。第二行将摄像机焦距的范围调在左右和下上各5个单位,并且能看到的最近的位置为5单位,最远的位置为15单位。


现在来看看另一个矩阵操作--模型视图(MODELVIEW)
MODELVIEW是在世界坐标系中进行的。在这个坐标系中,可以对观察目标实施平移glTranslatef()、旋转glRotatef()和放大缩小glScalef()。如果观察目标是立方体,其Y轴比例为2.0,其余都为1.0,就是说将立方体变成长方体。
下面这段代码使用了MODELVIEW
glMatrixMode(GL_MODELVIEW);
gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);

gluLookAt是glu库提供的辅助函数,设置视觉坐标系。在实际的编程应用中,用户在完成场景的建模后,往往需要选择一个合适的视角或者不停地变换视角,以对场景作观察。
gluLookAt(
摄像机x,摄像机y,摄像机z,
目标点x,目标点y,目标点z,
摄像机顶朝向x,摄像机顶朝向y,摄像机顶朝向z
)
所以gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0) 让摄像机位于3D茶壶的正前方10单位距离观察。如果将10改为-10,则从3D茶壶的正后方看,下面是两个截图:

 

下面的函数绘制红色茶壶,首先用前面设置的清除色黑色(glClearColor(0.0, 0.0, 0.0, 0.0))清除色彩缓冲区,然后指定绘图颜色为红色,绘制一个相对尺寸为3的茶壶。最后强制渲染引擎绘图。
void display() {
    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0, 0, 0);
    glutWireTeapot(3);

    glFlush();
}

注意glFlush函数返回不代表渲染引擎已经完成渲染(屏幕绘图完成)。


总之,我的正前方有10单位远有一个尺寸为3的红色茶壶(茶壶位于坐标轴中心),我对相机的焦距进行了设置,使它能够看到正前方的一个长方体所包括的空间内的景物:左5单位到右5单位的,下5单位到上5单位,我的正前方5单位到正前方15单位。茶壶刚好在这个范围内,所以,我看到了。


这一章开始涉及OpenGL的一些理论知识,目前还比较粗浅。计划后面章节开始增加矩阵方面的探讨。
欢迎大家提出意见,批评和建议。我写这一系列文章也是摸索着进行,如果有错误,随时修改。我的最终目的是开发一个包装OpenGL的开源C++库,可能需要若干年的时间。目前只打算研究Linux上的OpenGL应用,以后会测试Windows。