OpenGL笔记

1.库文件:

GLEW是一个跨平台的C++扩展库,基于OpenGL图形接口。GLEW能自动识 别你的平台所支持的全部OpenGL高级扩展涵数。也就是说,只要包含一个glew.h头文件,你就能使用gl,glu,glext,wgl,glx的全 部函数;glu是实用库,封装了OpenGL函数,Glu函数通过调用核心库的函数,为开发者提供相对简单的用法,实现一些较为复杂的操作;glaux是OpenGL辅助库,这部分函数提供窗口管理、输入输出处理以及绘制一些简单三维物体;glut是实用工具库,基本上是用于做窗口界面的,并且是跨平台(所以有时你喜欢做简单的demo的话,可以光用glut就ok了),根据不同平台,GLUT使用glx(X窗口系统)或wgl(Windows)或agl(Macintosh);GLX:OpenGL extension for X.对于X窗口系统,它所使用的的OpenGL扩展(GLX)是作为OpenGL的一个附件提供的,所有的GLX函数都使用前缀glX。

:OpenGL所使用的函数和常量声明。注意:使用glClearColor清除操作的颜色必须指定为RGBA颜色,且每个分量类型必须是GLclampf(float)。同时注意OpenCV的IplImage的图片数据中RGB的存储顺序,默认的是BGRA
:GLU(OpenGL实用库)所使用的函数和常量声明。GLU库属于OpenGL标准的一部分。(以下各种库则不属于)
:GLAUX(OpenGL辅助库)所使用的函数和常量声明。这个库提供了创建窗口,处理键盘和鼠标事件,设置调色板等OpenGL本身不提供,但在编写OpenGL程序时又经常用到的功能。目前这个库已经过时,只有比较少的编译环境中有提供,例如VC系列。在VC系列编译器中,使用这个头文件之前必须使用#include 或者具有类似功能的头文件。
:GLUT(OpenGL实用工具包)所使用的函数和常量声明。这个库的功能大致与GLAUX类似,目前许多OpenGL教程使用这个库来编写演示程序。一些编译系统可能不直接提供这个库(例如VC系列),需要单独下载安装。这个头文件自动包含了,编程时不必再次包含它们。
:扩展头文件。因为微软公司对OpenGL的支持不太积极,VC系列编译器虽然有这个头文件,但是里面只有OpenGL 1.1版本中所规定的内容,而没有OpenGL 1.2及其以后版本。对当前的计算机配置而言,几乎都支持OpenGL 1.4版本,更高的则到1.5, 2.0, 2.1,而VC无法直接使用这些功能。为了解决这一问题,就有了头文件。这个头文件提供了高版本OpenGL所需要的各种常数声明以及函数指针声明。
:扩展头文件。与类似,但这个头文件中只提供适用于Windows系统的各种OpenGL扩展所使用的函数和常量,不适用于其它操作系统。
"glee.h":GLEE开源库的头文件。它的出现是因为虽然可以使用高版本的OpenGL函数,但是使用的形式不太方便。GLEE库则让高版本的OpenGL函数与其它OpenGL函数在使用上同样方便。需要注意的是,这个头文件与是冲突的,在包含"glee.h"之前,不应该包含



2.OpenGL和GLUT坐标系之间的差异

应用程序所使用的坐标系为对象坐标系,对于二维程序,该坐标系x轴正方向水平向右,y轴的正方向竖直向上。但大多数窗口系统所使用的坐标系的y轴正方向都是竖直向下的,GLUT即是这种坐标系,所以如果想使x和y坐标只出现正直,可将坐标系原点设在屏幕的左上角,像素坐标的正方向为向右和向下(x=x'; y= ScreenHighth-y';将坐标点(x',y')平移到左上角)。第二中形式的坐标系是因为CRT显示系统在形成过程中都是安装从上到下,从左到右的顺序,行数和列数都是从左上角算起的。当有鼠标事件时,鼠标返回坐标是在屏幕坐标系中的位置,该坐标系原点就位于左上角(对象坐标(xx,yy),鼠标坐标(x,y),xx=x; yy=creenHighth-y;)用于剪裁窗口和几何对象规格的值是以世界坐标定义的,世界坐标系的原点位于左下角。所以知道屏幕高度对象坐标,鼠标点击坐标(屏幕坐标)之间坐标变换至关重要。

3.OpenGL二维

1.二维取景

实际上OpenGL是在四维空间中工作的,三维空间是四维空间的一个特例,而二维空间是三维空间的一个特例(三维坐标(x,y,z)中z=0)。取景问题中所使用的基本模型称为合成摄像机模型。该模型模拟了形成对象集合的图像的观察者(观测者或摄像师)以及为了生成一副图像我们需要在计算机中完成的工作。二维问题中,该模型如下

可通过指定或计算一个顶点集,在程序中使用一些代码组合——如glBegin(),glVertex*()和glEnd()来定义我们需要的对象。可将代码想象成在一张无限大的纸上来对对象进行描述。取景这一步就是确定这张虚拟纸的那一部分对于合成摄像机模型是可见的,从而可以出现在屏幕中。假设摄像机与x轴和y轴都对齐,则我们只需通过x和y坐标的最大值和最小值来指定一个矩形区域。可使用gluOrtho2D()来完成。该函数指定一个二维矩形剪裁区,左下角坐标(left,bottom),右上角坐标(right,top)。默认剪裁窗口的中心位于对象坐标系的原点。

2.视口

之前都是默认整个屏幕窗口来显示剪裁窗口中的所有对象。我们可通过视口来限制GL仅在屏幕窗口的任一部分进行绘制。视口是屏幕窗口中的一个矩形区域,其尺寸的度量单位为像素。可用glViewport()设置。

4.坐标系与变换

1.坐标系:对象坐标系(object coordinate)或世界坐标系(world coordinate)。对象是在对象坐标系中指定的,并且可以通过坐标变换将其转换至世界坐标系中。在该坐标系中可自由决定选取任何单位,然后在如glVertex*()的GL函数中指定相应单位的数值,可以是以微米、光年等等为单位;第二种坐标系为窗口坐标系或者屏幕坐标系,该坐标系中的度量单位为像素,范围由显示器的属性以及应用程序所选择的显示器中的区域两个因素决定!
GL会自动实现对象到窗口坐标系中的变换,所需要的信息是屏幕中显示窗口的尺寸(由glutInitWindowSize()决定可能根据与用户的交互而改变)以及用户希望显示多大范围的对象空间(gluOrtho2D()由设定)。
2.变换:计算机图像学中,我们只与2类基本几何实体打交道:点(顶点,表示空间中的位置)和方向(或向量)。变换是将顶点和向量映射到另一些顶点和向量。变换方法很多,我们感兴趣的只有一种:它们是否能够保持直线和线段不变。GL所需坐标变换由2个矩阵决定,即模型视图矩阵(model-view matrix)和投影矩阵(projection matrix)。gluOrtho2D用于为二维应用程序指定一个投影矩阵。设置这两种矩阵的步骤:glMatrixMode(GL_PROJECTION);//指定我们希望修改的矩阵;  glLoadIdentity();//将矩阵设置为单位矩阵; gluOrtho2D(-1.0,1.0,-1.0,1.0);//修改当前矩阵为用户所期望的矩阵  以上三步设定了一个二维剪裁窗口使其左下角位于(-1.0,-1.0),右上角位于(1.0,1.0)这些是GL的默认值。注意:如果要以增量式来修改已有矩阵,第二部便不需要。  这些矩阵几乎可在程序的任何部分进行修改。没有用户交互的情况下,可在程序的初始化阶段一次性设置好。程序修改模型视图矩阵的概率总是大于修改投影矩阵,因为摄像机(或观察者)的位置一般很少会修改,修改的一般都是对象的位置。
3.双缓存:大多数图形显示设备工作时都以固定频率进行重绘或刷新。该过程要求显示硬件获取颜色缓存中的内容,并用这些值来决定屏幕上的图形窗口的颜色。对于应用程序来说,屏幕的刷新过程是不可控制的,实际上,二者是不同步(或异步)。所以,用户程序在为颜色缓存创建新值的同时,显示过程取出这些值并加以显示。用于显示的值是多次执行显示回调函数后形成的一些颜色值的组合。使用两个颜色缓存——前台缓存和后台缓存,前台缓存是显示硬件所显示的内容,而后台缓存则是应用程序进行绘制的地方。在后台缓存中绘制一个完整的正方形后,我们所要做的仅仅是交换这两个缓存中的内容。在显示回调函数中用glutSwapBuffer()取代函数glFlush()。因为交换过程中涉及与窗口系统的交互,我们必须在初始化阶段请求双缓存模式,因为在默认情况下显示模式为单缓存。设定双缓存:glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

5.GL三维

1.摄像机与对象:合成摄像机模型可模拟显示世界中成像系统(如摄像机和人的视觉系统)的功能。无论观察者的主体是摄像机还是我们的视觉系统,合成摄像机模型都是建立在为形成图像所做观察的基础上。所以需要有两个独立的实体:一个几何对象集以及这些对象的观察者。每个实体都可彼此独立地进行指定。
摄像机和几何对象集(本身是三维对象)所生成的是二维的。将对象的规格和摄像机整合的过程称为投影,GL内部完成,所以应用程序只需要指定摄像机和场景中的对象。投影线穿过图像中的每一点,并经过摄像机的光心(投影中心)。经过对象上某一点的投影线与焦平面的焦点即为该点在图像中投影点所在的位置。下图,焦平面被移到了摄像机的前方,避免了由透镜引起的图像倒置。

位于摄像机的焦平面或投影平面中的图像即为我们在屏幕上的所见。


一旦对摄像机指定了位置和朝向,投影过程只需要完成两部分内容。第一:确定那些对象可见或不可见。GL观察函数定义了一个剪裁体(或视域体),以模拟真实摄像机通过透镜所能观察到的空间。现实中我们看到只有那些位于摄像机前方的物体才会被观察到,而无论它们离摄像机有多远。计算机中人为的增加了一个前剪裁面(近剪裁面)和一个后剪裁面(远剪裁面)。所以只能看到有限体积内(视域体,平截头体,剪裁体)的对象。第二:确定位于剪裁体内的对象上的某个特定位置的图像在投影平面中的位置。

2.正交投影:可看作模拟长焦镜头拍摄图片的方式。缺乏立体感,但保持距离和形状。摄像机移动到距离拍摄对象无穷远处,但投影平面在对象附近时,就可以得到正交投影图像。物距无穷大时,所有的投影线都彼此平行,投影中心将被投影方向所取代。此时视域体变为一个直平行六面体(长方体)。用glOrtho设定一个正交投影矩阵,参数必须满足right>left,top>bottom,far>near。gluOrtho2D实际上是通过glOrtho函数中near和far参数分别设为-1和+1得出。
3.摄像机的定位:之前所存在的问题是,摄像机只朝向物体的一个面,我们只能看到物体的一个面。所以必须通过移动摄像机或被观察者对象。GL中,相对一个固定摄像机移动物体或固定物体移动摄像机可以生成完全相同的图像。给定视点(或观察点),将立方体旋转,并使其偏离原点。可有三种方式实现这一过程,第一种:计算立方体各顶点的新位置。但是,我们使用的立方体来自GLUT,所以无法直接访问这些顶点。第二种:使用变换。可将立方体旋转,并将其平移到所期望的新位置上。但是,为形成所期望的视图的参数计算涉及太多技巧。因此,可使用第三种:GL提供的gluLookAt函数,可决定摄像机的位置(eye point视点)并通过该摄像机所指向的点来指定其朝向,方向向量来指定期望的up方向。

4.透视投影:glFrustum()有立体感,近大远小。  注意:切记用于观察者的参数都是在摄像机坐标系中定义的。参数near和far分别是摄像机到剪裁平面的距离。对于透视投影,应有far>near>0。该函数计算所得矩阵将作用于当前矩阵(右乘)。必须首先保证矩阵模式已经正确选择,通常会从一个单位矩阵开始。glMatrixMode(GL_PROJECTION);  glLoadIdentity(); gluFrustum(left, right, bottom, top, near, far);  不管是透视投影还是正交投影,都未定义摄像机的方位,GL中摄像机位于原点,并指向z轴的负方向。glFrustum修改了观察条件等价于改变了摄像机的透镜。为了改变位置或朝向,必须借助模型视图矩阵相对于摄像机移动场景中的对象,或通过GL变换,或者通过使用gluLookAt()。
广角视图:gluPerspective更自然(接近与我们使用真实摄像机的方式)的接口。在希望通过一个固定摄像机看到更多的对象时,我们会选择对透镜进行调整以获得该视图。注意:近剪裁面与摄像机距离过近(观察者想看非常靠近摄像机的物体)时,将为透视投影中的深度计算带来数值误差。与glFrustum相比缺乏通用性。

注意:GL变换应用的次序与其在程序中出现的次序相反。换而言之,最后指定的变换将先得到应用。因为每次GL定义的变换都是自右乘作用于当前矩阵的。顶点和模型视图矩阵通过右乘进行运算,所以从数学上看到最后的矩阵将首先得到应用。
所以,绕着任意固定点旋转,一个不动点而非原点的旋转。我们是希望绕着方向(dx,dy,dz)旋转,而使得旋转不动点为(xf,yf,zf),可
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(xf, yf, zf);
glRotatef(angle, dx, dy, dz);
glTranslatef(-xf, -yf, -zf);

视口变换在投影变换之后

投影变换:

OpenGL笔记_第1张图片

视口变换:

OpenGL笔记_第2张图片



你可能感兴趣的:(OpenGL)