OpenGL 需要用到的数学知识:
空间解析几何,矢量代数。
世界坐标系: 有三维 x,y,z 轴,是 右手坐标系。
向量:在一个坐标系中,两个点位置之间的差,可认为是一个有向线段。
矩阵: 由mxn个数排成的m行n列的数表。
对于OpenGL刚入门的朋友,推荐大家看一下以下这些知识:Programming Guide (红宝书). PDF and HTML, 橙宝书 ("OpenGL Shading Language"), 以及 NeHe's OpenGL教程。
OpenGL windows 环境搭载:
在windows开发openGL可以使用vc,也可以用devc++,后者是免费软件。
我们讲一下如何使用devc++。
首先是下载和安装devc++.下载地址: https://sourceforge.net/projects/dev-cpp/files/Sources/Mingw%20sources/binutils-2.15.91-20040904-1-src.tar.gz/download?use_mirror=nchc
安装成功以后,创建一个新工程,工程里面就有一个openGL工程,创建好openGL工程以后,自带了一个openGL的例子。
接下来我们想把《红宝书》的例子放到这个IDE中去编译运行,首先我们去下载源代码,下载地址是: http://www.opengl.org/resources/code/samples/redbook.zip
打开压缩包,看到的是一组exe可执行文件和它们的c源文件,双击exe文件发现并不能正常运行,报告缺少某些dll文件,我们需要 通过源文件来重新编译exe文件。
打开一个源文件,把内容copy到我们工程里面的main.cpp里面,然后编译运行,IDE报link错误,难点在这里了。
工具-->检查更新-->select dev pack server,选择devpaks.org Community Devpaks
点击最下方的Check for updates 按钮,等待加载完成后在groups里面选择openGL,会出现多个插件供你选择安装,因为我们的源代码里面用到了glut,所以我们需要安装这个pakage,我们需要选择openglut就行安装,而不是选择glut,这个依然会在link的时候报错。
安装完成后,工程--》工程属性--》参数,加入库或者对象,选择以后库文件:
Lib/libopengl32.a
Lib/libopenglut.a
Lib/libglu32.a
ok,现在你可以编译和运行openGL例子了!
ps: 如果使用了aux library,一定要把Lib/libaux.a 放在Lib/libopengl32.a 之前。
----OpenGL 红宝书----
----chapter 1 开始-----
1. openGL 是对图形硬件的一组接口,这些接口包含了120个命令。
2. openGL 有客户端和服务端的概念,openGL可以工作在网络环境中,运行程序和发射openGL命令的计算机称作客户端,接受命令并显示图形的计算机称为服务器端,如果只有一台机器,则这台机器既是客户端又是服务器端。
3.openGL被设计为硬件无关,所以它并没有提供跟窗口和用户输入相关的接口。
4. 把图形对象的数学描述和颜色信息转化成屏幕上的像素的过程,称为光栅化。
5. 两个图形有遮挡的情况下,为了提高性能,被遮挡的部分不被画出来。
6. bitplane存储了屏幕像素的颜色信息,或者说某个像素到底有多红。
7. openGL命令习惯于使用后缀表示参数的数量和类型,比如: glColor3f() 表示这个方法有三个参数,而且类型是单精度浮点型;几乎每个命令都有vector版本,即参数是一个vector(数组,序列)。
8. openGL 是个状态机,你对openGL的一次配置都会影响到接下来的绘图工作,比如你设置了颜色,如果在接下来 不显示改变绘图颜色,那么所有图形将使用你之前设置的颜色进行绘图。
9. 有一些库封装了openGL的基本函数,使openGL的使用更方便,如GLU,这个库是跟openGL的实现一起发行的; GLX,这个库是专门用于x windows 系统的;Open Inventor 是一个openGL的面向对象工具箱。
10. 图形编程中,双缓冲技术是常用的一种图形绘图技术,先将图形绘制在内存中,完成以后再投影在到屏幕上,这样不会 因为频繁的屏幕刷新操作引起屏幕闪烁。
11. 要做到动画的产生,需要至少每秒钟在屏幕上顺序显示24帧的图片,在呈现每一张的图片的过程中,我们不要把画的过程呈献给用户,当图片画好以后再投影到屏幕上,而第一张再投影的时候,后台应该在绘制第二张需要投影的图片,这就是双缓冲技术的一个使用。
动画制作过程中遇到的问题:
12. 假如一个机器支持的最高刷新率是60帧每秒,如果你可以在1/60之内把图片绘制完成,那么我们就可以得到最高的刷新率,即每秒60帧,这样的图像看起来也是最流畅的;但是如果我们的图片非常复杂,绘制一张图片需要1/45秒,而且在绘制完成之前是不能投影到屏幕上的,防止用户看到不完整的图片,那我们在只能在两个1/60内显示同一张图片,屏幕的实际帧数就降到了每秒30帧,假如随着程序的执行过程中我们需要绘制越来越复杂的图片,那么每秒显示的帧数可能继续降低,越来越不流畅,甚至画面卡住。
13. 因为画每一张图片的时间是随机的,有可能低于一次刷新也有可能高于一次刷新,所以动画看起来就可能时快时慢,这种情况下最好设置一个更长的刷新周期,让动画播放的慢点。
----chapter 1 结束-----
----chapter 2 开始-----
1. 不管多么复杂的图片都是由最基本的图形组成的,这些基本图形有点、线、二维多边形等。
2. openGL画图过程:清空屏幕、绘制基本几何图形、绘制光栅对象。
3. openGL 默认的是即画即显得模式,当你向发出一个openGL命令时,显示会更新,作为增强,可以维护一个openGL的命令队列。
4. 画图之前一般要先清空屏幕到指定的背景,比如要画word文件清空到白色,要绘制星空的清空到黑色,但是有时候也不需要清空,比如换了一个场景,从室外转到了室内。
5. 很多系统都有很多缓冲作为颜色缓存,这些缓存都需要被实时的更新,最好有一个这样的例程做这些工作。
6. RGBA 颜色: RED , GREEN, BLUE, ALPHA. 范围都是【0,1】闭区间,alpha = 0 完全透明, alpha = 1 完全不透明。
7. 完全的红,绿,蓝混合成白色,一点都没有的混合成黑色,红和绿混合成黄色,红和蓝混合成品红,绿和蓝混合成蓝绿。三个各一半是灰色(介于黑色和白色之间)。
8. 一般情况下,client端会把openGL命令装进一个network package,等这个package满了以后,就可以把它发给server端,然而如果package一直不满,就有可能一直等待下去。这时我们可以使用glFlush(),它命令将不满的package发送出去。
还有一个函数glFinish()执行和glFlush()一样的事情以后,等待server端将图形绘制完毕的消息,这个方法可以用在需要绘制有先后顺序,或者事件需要同步的场合。
9. 如何处理图形建的遮挡,为每个像素设置深度信息,这里使用一个深度缓冲表,当新图形的深度比旧图形的深度浅时,就把那个像素设置成新的,反之抛弃,由于像素被抛弃而不是用来 绘制,可以提高性能。
10. openGL 中的点、线、多边形 和数学中的概念有点不一样,而且知道它们的区别很重要,openGL中的点是有三维的,不过z轴通常被置为0,数学中的点是无穷的小的,在openGL中明显不是,他起码占一个像素,还有可能占更多;数学中的线是无穷细而且在两端无穷眼神的,openGL中指的是有宽度的线段;openGL中的多边形是凸多边形,而且不能有洞,凹多边形可以由凸多边形构成。
11. OpenGL中所有的几何图形都是由顶点组成的。可以使用glVertex*()来指定一个顶点。这个方法的调用应该在glBegin()和glEnd()之间。
12. 在绘制几何图形的时候,告诉openGL你要画什么,然后指定几个顶点, 绘制语句是要区分顺序的,顺序变了,画出的图形可能也就不一样了。
例:绘制圆圈:
#define PI 3.1415926535897;
GLint circle_points = 100;
glBegin(GL_LINE_LOOP);
for (i = 0; i < circle_points; i++) {
angle = 2*PI*i/circle_points;
glVertex2f(cos(angle), sin(angle));
} glEnd();
13. 默认的情况下,点占一个像素,线有一个像素宽,多边形是被填充的。但opengGL提供了定制接口 。
Point Details
你可以使用glPointSize(size)用像素数来指定点的宽度,这里有一个抗锯齿的概念:
如果抗锯齿功能没有开,启, 当一个点的像素数量不是一个整数的时候,系统会自动把这个数量约等于为整数,然后画出一个正方形区域,
这样我们看起来的图像是不平滑的;
如果开启了抗锯齿的功能, 会画出一个圆形的区域,而且这个区域的边缘像素的亮度不是满的,这样可以让图像看起来更平滑,
在这个模式下,非整数宽度是不会被截取为整数的。
不抗锯齿的点的宽度的上限是抗锯齿宽度上限约为整数的值,可以用glGetFloatv(GL_LINE_WIDTH_RANGE)得到抗锯齿点的宽度的上限。
Line Details
线的宽度和点的宽度的概念是相同的,同样要区分抗不抗锯齿,这里需要注意的是线的宽度默认是1个像素宽,在低分率的屏幕上,线的宽度可能比较明显,而高分辨率的屏幕上,一个像素的宽度有可能让你根本看不见那条线,而要实现分辨率无关的线宽,需要把像素的物理宽度计算进来。
待续。。。。。。