OpenGL入门学习

来源:互联网 发布:打开淘宝网 编辑:程序博客网 时间:2024/05/21 06:35

OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX更优越的特性。
1、与C语言紧密结合。 
2、强大的可移植性。 
3、高性能的图形渲染。
  总之,OpenGL是一个很NB的图形软件接口。至于究竟有多NB,去看看DOOM3QUAKE4等专业游戏就知道了。

说起编程作图,大概还有很多人想起TC的#include<graphics.h>吧?
但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率、16色来做吗?显然是不行的。

本帖的目的是让大家放弃TC的老旧图形接口,让大家接触一些新事物。

OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX更优越的特性。
1、与C语言紧密结合。
OpenGL命令最初就是用C语言函数来进行描述的,对于学习过C语言的人来讲,OpenGL是容易理解和学习的。如果你曾经接触过TC的graphics.h,你会发现,使用OpenGL作图甚至比TC更加简单。
2、强大的可移植性。
微软的Direct3D虽然也是十分优秀的图形API,但它只用于Windows系统(现在还要加上一个XBOX游戏机)。而OpenGL不仅用于Windows,还可以用于Unix/Linux等其它系统,它甚至在大型计算机、各种专业计算机(如:医疗用显示设备)上都有应用。并且,OpenGL的基本命令都做到了硬件无关,甚至是平台无关。
3、高性能的图形渲染。
OpenGL是一个工业标准,它的技术紧跟时代,现今各个显卡厂家无一不对OpenGL提供强力支持,激烈的竞争中使得OpenGL性能一直领先。
总之,OpenGL是一个很NB的图形软件接口。至于究竟有多NB,去看看DOOM3和QUAKE4等专业游戏就知道了。
OpenGL官方网站(英文)
http://www.opengl.org

下面我将对Windows下的OpenGL编程进行简单介绍。 

学习OpenGL前的准备工作 

第一步,选择一个编译环境
  现在Windows系统的主流编译环境有Visual Studio,Broland C++ Builder,Dev-C++等,它们都是支持OpenGL的。但这里我们选择Visual Studio 2005作为学习OpenGL的环境。 

第二步,安装GLUT工具包
  GLUT不是OpenGL所必须的,但它会给我们的学习带来一定的方便,推荐安装。
Windows环境下的GLUT下载地址:(大小约为150k)
http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip
无法从以上地址下载的话请使用下面的连接:
http://upload.programfan.com/upfile/200607311626279.zip
Windows环境下安装GLUT的步骤:
1、将下载的压缩包解开,将得到5个文件
2、在“我的电脑”中搜索“gl.h”,并找到其所在文件夹(如果是VisualStudio2005,则应该是其安装目录下面的“VC\PlatformSDK\include\gl文件夹”)。把解压得到的glut.h放到这个文件夹。
3、把解压得到的glut.lib和glut32.lib放到静态函数库所在文件夹(如果是VisualStudio2005,则应该是其安装目录下面的“VC\lib”文件夹)。
4、把解压得到的glut.dll和glut32.dll放到操作系统目录下面的system32文件夹内。(典型的位置为:C:\Windows\System32)
第三步,建立一个OpenGL工程
这里以VisualStudio2005为例。
选择File->New->Project,然后选择Win32 Console Application,选择一个名字,然后按OK。
在谈出的对话框左边点Application Settings,找到Empty project并勾上,选择Finish。
然后向该工程添加一个代码文件,取名为“OpenGL.c”,注意用.c来作为文件结尾。
搞定了,就跟平时的工程没什么两样的。 

第一个OpenGL程序

一个简单的OpenGL程序如下:(注意,如果需要编译并运行,需要正确安装GLUT,安装方法如上所述)

#include <GL/glut.h>

void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
glFlush();
}

int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("第一个OpenGL程序");
glutDisplayFunc(&myDisplay);
glutMainLoop();
return 0;
}

该程序的作用是在一个黑色的窗口中央画一个白色的矩形。下面对各行语句进行说明。 

怎么样?代码还不算长吧?

首先,需要包含头文件#include<GL/glut.h>,这是GLUT的头文件。
本来OpenGL程序一般还要包含<GL/gl.h>和<GL/glu.h>,但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含。

然后看main函数。
int main(int argc, char *argv[]),这个是带命令行参数的main函数,各位应该见过吧?没见过的同志们请多翻翻书,等弄明白了再往下看。
注意main函数中的各语句,除了最后的return之外,其余全部以glut开头。这种以glut开头的函数都是GLUT工具包所提供的函数,下面对用到的几个函数进行介绍。
1、glutInit,对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。其格式比较死板,一般照抄这句glutInit(&argc, argv)就可以了。
2、glutInitDisplayMode,设置显示方式,其中GLUT_RGB表示使用RGB颜色,与之对应的还有GLUT_INDEX(表示使用索引颜色)。GLUT_SINGLE表示使用单缓冲,与之对应的还有GLUT_DOUBLE(使用双缓冲)。更多信息,请自己Google。当然以后的教程也会有一些讲解。
3、glutInitWindowPosition,这个简单,设置窗口在屏幕中的位置。
4、glutInitWindowSize,这个也简单,设置窗口的大小。
5、glutCreateWindow,根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口。
6、glutDisplayFunc,设置一个函数,当需要进行画图时,这个函数就会被调用。(这个说法不够准确,但准确的说法可能初学者不太好理解,暂时这样说吧)。
7、glutMainLoop,进行一个消息循环。(这个可能初学者也不太明白,现在只需要知道这个函数可以显示窗口,并且等待窗口关闭后才会返回,这就足够了。)

在glutDisplayFunc函数中,我们设置了“当需要画图时,请调用myDisplay函数”。于是myDisplay函数就用来画图。观察myDisplay中的三个函数调用,发现它们都以gl开头。这种以gl开头的函数都是OpenGL的标准函数,下面对用到的函数进行介绍。
1、glClear,清除。GL_COLOR_BUFFER_BIT表示清除颜色,glClear函数还可以清除其它的东西,但这里不作介绍。
2、glRectf,画一个矩形。四个参数分别表示了位于对角线上的两个点的横、纵坐标。
3、glFlush,保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)。其作用跟fflush(stdout)类似。 

大家可以按照上面的叙述,自己设置编译器,下载GLUT,并亲手编译示例代码。
祝大家成功~

以后有空我会陆续放出后面一点的教程。
声明:我本人也是OpenGL菜鸟,大家可不要指望我可以教大家写个“星际争霸”什么的。当然也欢迎有此能力的朋友能给我们上一上课了。 

关于计算机图形学的学习

一定要记住,不要指望通过一本教材就学会计算机图形学,它比你想象的要复杂的多。

1. 引言 
  计算机图形学是用计算机来画东西的学科,数字图象处理是把外界获得的图象用计算机进行处理的学科。在法国,图形图象是一门课程。 

  如何学习计算机图形学呢?除了计算机图形学的基础知识以外,你还需要有以下的知识,你懂的越多,当然做的越好。 

* 英语, 你一定要把英语学好,如果你想学习计算机图形学的话,尽量看英文的书籍和资料 

* 数学, 计算机图形学里面的数学用的比较多,,我们可以列举一些常用的: 
高等数学,数值分析,微分几何,拓扑,概率, 插值理论,(偏)微分方程… 

* 物理, 如果你要进行基于物理的建模,一些物理理论是要学习的: 
力学(运动学,动力学,流体力学…),光学,有限元… 

* 编程语言: C或C++是计算机图形学最通用的‘普通话’, 

* 数据结构: 你需要数据结构来描述你的图形对象,除了通用的链表、树等数据结构外,图形学还有自己特殊的数据结构 

* 其他类别: 有的时候你需要其他学科的知识,根据你的需要去学习吧 

上面列举的不是你必须学习的东西,而是计算机图形学可能会用到的东西,一定要记住,不要指望通过一本教材就学会计算机图形学,它比你想象的要复杂的多。 

2. 图形学的问题 
  每个学科都有自己学科的特定问题,图形学要解决的是如何画出图来,得到需要的效果,当然这是图形学最大的一个问题。 

  在开始学习计算机图形学的时候,找一本简单的书看,对计算机图形学有个大概的认识,你就可以开始图形学之旅了: 

OpenGL Programming Guide: The Official Guide to Learning OpenGL, Version 1.4, Fourth Edition 
OpenGL SuperBible (3rd Edition) 

是比较好的学习计算机图形学的入门教材,在练中去学,一开始就去啃Foley的Computer Graphics: Principles and Practice, Second Edition in C 不是好主意,会看的一头雾水,一本什么都讲的书的结果往往是什么都没讲清楚。 

  当你把OpenGL的基本内容掌握之后,你对图形学就有了大概的了解了 

那么下面你可以来学习一下计算机图形学的数据结构和算法,下面的书比较适合Joseph O'Rourke 的Computational Geometry in C,书里面有C的源代码,讲述简单,清晰,适合程序员学习 

  总的来说,计算机图形学涉及到2大部分:建模和渲染 

2.1建模 

  你想画一个东西,首先要有它的几何模型,那么这个几何模型从什么地方来呢?下面的书很不错的: 
Gerald Farin 的Curves and Surfaces for CAGD: A Practical Guide 这本书就有一点的难度了,呵呵,要努力看啊 

  这本书算是CAGD (计算机辅助几何设计)的经典图书,CAGD方面的全貌,还有2本很好的讲述曲面的书Bezier和Nurbs的书Les A. Piegl, Wayne Tiller 的The Nurbs Book 书里面有NURBS曲线、曲面的程序伪代码,很容易改成C的,书讲的通俗、易懂,但是你要有耐心看的:) 

曲线与曲面的数学 
  这本书是法国人写的中文翻译版,里面还有Bezie本人写的序J,翻译的很不错的,看了你就掌握Bezier曲面技术了 

//另外一些你想知道的事情:其他的造型方式-开始 
注意:在后面会有这样的章节,标明 
//另外一些你想知道的事情:其他的造型方式-开始 
//另外一些你想知道的事情:其他的造型方式-结束 
里面是我认为的一些高级话题,跳过他们不影响你学习计算机图形学,但是要学好就要注意了,呵呵 
还有其他的一些造型技术,比如: 
隐式曲面(Implicit Surface)的造型: 
就是用函数形式为F( x ,y ,z ) = 0的曲面进行造型,这样的造型技术适合描述动物器官一样的肉乎乎的东西。

有2本书推荐大家 
  Jules Bloomenthal编辑的Introduction to Implicit Surfaces,是一本专著,讲述了Implicit Surface建模型(Modeling),面片化(Polygonization),渲染(Rendering)的问题 

Luiz Velho 的 Implicit Objects Computer Graphics 也是一本专著,讲述个更新的一些进展细分曲面(Subdivision Surface)造型当用NURBS做造型的时候,曲面拼接是复杂的问题,在动画的时候,可能产生撕裂或者褶皱,Subdivision Surface用来解决这个问题 
Joe Warren的Subdivision Methods for Geometric Design: A Constructive Approach就是这方面的专著 

从实际物体中得到造型,现在的技术可以用三维扫描仪得到物体表面的点,然后根据这些点把物体的表面计算出来,称为重建(Reconstruction),因为这些技术之在文章中论述,所以我们省略对它的描述 

//另外一些你想知道的事情:其他的造型方式-结束

下面还是一个高级话题:) 

//另外一些你想知道的事情:光有造型是不够的!-开始在你的几何模型做好之后,有一些问题需要对这个模型进一步处理,得到适合的模型,当面片很多的时候,或者模型很复杂的时候,需要对几何模型进行简化,才可以满足一些实时绘制的需要,这个技术叫做层次细节(LOD-Level of Detail)。下面的书就是讲这个的: 
David Luebke编著的 Level of Detail for 3D Graphics 
//另外一些你想知道的事情:光有造型是不够的!-结束 

2.2渲染 
  有了模型,怎么把这个几何模型画出来呢?这个步骤就是渲染啦 

  如果你看了上面的OpenGL的书,那么你就知道一些渲染的知识了,但是别高兴的太早,OpenGL使用的是局部光照模型(Local Illumination Model),不要被这个词吓住了 

  Local illumination Model指的是在做渲染的时候只考虑光源和物体之间的相互作用,不考虑物体和物体之间的影响,所以OpenGL不支持阴影,一个(半)透明物体的效果..,这些需要考虑物体之间的影响才可以实现。 

//另外一些你想知道的事情:OpenGL可以实现阴影-开始 
OpenGL本身不支持,但是通过一些方法可以实现的:),用Google搜索一下 
Shadow Volume, OpenGL就找到答案啦 
//另外一些你想知道的事情:OpenGL可以实现阴影-结束 

Global Illumination Model 这类模型考虑的就比较全啦。现在关于Global Illumination的技术有3大类,具体的技术就不在这里介绍了,如果想了解,可以联系我,大家一起讨论: 

光线追踪(Ray Tracing) 
关于Ray Tracing的好书有2本: 

Andrew Glassner 的An Introduction to Ray tracing 
Glasser是图形界的名人,这本书也是Ray Tracing的经典 

R. Keith Morley, Peter Shirley 的Realistic Ray Tracing, Second Edition 
这本书第一版是伪代码,第二版是C代码。它的结构不是很清楚,虎头蛇尾的感觉。 

辐射度(Radiosity) 
关于Radiosity的好书有4本: 
Michael Cohen 的Radiosity and Realistic Image Synthesis , Cohen获得SIGGRAPH 1998计算机图形学成就奖,他把Radiosity变成实际可用,现在Cohen在MSR图形http: //research.microsoft.com/~cohen/CohenSmallBW2.jpg 

Francois X. Sillion的Radiosity and Global Illumination , Sillion是法国人,他的主要研究方向是Radiosity,这本书写的很不错的,非常清晰 

Philip Dutre 的新书Advanced Global Illumination ,看起来还不错,刚拿到手,还没看,呵呵,所以不好评价 

Ian Ashdown的Radiosity: A Programmer's Perspective 
有源代码的书啊!! 就凭这个,得给5***** 

Photon mapping 
这个我也不知道怎么翻译,呵呵。这个技术出现的比较晚,一本好书! 
Henrik Wann Jensen的Realistic Image Synthesis Using Photon Mapping 
Henrik Wann Jensen是Photon mapping技术的发明者 

3.3这些也是图形学吗? 图形和图象的区别模糊了:( 
除了上面讲的‘经典’的计算机图形学,还有下面的一些东西,它们也叫计算机图形学吗?是的!!! 
3.3.1非真实性图形学(Non-Photorealistic Graphics) 
真实性不是计算机图形学的唯一要求,比如:你给我画一个卡通效果的图出来,或者我要用计算机画水彩画怎么办?或者:把图象用文字拼出来怎么做?,解决这些问题要用到非真实性图形学, 好书继续推荐!!! 
Bruce Gooch, Amy Ashurst Gooch的 Non-Photorealistic Rendering 

3.3.2体图形学(Volume Graphics) 
用CT机做很多切片(比如头骨),那么能通过这些切片得到3D的头骨吗?Volume Graphics就是解决这样的问题的 
Min Chen 编著的Volume Graphics 

上面的2个图形学技术就和图象的界限不明显了,实际上他们是图形图象的综合
4 .还有其他的书吗? 
还有一些好书啊,呵呵,好书看不完的:),继续放送: 

Graphics Gems I ~ V,一大帮子人写的书,包括研究人员,程序员… 
有计算机图形学的各种数据结构,编程技巧 

Tomas Akenine-Moller 等人编著的Real-Time Rendering (2nd Edition) 
许多最新的计算机图形学进展 

David Ebert等人的Texturing & Modeling: A Procedural Approach, Third Edition 
讲述如何通过程序实现纹理、山、地形等图形学要素 
F. Kenton Musgrave号称分形狂(Fractal Mania) 
Ken Perlin就是Perlin噪声的发明者,用过3d软件的人对Perlin Noise不会陌生的 

关于图形学的特定对象,有特定的专题图书, 
Evan Pipho Focus On 3D Models,对于图形学的常用模型格式,进行了讲解 
Trent Polack的 Focus On 3D Terrain Programming ,讲地形的 
Donald H. House 的Cloth Modeling and Animation ,讲布料的 
Nik Lever的Real-time 3D Character Animation with Visual C++ ,讲角色动画的 
…… 

还有:) 
Richard Parent的 Computer Animation: Algorithms and Techniques,当然是讲动画的啦,呵呵。 
David H. Eberly的3D Game Engine Design : A Practical Approach to Real-Time Computer Graphics ,有代码的啊!呵呵:) 

最后,没事情的时候,看看下面的书吧 
Alan H. Watt, 3D Computer Graphics (3rd Edition) 

James D. Foley等人的 Computer Graphics: Principles and Practice in C (2nd Edition) ,这本圣经没事的时候再看吧,呵呵 

累了:( 不说了,上面的书差不多了,还有一些shader的书,我不了解,以后会补上的:) 

5.从哪里找到这些书啊?还有什么资源啊? 
我保证,上面的书在www.amazon.com 都可以买到:) 别打我

OpenGL学习资源

 来自网络上的推荐,未一一验证,如果网址有任何问题请告诉ITHao.COM,邮箱:ithao123@163.com ,谢谢 

重点推荐:www.opengl.orgopengl的官方网站,内容丰富,学习opengl知识的百宝箱,圣地。

 

重点推荐:http://nehe.gamedev.net/: NeHe网站的opengl教程,讲解的非常详细,非常适合初学者,把上面的教程看完,应该对opengl有初步的认识。

 

http://www.sgi.com/products/software/opengl/sgi公司的opengl主页。

 

http://www.eecs.tulane.edu/Terry/OpenGL/Introduction.html#Introductiontulane大学opengl教程 

 

http://www.rush3d.com/reference/opengl-bluebook-1.0/bk02.html

opengl参考手册(reference manual

 

http://www.xmission.com/~nate/opengl.htmlNate Robin的教程,不同的视角,和演示,比nehe来的直观,适合对opengl的初步了解。

 

http://www.gamedev.net/reference/list.asp?categoryid=31

GameDevopengl主页,有很多技术帖子,相当不错。

 

http://www.mevis.de/opengl/opengl.htmlopengl index 对所有的opengl命令的详细解释。

 

http://www.codecolony.de/opengl.htmcodecolony opengl教程

 

基本上就是这些,初学者把nehe的教程学完,再作深入的学习,是一个不错的选择。

关于怎么学习API (OpenGL/Direct3D-针对初学者

   API是工具,不是本质,OpenGL/Direct3D的本质是图形学,而不是OpenGL/Direct3D的本身,API的本身只是一些Interface而已.

最近很多人在问,我该如何学习OpenGL?我学完了OpenGL了,该怎么用?

   我想在回答这些类似的问题以前先和大家谈谈怎么学习API的方法,或许谈完了,我就不需要回答了。 

   首先,我认为API是工具,不是本质,OpenGL/Direct3D的本质是图形学,而不是OpenGL/Direct3D的本身,API的本身只是一些Interface而已.如果你明白图形学的原理.那么你很容易这些接口的作用,以及为什么要有这些接口的存在.所以,我要说的第一点是:你要学习3D编程,不是学会了OpenGL/Direct3D就可以了。甚至会不会这些API都不是那么的重要(虽然这么说,或许很多人不太赞同).最重要的,最根本的是,你要明白这些API背后的图形学的原理---因为那才是根本中的根本.

   下面我来介绍我对API学习的看法.

   我认为API的学习有两种方法:一是正向学习.二是反向学习.

   一:正向学习,所谓的正向学习,就是学习API的本身.我觉得这种方法是一种Brute Force行为.不是很好.我们只要看看API的特性,有那些部分.就可以了。比如学习Direct3D的时候,我们要知道它如何初始化,以及它和操作系统的结合.它在Direct3D8里引入了VS/PS.最后就是创建一个Direct3D应用的步骤和方法.这些就足够了。要不然.Direct3D那么多的函数,每一个都会要了我的命.

   正向学习的第二个作用就是你在熟悉了图形学和大概了解了API后,有空就来看看API的细节,然后思索一下API里提供的一些特性对你的程序有什么作用.比如Direct3D里的Two Side Stencil.OpenGL里的TextureCombine等。

   二:逆向学习.这是根本的方法,到了这一步,你就可以真正的算是图形学入门了。这要求你要有一定的图形学基础.比如,你现在开始做一个demo.你预计你的demo里有一堆眩眩的效果,当然你也要明白你的这些眩眩的效果要怎么实现的.然后你去找API里对应的功能,我想如果你的想法正常,一般的功能在Direct3D/OpenGL里应该都会有的.当然你也会碰到你想要的功能在这些API里没有,但是这不重要,重要的是你又学到新东西了---这个特性在XX API里不支持^_^.

   通常我是采用先正向,再逆向,同时再进行正向学习的方法.希望以上的建议,对各位初学者有一定的帮助. 

如何建立一支强力的手机游戏开发团队

 如何建立一支强力的手机游戏开发团队的问题:
STEP.1 找一名经验丰富的策划做LEADER;
STEP.2 招聘;
STEP.3 办公室和设备

呵呵,现在有很多公司要开始开发手机游戏,那以下这篇文章值的大家看看,说不定有些益处,我想对从事手机游戏开发行业的人来说,也是一个很好的文章,可以找到自己的定位,这样的公司,这样的团队要什么样的人!(在Baidu里找的)

各位,今天我们来谈谈如何建立一支强力的手机游戏开发团队的问题。 

STEP.1 找一名经验丰富的策划做LEADER 
一般来说,策划在游戏开发团队中的作用很难界定,因为他并不想画图的艺术家或编码的科学家那样有明显的标签,也不像写故事的剧作家那样有明显的工作成果,所以长期以来,在我国的游戏业界很有些人将策划与办公室助理划上等号。其实这种错误是因为对游戏开发工作本身缺乏了解,和我们国家并没有成熟的游戏人才培养氛围,使得大量滥竽充数的伪策划充斥业内,才造成了如今这种劣币淘汰良币的事实。 

一个真正的策划是什么都要通的,市场、技术情报、沟通、美术、音乐、程序、编剧、管理流程、宣传、软硬件器材都要考量,虽然不见得全要精通,但游戏策划事实上相当于一部电影的导演。 

正因为策划的工作范围涉及了如此广泛的方面,所以策划对于聘用什么样的人才最是要心中有数,若非如此,自然不能对游戏开发的各个环节了如指掌,也不能对游戏的质量予以把握,出来的产品会是什么样子,恐怕只有上帝知道。 

同时,为了能彻底的贯彻策划意图,将停留在幻想阶段的策划案变成实实在在的游戏,必须要给予LEADER必要的权力,只有这样才能做到上令下行,才能将游戏在保证质量的前提下制作出来。 

本来很多优秀的策划案就是因为策划的意图不能贯彻执行最终都变成了一纸空谈,这是游戏开发公司必须要重视的问题。 

STEP.2 招聘开始了 
有了一名经验丰富的策划后,不要犹豫,派他去找人吧! 

JAVA游戏由于目前的功能有限,所以一般的开发团队主要是需要程序、美工这两种人才。

目前市场上的主流机型,比如NOKIA、MOTO等都支持J2ME语言,所以程序员也要以此为主要技能,同时游戏编程与普通的软件编程也有很大区别,计算机图形学和各种优化图像大小的算法多少也有要懂些,如果有实际的开发经验,并且热爱游戏的话,那就太完美了。 

SYMBIAN游戏主要使用C++语言编程,其他条件与J2ME程序员相同。 

美工方面主要要求是掌握点阵图的画法。软件以PHOTOSHOP为主,对色彩构成必须很了解,手绘技能由于手机游戏要求的图都是很小尺寸的图形,所以不是很重要。别的方面还是那句话——如果有实际的开发经验,并且热爱游戏的话,那就太完美了。 

目前业内手机游戏方面的有经验人才薪资都被炒的虚高,所以我认为如果没有迫切压力的话,不妨试着从新手培养,只要坚持热爱游戏和心态踏实这两点原则,不难在短时间内培养出优秀的人才,国内著名的手机游戏开发论坛上并不缺乏这类人的身影,何况还可以通过和NOKIA等厂商在各个大学中开办的培训专业里挑选。而美工方面由于近年动漫市场的火爆比找程序员更容易,夸张点说随时都能抓出一大把技艺高超的艺术家来。 

其他人员,如配乐、测试等可以等发展达到一定程度后再委以专人负责,初期可以由其他部门人员负责。 

薪资上,刚毕业的新人试用期一律以3K/M为基准,有过实际开发经验的则按情况而论,估计在6-8K左右。 

STEP.3 办公室和设备 
电脑基本配置如下: 
CPU: Intel Celeron4 2.4G 
主板: 技嘉 GA-8I845PE-RZ 
内存: Hy 256M DDR400 
硬盘: 希捷 酷鱼7200.7/ST380011A 
显卡: 小影霸 G8520D 
显示器: 优派 E70f 
键盘: Microsoft 光学灵动鲨套装 Basic Optical Desktop 
机箱: 华康 107(空箱) 
电源: 航嘉 BS2000+ 
手写笔: WACOM 
价格总计:4500元左右 

其中程序员所用的电脑不需要手写笔,可以改为增加一条256M内存。 

还需要购买几部市场主流的手机用于测试,相应的通讯工具如蓝牙、IRC等设备也必须齐备。 

另外就是最好有单独的办公室,将游戏开发部门同其他部门员工分隔开来,避免相互之间的影响。 

一个完整的手机游戏开发团队最重要的资产就是人,在此我们得感谢互联网将我们带进了这个资讯发达得世界,得此助力,所需要得一切人才基本上都能在网上找到。当将这些人装到一个办公室之后,如何扬长避短,人尽其用,发挥出最大潜能,制作出世界一流的手机游戏则是管理者最为重要的问题。 

游戏开发要掌握的知识初探

 要看开发什么游戏了,开发2D RPG,则不需要那么多知识,C++DIRECTX,数据结构和计算机图形常识,RPG游戏制作流程及常识,会用MFCVB来开发地图脚本编辑器,最后加上一些算法,A*ALPHA BLENDING,斜45度地图技术等就可以了。

游戏开发所需知识
   
   数学基础:高等数学、线性代数、离散数学、数值分析等;
   编程语言:c/c++、汇编(pascal、java可选);
   编程工具:vc++6.0、delphi;
   操作系统:windows api,系统工作原理;
   硬件基础:计算机工作原理,特殊硬件优化;
   图形基础:计算机图形学,图形快速显示算法,抖动算法;
   多媒体: 波形文件回放,音频设备控制,视频图像的解码及播放;
   压缩加密:声音、图像压缩解压缩算法,加密算法;
   游戏sdk: opengl,directx;
   其它知识:人工智能,脚本算法,遗传算法,模糊逻辑,物理建模(uml),软件工程,编译原理。
   
日本游戏培训课程:
   第一年:c语言,游戏设计,文章构成,windows开发,计算机系统导论,程序算法,游戏开发工具使用,情报数学,windows基础;
   第二年:c++语言,windows程序游戏设计,cg数学,java,playstation程序开发,可视化程序开发,数据通信,数据库入门;
   第三年:游戏开发演习,游戏理论,directx研究,vb游戏制作,java游戏制作,playstation研究;
   
游戏设计工具:
   调试器: ollydbg(免费);
   十六进制编辑: hex workshop;
   安装工具: install shield professioal
   midi音乐: cakewalk;
   声效音乐: cooledit(或sound forge);
   3d建模: 3dmax(或maya);
   2d图形程序: paint shop pro(或painter);
   2d画图程序: coreldraw;
   2d图像处理: photoshop;
   c/c++编译器: vc++6.0; 


要看开发什么游戏了,开发2D RPG,则不需要那么多知识,C++,DIRECTX,数据结构和计算机图形常识,RPG游戏制作流程及常识,会用MFC或VB来开发地图脚本编辑器,最后加上一些算法,A*,ALPHA BLENDING,斜45度地图技术等就可以了

如果你想编游戏,而又有很多不清楚的问题,那请看这个: 
1 语言编程:c/c++ 
2 编程基础一定要好:数据结构,c/c++语言 
2 IDE集中开发环境:visual studio .net 2003 
3 游戏开发SDK用DirectX9 
4 Win32 api开始的时候不能学的太多 
5 可以不用MFC(如果你c++基础好,MFC学起来很简单) 
6 编网络游戏,使用winsock,通讯协议用TCP 
7 多下载源代码,观看之 
8 数学上的要求(其它基础文化课类似):不需要了解算法的来历、推导等,但一定要知道它们是干什么用的以及如何用 
9 学习STL,必须C++要过关!否则会很难学。首先要学会如何用STL,再想深入的话,学习STL的内部代码。STL首先从list,vector学起。 

这里有一些经典推荐书籍介绍: 
《微型计算机原理及应用》(第三版) 编著:郑学坚 周斌 清华大学出版社 
这是一本大学计算机基础教材,虽然内容不是很新鲜,但基础部分和汇编部分还是不错的,并且价格方面,嘿嘿,借也可以借到,拥有这本书的学生真是太多了。 

《C程序设计》(第二版) 作者:谭浩强 清华大学出版社 
这本书不用我说,大家也都知道,流传最广泛的C语言教材了。如果看好了此书,C的功底一定不错! 

《数据结构(C语言版)》 编著:严蔚敏 吴伟民 清华大学出版社 
又是一本大学经典教材,想对程序有深入了解,数据结构不可不看,学了他,你才能打开专业之门。 

《C++编程思想》(第二版) 作者:Bruce Eckel 机械工业出版社 
嘿嘿嘿,又是经典之作,想学C++和OO,看他,绝对没错,不用买别的C++入门书籍了!!!绝对经典。 

《The C++ Standard Library--A Tutorial and Reference》 作者:Nicolai M. Josuttis 
具有了一定的C++功底,该是看他的时候了,STL可是前人的思想精华。这本书主要讲述如何使用STL.(我只有这本书的电子版) 

《设计模式》 作者:Erich Gamma等著 机械工业出版社 

初级游戏开发指南

  本文试图帮助那些想实现自己的游戏,但又没什么编程经验的人。事实上,在这里我将假定您根本不懂编程,我主要针对游戏开发的编程与设计进行阐述,而不会涉及设计艺术。我也不大算对这个行业展开长篇赘论(毕竟到处可以找到大量的资源),但我将指出在制作你自己的游戏时需要注意的某些事情。

作者:Dave Astle
译者:Room3rd@hotmail.com

1. 作者简介
   从1984年开始,Dave Astle就做着游戏开发工作。日间,他是ROI System,Inc的一名软件工程师,夜间,引领Myopic Rhino游戏开发小组。只要有时间,他就会帮助GameDev.net成为最好的游戏开发资源网站。当然,他也需要偶尔的休息。
2. 译者序
3. 正文
   很多刚接触开发或没什么编程经验的人经常会问:我该如何开始游戏编程。即便直到现在,我也只是帮助回答我所知道一个又一个的基本问题。然而,最近这种类似问题太多了,多的有些难以接受了,所以,我决定还是把所有建议写下来,分享给大家吧。
   本文试图帮助那些想实现自己的游戏,但又没什么编程经验的人。事实上,在这里我将假定您根本不懂编程,我主要针对游戏开发的编程与设计进行阐述,而不会涉及设计艺术。我也不大算对这个行业展开长篇赘论(毕竟到处可以找到大量的资源),但我将指出在制作你自己的游戏时需要注意的某些事情。最后,这里展示的途径不是唯一的——也不一定是最好的 ——只是指出了该怎样制作游戏的学习途径,但对我和另外一些人来说,它已经足够好了。

   选择一门语言

   首先,你应该选择一门编程语言,可能会有很多选择:Basic,Pascal,C,C++,Java等等,并且还会有许多许多争论:对于一个新手来说,到底应该(最好)使用哪种语言呢?对于若干流行语言的讨论,可以看John Hattan的精彩文章“What Language Do I Use?”(http://www.gamedev.net/reference/design/features/whatlang)。
我会建议使用C/C++,可能有人会说“对于新手来说太深奥了吧”,起码我就是从C++开始的,所以对大家也应该没有问题。另外,C/C++应用很广泛,所以你可以找到大量的资源及帮助。先学C还是C++并不关键,毕竟只要学了一门,另一门也会触类旁通。然而,如果你决定先学习C++的话,还是应该在学习面向对象编程前首先要了解并掌握面向过程的开发。(也就是说,学习使用类前,你完全可以不用它们而很好进行开发)
   如果采用C/C++的话,可能发觉深入会越发的困难,当然,重新开始再选择学习一门更为简单的语言,如Basic或者Pascal,也未尝不可,但我还是要告诉你,只要坚持下去,找到所需的资源,逐步深入,C/C++开发也会越来越得心应手。
   接着你应该会问“那我该如何学习C/C++呢?”,很高兴你会这么问。最好的办法是上一个培训班(课),有老师或助教回答你的问题,能使你迅速提高,而留下的作业也会确认你是否真的掌握了你所学的知识点。(译者注:呵呵,在国内很难碰到这么好的教师吧)
   如果上培训班对你来说不现实的话,那最好的办法就是找一些好的书籍。不要过于专注“精通”之类的书籍,否则,最后你可能会买上一大摞。我的建议是到最近的图书市场,在那里花些时间来浏览那些关于C/C++介绍(入门)的书籍,直到你确定你能读懂并能从那本书学到一些东西。然后,等你需要一些高级编程的书籍,或者是一本参考时,由于你对于这门语言有了些许了解,那时你就会知道你更需要什么。我们的“books section”中给了一些建议,地址为:http://www.gamedev.net/columns/books/。
   在此,我还想费些口舌来提醒众多的编程新手,尤其是那些年轻人:没有钱买书或者干其他的事情。首先,你可以找到很多编程资源,其中包括本地库文件,还有Macmillan Computer出版物,通过http://www.mcp.com/personal可以找到成千上百的编程书籍。但是,其次,如果你真的想成为一名出色的程序员,有时脑筋不得不转个弯儿,使用任何东西(合法的;<)都意味着你不得不数数口袋里的钞票然后掏出来。
   通过Web完全可以找到大量的C/C++学习指南,但我觉得这些指南最好作为你学习书籍的补充,而不是作为单独的资源使用。

   选择合适的编译器

   你写的程序或者说是源代码,被存储为文本文件,你完全可以使用Notepad来写一个C/C++程序,但你还是需要“某些东西”来把源代码转化成可执行文件。在C/C++中,这个“某些东西”指的就是编译器。
编译器有很多,有些还是免费的,选择一个适合你的很重要,免费的更方便你去尝试,并选择一个你觉得最好的。然而,免费也通常意味着功能不全或者支持不够。幸运的是,大多数商业编译器也有入门及学术版本(introductory or academic versions),这样你就会花更少的钱而获得全部功能,唯一的限制是:你不能把用它编译的程序发布出去(毕竟在某段时间你不会发布……)。
   最后,你选择的编译器应该取决于你的花费及开发所处于的操作系统或平台。如果打算在Windows下开发,强烈建议使用Microsoft Visual C++,它拥有一个强大的开发环境,使得开发变得更容易,并且毫无疑问开发Windows应用程序也没有其他更适合的编译器。(译者注:应该是针对C++而言,不过使用BC或者其他编译器的肯定不同意,但我也推荐使用VC,因为开发资料确实很多,虽然我也不太会:))如果你是学生,那太好了,你会以不错的折价得到一个拷贝,如果在DOS下编程,最好赌注DJGPP(http://www.delorie.com/djgpp),它是免费的。(译者注:的确真的确实非常好奇地问“DOS下开发的人还有么?”)

   目标平台

   尽管你最终可能发布到若干不同平台下,但你还是需要一种来重点学习。一旦学习一门语言,在进入开发前(包括图形开发),你可能需要使用一个非GUI的操作系统,如DOS或者UNIX,这会避免一些前置问题(the overhead involved with),例如,Windows编程中,你就可以仅专注于语言的学习,(而不用担心界面部分)。
   一旦你准备好开始游戏编程了,你还是应该确定你的目标平台。还是让我们看看更多的(需要注意的)重要环节吧:
   Windows:如果你想在游戏行业中做的很专业,或者更多的人能玩你的游戏,那就选择Windows吧。重要的是你的用户在使用Windows — 至少现在看来是这样的。Windows大量主流游戏使用了一种开发技术 — DirectX,你可能听到过。DirectX是一个开发库,可以使你直接访问硬件层,也就意味着你可以开发高性能的游戏。
   DOS:DOS曾经是主流的游戏开发平台,但那些日子已经一去不复返了。尽管还有一些嗜好者仍在开发DOS游戏,但不再有商业游戏开发了,毕竟Microsoft不再给予更多的支持了。如果你刚开始做游戏,不要选择DOS,否则,不要执着于此。注意:由于还是有些DOS游戏编程的书籍,需要注意学习的话,可能会跟实际有所不同了。现在Windows游戏开发的书籍越来越多,这方面的争论也会越来越少。
   Linux:Linux作为一种UNIX变体,基于某些原因,近来变得很流行,这些因素包括稳定性、价格还有反Microsoft情绪在内。尽管Linux的用户数还相对较少,但由于对它的极度热衷和潜在市场的增长,使得可以作为目标平台的另一种选择。
   Macintosh:Mac有着大量的不容忽视的热衷者,而且我所了解得每个热衷者都极度渴望Macintosh下能有更多更好的游戏。虽然我没有看到过在Mac下开发的资源,但我还是确信肯定在某处存在着,因此这也是一种有理由选择的平台。
   控制器(Consoles):控制器(也就是PS、N64、DC等等)游戏市场是巨大的,开发控制器游戏当然有前途,但是,非商业开发有很多因素使得有很大的不确定性。如果你在开发控制器游戏,可能是正在被一个商业游戏工作室所雇用吧。

   备足原料(On to good stuff)

   现在可以开始讨论实际的游戏开发了,简单起见,我将假定你已经选择了C/C++语言并在Windows下开发,但我所说的对其他条件同样适用。
   首先,开发游戏前,你应该熟练掌握C/C++。你需要了解指针、数组、结构、函数,可能还有类,应该是很精通了。如果这样的话,那你就已经准备好了。
本文不可能教会游戏开发中的所有事情,幸运的是,也没有必要,Web上完全可以找到大量的相关书籍及指南。GameDev.net应该有你所需要的。下面就是我的一些建议:
   一本或更多的书籍。Windows中,开始开发游戏的话,“Windows游戏开发诀窍”(http://www.amazon.com/exec/obidos/ASIN/0672313618/gamedev)很适合你看。另外Books section也会找到其他一些书籍。通读整本书,尝试所有的范例,然后重新阅读你不能理解的部分。
   以在线指南作补充。除了阐明你所读过的知识外,他们同样包含书中没有的知识点(主题)。
   问专家。书中或指南中都找不到答案的话,那就充分利用留言板和聊天室(译者注:感觉国内的聊天室没有太好的氛围,还是找些BBS或者论坛问吧),会有很多人愿意帮你解决的。
   实际中,不应该是一个固定不变的过程,而应该是一个相似过程的不断重复。
   仅仅学习是不够的,还需要把学到的东西应用,首先开始一个简单的游戏,然后逐步发展。可以看看Geoff Howland的文章:“我是怎样开发游戏的?一条游戏开发的途径”(http://www.gamedev.net/reference/design/features/makegames)。
   起初,还是打算自己干吧,不要急于加入一个开发组,因为那只会让你的学习过程变得缓慢。一旦你自行完成了数个游戏,那对于一个开发组来说你也会起到更大的作用。
关于书籍我还是愿意多说两句:除游戏开发的书籍外,你需要阅读更多的书籍。为了能创建各式各样的游戏 — 如售货架上的那些 — 你将不得不钻研那些更高级的主题。有些你是可以在指南中找到的,但还是会需要更多的书籍:图形、人工智能、网络、物理等等。所以你需要上这些培训(课) — 虽然你觉得这些对于游戏编程没有用 — 这简直够的上一个计算机科学专业的学位。

   总结(Wrapping up)

   这里还有些重要的提示:
   不要仅仅积累知识,去应用。你绝对不会真正懂得或者理解一个事物,除非你使用它。用自己所学,实现些小的demo程序吧。可以做一下书中每章节后的练习题。
   玩大量的游戏。这样做可以给你些启发,帮你实现更好游戏,同样也给你很好的理念(a welcome relief from programming)。
   帮助他人。通过帮助他人解决问题,你也会了解这个知识点,并学会更多东西。
   完成你所开始的。不要陷入到你的思维陷阱中:“我知道我可以完成这个游戏,但我有了更好的主意,我要实现这个更好的(而不是原来的)。”如果坚持完成你所开始的,你会懂得更多东西,而且你拥有了一个事物可以证明你并不是夸夸其谈。要想实现简单些的话,就不要在更多经验前尝试实际上很大、很复杂的游戏。
   开始吧!现在你肯定陶醉于制作Quake 4中,好的,虽然不见得如此,但至少你能沿着这条路走下去,并找到更多的信息,夜以继日的辛勤工作后,必定有收获。 

OpenGL FAQ

标题可能写的大了点,不过没关系,以后还会加新的内容进来,今天先开个头。。。

学习OpenGL也有一段时间了,想想这一路走来也费了不少劲,现在论坛上仍然有很多人问一些初级的问题,当时我也是那样,可能连OpenGL到底是什么都不知道,呵呵,姑且将自己对OpenGL的一点点了解共享出来,希望对刚刚上路的朋友能有所帮助,还是那句话,如有不当之处,敬请指出,感激不尽!

1.   什么是OpenGL

这个问题看起来傻了点,但对于从未接触过OpenGL的人来说,也并不简单。OpenGL

全称:Open Graphics Library 中文译名没有什么说的,就叫它开放式图形库吧,说白了就是一套功能强大的3D图形处理API,如果你连什么是API都不明白的话,兄弟,那就别往下看了,最早是由SGI公司开发并维护的,主要是应用于其图形工作站。现在已经到了OpenGL2.1了,但是遗憾的是微软对OpenGL的支持只到1.1,因为DirectX和OpenGL本来就是死对头。

有一点要说明的是,OpenGL是跨平台的,可以运行在多种操作系统上,Windows,UNIX等等。

2.   如何获取OpenGL

如果你使用的是Windows系统,那么你的系统上已经自带了OpenGL 1.1的库文件了,如果想使用更高版本的OpenGL,比如1.2或者2.0,那么只能使用OpenGL扩展,关于如何下载和使用OpenGL扩展,请看这里:

http://myturn.blog.hexun.com/7704537_d.html

强调一下:经常有人这样问:哪里有OpenGL2.0的库文件?在Windows平台下,这是一个错误的说法,因为前面已经说过,Windows系统对OpenGL的支持只到1.1,1.1以后的新功能,都是以扩展的形式存在的,所以根本就没有什么OpenGL2.0的库文件了。如果你在别的平台下,也许会幸福一点,没办法,现在毕竟还是Windows的天下。

3.   如何使用OpenGL开发程序

这也是经常被问道的一个问题,我只说一下Windows平台,UNIX我没玩过,没有发言权,在Windows平台下,最好使用Visual Studio作为开发环境,比如VC6.0和VC8.0(确切的说是VS2005中的VC++),如果你连编程序都不会,那最好先不要学这个,先把编程学明白再说吧

建议的开发环境:32bit-WINXP-PRO-XP2 + VC++8.0

Vista 么,刚刚出来,大家用起来可能不太习惯,VC6.0也可以,但最好用VC8,有新的干嘛不用呢,如果你非在2K上编的话,谁也拦不住你,但是我想说一句,2K要淘汰了,Vista都出来了!XP还能用几年?要跟得上时代。

4.   如何配置开发环境

由于OpenGL是跨平台的,所以与平台有关的东西它都没有,比如Windows系统上的窗口过程,OpenGL标准并不提供窗口函数,如果你要编写窗口函数,只能使用额外的工具函数库,这里我推荐大家使用glut库,当你使用额外的工具函数是,你需要导入一些文件,对于OpenGL来说,主要有三类文件:

.lib文件,也叫库文件,这个文件是编译是链接到程序中的

.dll文件,动态链接库文件,我们用到的函数就保存再这里

.h文件, 头文件,包含在你的源程序中

下面我以glut库为例说一下如何放置这些文件,下载glut库以后,解压后共有三个文件,

这样放置:

如果你使用的是VC6.0

将glut.h放入VC98\Include\GL文件夹下

将glut.lib和glut32.lib放入VC98\LIB文件夹下

将glut32.dll和glut.dll放入Windows\System32\文件夹下

如果你使用的是VC8.0 (假定VC8.0装在C:\Program Files)

glut.h放在

C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\gl

glut.lib和glut32.lib放在

C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Lib

glut32.dll和glut.dll放在

C:\Windows\System32\

在你的源程序中包含头文件时要这样写,比如包含glut.h,应该写成:

#include "GL/glut.h"

使用glut的另一个好处是,它已经包含了gl.h和glu.h,不必在程序中再指定这两个文件了

5.   函数类型

在OpenGL的程序中经常会看到一些函数有一些固定的前缀,简单解释一下

a)          gl 核心函数

b)         glu 使用函数,对核心函数进行了简单封装,主要为了减少编程负担

c)          aux 辅助函数 与平台相关,主要是在windows平台上管理输入输出

d)         wgl 专用函数,w代表windows,所以这些函数主要在windows平台使用

6.   简单代码

说了一大堆,怎么也得给点代码看看,光说不练是扯蛋!来点最简单的,该省的都省了,也许不太规范,多了大家看着烦

在运行这个程序的时候,你需要按照上面第4步的方法配置好环境先。

#include <windows.h>

#include <GL/glut.h>

void display(void) 

{

glClear(GL_COLOR_BUFFER_BIT) ;

glBegin(GL_POLYGON) ;

glVertex3f(0.25, 0.25, 0.0) ;

glVertex3f(0.75, 0.25, 0.0) ;

glVertex3f(0.75, 0.75, 0.0) ;

glVertex3f(0.25, 0.75, 0.0) ;

glEnd() ;

glFlush() ;

}

int main(int argc, char **argv)

{

glutInit(&argc, argv) ;

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB) ;

glutCreateWindow("I love OpenGL") ;

glutDisplayFunc(display) ;

glutMainLoop() ;

return 0 ;

}

没有任何注释,对于一个新手来说,给你留点思考的空间,对于老手来说,呵呵,我就不多说了,都明白。

简单写点,以后再扩充。

作为3D的工业标准,OpenGL在苹果上可以说无处不在,用起来也是分外的舒服。
一般OpenGL需要搭配一些窗口库来做,比如QtMFC等,或者用跨平台的GLUT
好在GLUTMac OS X自带的,所以直接用就可以了,很方便。

OpenGLGLUT作为Framework,都在/System/Library/Frameworks下。在程序里
唯一需要注意的是include的头文件。

Windows提供了OpenGLGLU,如果用GLUT,得自己去装一个。Windows下的头文
件使用方式一般是
#include <Windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
//#include "GLUT/glut.h"
//depends on where you put GLUT

而在Mac OS X下,一般是
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>

在编译的时候,需要用到Mac OS Xgcc-framework参数,例如
g++ -framework OpenGL -framework GLUT -framework Foundation -o test my.cpp

附件里是以前的实验作业(一个消隐算法,一个是Phong光照模型),在Mac OS X
Windows下的效果都还可以。哪位大虾有空写两个游戏给大家玩玩吧(声音视频
等可以考虑用SDL来做),呵呵。

OpenGL发展历程

在计算机发展初期,人们就开始从事计算机图形的开发,但直到20世纪80年代末、90年代初,三维图形才开始迅速发展。于是各种三维图形工具软件包相继推出,如GL,RenderMan等。随着计算机技术的迅速发展,GL已经进一步发展成为OpenGL,现在OpenGL被认为是高性能图形和交互式视景处理的标准。这些三维图形工具软件包有些侧重于使用方便,有些侧重于绘制效果或与应用软件的连接,但没有一种软件包能在交互式三维图形建模能力和编程方便程度上与OpenGL相比拟。

OpenGL(即开放性图形库Open Graphics Library),是一个三维的计算机图形和模型库,最初是美国SGI公司为图形工作站开发的一种功能强大的三维图形机制(或者说是一种图形标准)。它源于SGI公司为其图形工作站开发的IRIS GL,在跨平台移植过程中发展成为OpenGL。SGI在1992年7月发布1.0版,后成为工业标准,由成立于1992年的独立财团OpenGL Architecture Review Board (ARB)控制。SGI等ARB成员以投票方式产生标准,并制成规范文档(Specification)公布,各软硬件厂商据此开发自己系统上的实现。只有通过了ARB规范全部测试的实现才能称为OpenGL。1995年12月ARB批准了1.1版本,最新版规范是2006年8月2日通过的opengl2.1,是自1.0版本后的第七次版本。新版本适应以往早期的版本,也就是2.0, 1.5, 1.4, 1.3, 1.2, 1.1, or 1.0 GL不要任何改变就能在新版本下运行。

OpenGL被设计成独立于硬件,独立于窗口系统,在运行各种操作系统的各种计算机上都可用,并能在网络环境下以客户/服务器模式工作,是专业图形处理、科学计算等高端应用领域的标准图形库。它低端应用上的主要竞争对手是MS-Direct3D,该图形库是以COM接口形式提供的,所以极为复杂,稳定性差,另外微软公司拥有该库版权,目前只在Windows平台上可用。Direct3D的优势在速度上,但现在低价显卡都能提供很好的OpenGL硬件加速,所以做3D图形开发使用Direct3D已没有特别的必要,在专业图形处理特别是高端应用方面目前还没有出现以Direct3D技术为基础的例子,而游戏等低端应用也有转向OpenGL的趋势。

微软在Windows NT对OpenGL的支持始于3.51,在Windows9x中的支持始于Win95 OEM Service Release 2。Windows下常用的OpenGL库有两种,MS实现的和SGI实现的,MS-OpenGL调用会自动检测是否存在显示卡制造商提供的ICD(Installable Client DeviceDriver)驱动程序,有则调用ICD中的例程,否则使用CPU进行计算,所以能利用显示卡的OpenGL加速能力。对开发者来说使用方法并没有区别,只是有ICD驱动时更快些。SGI的版本是纯软件实现,不能利用硬件加速并且SGI已经在1999年宣布停止支持,但这套图形库便于调试程序,仍有不少开发者使用。

1999年SGI宣布与MS合作开发Ferihant,即Windows的下一代图形处理体系,包括DirectX与OpenGL的低级图形处理接口和以场景图支持为特点的高级接口,并且就此停止对其在Windows下的OpenGL实现的支持以示决心。此举令世人瞩目,大家都以为Windows图形处理快要过上幸福生活了,然而,不久,SGI宣布中止合作,并撤回派出的科学家,Ferihant基本上夭折。SGI 称终止合作的原因是MS不肯积极合作,光想把SGI 的技术合并进DirectX,但是真正内幕不详。不过以SGI在图形处理界的老大地位来说,还是有几分可信度的,因为MS最初支持OpenGL就不积极。

OpenGL可以运行在当前各种流行操作系统之上,如Mac OS、Unix、Windows 95/98、Windows NT/2000、Linux、OPENStep、Python、BeOS等。各种流行的编程语言都可以调用OpenGL中的库函数,如C、C++、Fortran、Ada、Java。OpenGL完全独立于各种网络协议和网络拓扑结构。目前,Microsoft公司、SGI公司、ATT公司的Unix软件实验室、IBM公司、DEC公司、SUN公司、HP公司等几家在计算机市场占主导地位的大公司都采用了OpenGL图形标准。值得一提的是,由于Microsoft公司在Windows NT和Windows 95/98中提供OpenGL标准,使得OpenGL在微机中得到了广泛应用。尤其是在OpenGL三维图形加速卡和微机图形工作站推出后,人们可以在微机上实现CAD设计、仿真模拟、三维游戏等,从而使得应用OpenGL及其应用软件来创建三维图形变得更有机会、更为方便。

OpenGL作为一个性能优越的图形应用程序设计界面(API),适用于广泛的计算机环境。从个人计算机到工作站和超级计算机,OpenGL都能实现高性能的三维图形功能。由于许多在计算机界具有领导地位的计算机公司纷纷采用OpenGL作为三维图形应用程序设计界面,所以OpenGL应用程序具有广泛的移植性。因此,OpenGL已成为目前的三维图形开发标准,是从事三维图形开发工作的技术人员所必须掌握的开发工具。OpenGL应用领域十分宽广,如军事、电视广播、CAD/CAM/CAE、娱乐、艺术造型、医疗影像、虚拟世界等。

1.1 opengl1.1

1995年,SGI推出了更为完善的OpenGL 1.1版本。OpenGL 1.1的性能比1.0版提高甚多。其中包括改进打印机支持,在增强元文件中包含OpenGL的调用,顶点数组的新特性,提高顶点位置、法线、颜色、色彩指数、纹理坐标、多边形边缘标识的传输速度,引入了新的纹理特性等等。

1.2 opengl1.3

2001年8月,ARB发布OpenGL 1.3规范,它增加了立方纹理贴图、纹理环境、多重采样、纹理框架压缩等扩展指令,但是改进程度非常有限。

1.3 opengl1.4

2002年7月,ARB正式发布OpenGL 1.4,它也只加入了深度纹理/阴影纹理、顶点设计框架、自动纹理贴图等简单的功能。

1.3 opengl1.5

2003年的7月,ARB公布OpenGL 1.5规范。OpenGL 1.5内包含ARB制定的“正式扩展规格绘制语言”(OpenGL Shading Language v1.0),该语言用于着色对象、顶点着色、片断着色等扩展功能,同时也将作为下一代OpenGL 2.0版本的内核。OpenGL 1.5的变化还增加了顶点缓冲对象(可提高透视性能)、非乘方纹理(可提高纹理内存的使用效率)以及阴影功能、隐蔽查询功能等等。其主要内容包括

l 顶点Buffer Object:进行顶点配列方式可以提高透视性能
l Shadow功能:增加用来比较Shadow映射的函数
l 隐蔽查询(QUERY):为提高Curling性能采用非同步隐蔽测试
l 非乘方纹理(Texture):提高mipmap等纹理内存的使用效率
l OpenGL Shading Language v.1.0:用于着色(shader)对象、顶点着色以及片断着色技术(fragment shader )的扩展功能
1.4 opengl2.0

OpenGL 1.0推出后的相当长的一段时间里,OpenGL唯一做的只是增加了一些扩展指令集,这些扩展指令是一些绘图功能,像是ClearCoat、Multisample、视频及绘图的整合工具(某些是通过OpenML的努力而开发出来的,它本身属于OpenGL ARB扩展指令之一。
   OpenGL 2.0将在OpenGL 1.3基础上进行修改扩充、但它将有下面五个方面的重大改进:①复杂的核心被彻底精简;②完全的硬件可编程能力;③改进的内存管理机制、支持高级像素处理;④扩展至数字媒体领域,使之跨越高端图形和多媒体范畴;⑤支持嵌入式图形应用。
    为了在获得强大功能的同时保持理想的兼容性,OpenGL 2.0经历以下两个发展阶段:第一个阶段注重兼容能力和平滑过渡,为此,OpenGL 2.0核心将在精简后的OpenGL 1.3功能模块的基础上加上可完全兼容的新功能共同组成,这种做法在满足兼容性的同时,还可将原有OpenGL中数量众多、且相互纠缠不清的扩展指令进行彻底精简。 第一阶段的任务只是为了过渡,而第二阶段才是OpenGL 2.0的真正成熟期。此时,ARB将合成出一个“纯OpenGL 2.0”内核,纯内核将包含更多新增加的“精简型API函数”,这些函数具有完全的可编程特性、结构简单高效、功能强大且应用灵活。除了完成这项任务外,ARB组织还得指导开发商抛弃繁琐的OpenGL 1.X、转用更具弹性的“纯OpenGL 2.0”。

1.5 opengl2.1

OpenGL version 2.1在2006年8月2日发布,是最初版本1.0后的第七个版本。尽管增加了版本的层析,支持高层析的编程shaders,但版本能够适于早期的版本,意味着运行2.0, 1.5, 1.4, 1.3, 1.2, 1.1, or 1.0 GL的程序不用任何改变就可运行。

OpenGL2.1与当前的2.0版本相比,虽然版本号变更不如DX9到DX10那么巨大,但它却增加了多项实用的技术和功能,例如向后兼容增强型OpenGL的先进管道规划,其中包括:优化GPU和显存之间并行工作时间,提高象素缓冲和对象的象素和质感快速缓冲利用率;增加标准彩色图像质感sRGB色彩空间应用促进管理的灵活性;并增加了许多新的shader弹性调配,包括非平方矩阵支持,支持阵列流对象和碎块点位置时,干扰和shaders属性不变的变量shader代码提高可靠性。1. GLSL升级至1.2版;2. 支持非正方形的矩阵. UniformMatrix {2x3,3x2,2x4,4x2,3x4,4x3}fv ;3. 象素缓冲对象(Pixel Buffer Object).  它扩充了缓冲对象的接口.现在缓冲区对象可以支持顶点数组和象素数据了.象素缓冲对象能加速在GPU内存中进行的缓冲区之间的数据拷贝及其他象素操作.;4. sRGB纹理. 遵循IEC 61966-2-1.标准的sRGB颜色空间的纹理格式(包括压缩和非压缩格式).(OpenGL 2.1 adds backwards compatible enhancements to OpenGL's advanced programmable pipeline including: Pixel Buffer Objects for fast texture and pixel copies between frame buffer and buffer objects in GPU memory; texture images specified in standard sRGB color space for enhanced application color management flexibility; and numerous additions to increase the flexibility of shader programming including non-square matrix support, support for arrays as first-class objects, a fragment position query in shaders using Point Sprites and an invariant attribute for variables to enhance shader code reliability.)

OpenGL2.1的效果

2 OpenGL扩展(OpenGL Extensions)

OpenGL和Direct3D比较起来,最大的一个长处就是其扩展机制。硬件厂商开发出一个新功能,可以针对新功能开发OpenGL扩展,软件开发人员通过这个扩展就可以使用新的硬件功能。所以虽然显卡的发展速度比OpenGL版本更新速度快得多,但程序员仍然可以通过OpenGL使用最新的硬件功能。而Direct3D则没有扩展机制,硬件的新功能要等到微软发布新版DirectX后才可能支持。 
OpenGL扩展也不是没有缺点,正因为各个硬件厂商都可以开发自己的扩展,所以扩展的数目比较大,而且有点混乱,有些扩展实现的相同的功能,可因为是不同厂商开发的,接口却不一样,所以程序中为了实现这个功能,往往要为不同的显卡写不同的程序。这个问题在OpenGL 2.0出来后可能会得到解决,OpenGL 2.0的一个目标就是统一扩展,减少扩展数目。 

2.1 扩展名
每个扩展都有一个扩展名,扩展名类似如下形式: 

GL_ARB_multitexture 

第一段GL,用来表示针对OpenGL哪部分开发的扩展,有以下几个值: 

GL – 针对OpenGL核心的扩展 
WGL – 针对Windows平台的扩展 
GLX – 针对Unix / Linux平台的扩展 
GLU – 针对OpenGL Utility Library的扩展 

第二段ARB,用来表示是谁开发的这个扩展,常见以下几个值:

ARB – 经OpenGL Architecture Review Board(OpenGL管理机构)正式核准的扩展,往往由厂商开发的扩展发展而来,如果同时存在厂商开发的扩展和ARB扩展,应该优先使用ARB扩展 

EXT – 被多个硬件厂商支持的扩展 
NV – nVIDIA 公司开发的扩展 
ATI – ATI公司开发的扩展 
ATIX– ATI公司开发的实验性扩展 
SGI – Silicon Graphics(SGI)公司开发的扩展 
SGIX– Silicon Graphics(SGI)公司开发的实验性扩展 

第三段multitexture就是真正的扩展名了,如multitexture就是多重纹理扩展。

2.2使用OpenGL扩展

要使用一个OpenGL扩展,首先必须检查显卡是否支持这个扩展,以下代码可以获取一个显卡支持的的OpenGL扩展:
const char *str = glGetString( GL_EXTENSIONS );
函数返回一个字符串指针,这个字符串就是显卡所支持的所有扩展的扩展名,不同的扩展名之间用空格隔开,形如:

"GL_ARB_imaging GL_ARB_multitexture GL_ARB_point_parameters ……"

OpenGL扩展往往都会新增一些函数,在Windows平台上,这些函数不是通过.lib库连接到程序里的,而要在运行时动态获得函数的指针。我们以GL_ARB_point_parameters扩展为例看看怎么获得函数指针。

首先要定义函数指针类型,

typedef void (APIENTRY * PFNGLPOINTPARAMETERFARBPROC)(GLenum pname,
GLfloat param);
typedef void (APIENTRY * PFNGLPOINTPARAMETERFVARBPROC)(GLenum pname,
const GLfloat *params);

这个工作SGI已经为我们做好,它提供了一个头文件 glext.h ,里面有目前绝大多数扩展的常量和函数指针定义,下载下来放到编译器的include/GL文件夹下面,然后在程序里面加上:

#include <GL/glext.h>

就可以在程序中使用常量和函数指针类型了。

然后要定义函数指针:

PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;

再检查显卡是否支持GL_ARB_point_parameters扩展,其中isExtensionSupported是自定义的一个函数,就是在glGetString( GL_EXTENSIONS )返回的字符串里查找是否存在指定的扩展名:

int hasPointParams = isExtensionSupported("GL_ARB_point_parameters");

如果支持,就可以用wglGetProcAddress函数获取扩展函数的指针:
if (hasPointParams) 
{
glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)\
wglGetProcAddress( "glPointParameterfEXT" );
glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC) \
wglGetProcAddress( "glPointParameterfvEXT" );
}

最后就可以在程序里使用扩展函数:

if (hasPointParams)
{
static GLfloat quadratic[3] = { 0.25, 0.0, 1/60.0 };
glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, quadratic);
glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0);
}

另外,下面代码说明如何访问扩展函数:(资料来源于csdn知识库)

调用wglGetProcAddress函数访问一个不在标准OpenGL库中的扩展函数。如果该扩展函数存在当前的执行(implementation)中,那么wglGetProcAddress返回一个用来访问该函数的函数指针。否则,wglGetProcAddress返回NULL.

例如,要访问glAddSwapHintRectWIN扩展函数,如下调用wglGetProcAddress:

// Get a pointer to the extension function.
typedef void (WINAPI *FNSWAPHINT)(GLint, GLint, GLsizei, GLsizei);
fnSwapHint = (FNSWAPHINT)wglGetProcAddress("glAddSwapHintRectWIN");

// Actual call to glAddSwapHintRectWIN.
if (fnSwapHint != NULL)
(*fnSwapHint)(0, 0, 100, 100);

2.3 WGL扩展

glGetString( GL_EXTENSIONS )取得的扩展字符串中并不包括针对Windows平台的WGL扩展,WGL扩展串要通过WGL_ARB_extensions_string扩展来获得,以下代码演示了如何获得WGL扩展串:

定义WGL_ARB_extensions_string扩展新增函数wglGetExtensionsStringARB的函数指针类型,同样这个工作SGI已经为我们做好,只不过不在glext.h中,而在它提供的另外一个头文件 wglext.h 中:

typedef const char *(APIENTRY * PFNWGLGETEXTENSIONSSTRINGARBPROC)(
HDC hdc);

定义函数指针:

PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;

检查是否支持WGL_ARB_extensions_string扩展,如果不支持,表示这个显卡不支持WGL扩展,如果支持,则得到wglGetExtensionsStringARB函数的指针,并调用它得到WGL扩展串:

int hasWGLext = isExtensionSupported("WGL_ARB_extensions_string");
if (hasWGLext)
{
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) \
wglGetProcAddress( "wglGetExtensionsStringARB" );
const char *wglExt = wglGetExtensionsStringARB( hdc );
……
}

2.4 OpenGL版本

一些常用的OpenGL扩展会在新版的OpenGL中加到OpenGL核心中去,成为OpenGL标准的一部分,可以简化程序开发,程序员使用这些功能时不必做繁琐的扩展初始化工作。比如多重纹理功能,在OpenGL1.2.1加入到OpenGL核心中,以前要使用多重纹理,要先检查是否支持GL_ARB_multitexture扩展,然后初始化glActiveTextureARB等函数,很麻烦,而OpenGL1.2后,则可以直接使用glActiveTexture函数。 
不过,这种简化只有Mac/Unix/Linux程序员才能享受到,在Windows平台上没有这么简单。微软为了维护Direct3D,对OpenGL的支持很消极,其OpenGL实现仍然是1.1。由于Windows上的OpenGL程序最终都会动态链接到微软的OpenGL32.dll,可OpenGL32.dll只支持OpenGL 1.1,使我们不能直接使用新版OpenGL,仍然要用扩展访问OpenGL1.1以来新增的功能。

2.5 OpenGL扩展资料

All About OpenGL Extensions :必读。
讨论OpenGL扩展机制,讲述了如何阅读扩展官方说明书,并举了一些扩展的例子。
OpenGL Extension Registry :
由SGI维护,列出了目前公开的所有扩展及其官方说明书。

OpenGL Hardware Registry : 由Delphi3D.net维护,列出了目前几乎所有3D加速卡的OpenGL硬件信息,包括其支持的扩展。当然,这里面列的扩展不能作为程序的依据,程序中要使用某个扩展,还是要先检查显卡是否支持。因为同样的显卡,如果驱动程序不同,支持的扩展也不相同,往往新的驱动程序会加入新的扩展,丢掉一些废弃的扩展。

2.6 OpenGL硬件加速 

在Windows平台上,OpenGL驱动可能有三种模式:纯软件、MCD和ICD: 

纯软件模式:微软提供一个OpenGL的软件实现,所有渲染操作均由CPU完成,速度很慢。如果安装系统时使用Windows自带的显卡驱动程序,那么OpenGL程序就会运行在软件模式下。而且由于微软有自己的Direct3D,所以对OpenGL的支持很消极,它的OpenGL纯软件实现只支持OpenGL1.1,而目前OpenGL的最新版本为1.4

MCD(Mini Client Driver):MCD是早期微软在Windows NT上支持OpenGL时,为了简化驱动开发时使用的一个模型。在这个模型中,OpenGL渲染管线的变换、光照部分仍然由软件实现,而光栅化部分则由硬件厂商实现,因此只要硬件支持,MCD可以硬件加速光栅化部分。MCD虽然可以简化驱动开发,但是功能限制太大,现在市面上的3D加速卡均支持硬件变换和光照,MCD却不能利用这一特性,看上去MCD已经没有存在的价值

ICD(Installable Client Driver):ICD是一个完整的OpenGL驱动模型,比MCD复杂得多。硬件厂商要实现完整的OpenGL渲染管线,如变换、光照、光栅化等,因此只要硬件支持,ICD可以硬件加速整个OpenGL渲染管线。我们通常说的OpenGL硬件加速就是指的通过ICD模型获得的硬件加速,而现在硬件厂商提供的OpenGL驱动程序也都是依照ICD模型开发的。主要硬件厂商的ICD已经可以支持OpenGL的最新版1.4

Windows怎么实现OpenGL硬件加速呢?OpenGL32.dll是微软的OpenGL 1.1纯软件实现,我们的程序都要动态链接到这个dll。如果安装3D芯片厂商的驱动程序,会将一个不同名字的dll放到Windows系统目录下,比如在Windows 2000下安装nVIDIA GeForce2 MX的驱动程序,会在系统目录下放一个nvoglnt.dll(这就是nVIDIA的OpenGL驱动),并在注册表中登记nvoglnt.dll,让Windows知道硬件加速OpenGL驱动的名字,以后运行OpenGL程序,OpenGL32.dll就会把OpenGL调用直接转到nvoglnt.dll。 

Windows平台上,一个OpenGL程序是否使用硬件加速由三个因素决定,这三个因素缺一不可,否则程序都会运行于纯软件模式: 

是否有一块3D加速卡 

是否安装了显卡厂商提供的最新的驱动程序,Windows自带的显卡驱动程序并不会提供OpenGL硬件加速能力 

指定的像素格式是否被显卡硬件所支持 

判断一种像素格式是否被显卡硬件所支持,可以用函数DescribePixelFormat取得该像素格式的数据,然后看结构体PIXELFORMATDESCRIPTOR中的dwFlags的值,如果

PFD_GENERIC_FORMAT被置1,并且PFD_GENERIC_ACCELERATED被置0,即
(pfd.dwFlags & PFD_GENERIC_FORMAT) && 
!(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
表明该像素格式不被显卡硬件支持,使用该像素格式的OpenGL程序将使用纯软件模式渲染 

PFD_GENERIC_FORMAT被置1,并且PFD_GENERIC_ACCELERATED被置1,即
(pfd.dwFlags & PFD_GENERIC_FORMAT) && 
(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
表明该像素格式被显卡硬件支持,并且程序使用MCD模式渲染 

PFD_GENERIC_FORMAT被置0,并且PFD_GENERIC_ACCELERATED被置0,
!(pfd.dwFlags & PFD_GENERIC_FORMAT) && 
!(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
表明该像素格式被显卡硬件支持,并且程序使用ICD模式渲染 

3 OpenGL Extension 

这个软件可以自动测试显卡对OpenGL的版本支持和扩展命令。

4、如何使用扩展

如果你在Windows平台下开发OpenGL程序,那么系统中自带的OpenGL库就是1.1的,如果想使用1.2或者更高版本的OpenGL库,那么只能使用OpenGL扩展。很多参考书上都会提到OpenGL2.0OpenGL2.1,但是微软对OpenGL的支持只到1.11.1以后微软就不再支持了,为什么,因为微软更想发展自家的DirectX。所以如果想使用OpenGL1.1以上的功能或者函数,只能使用OpenGL扩展,这些扩展是一些OpenGL团体或个人开发出来的能Windows上使用的OpenGL1.1以后的一些功能及函数。所以,在Windows上根本就没有什么OpenGL2.0的头文件或库文件了,OpenGL1.1以后的东西都已经以扩展的形式存在了,而且,并没有一个统一的标准,你可以使用glexglewglee等等。

是否能用扩展和显卡的功能有关,const     GLubyte   * glGetString( GLenum name )我们以GL_EXTENSIONS为参数调用该函数,就能获得当前显卡所支持的所有扩展,像下面这样:const GLubyte *str = glGetString(GL_EXTENSIONS) ; cout << str << endl ;输出的各个扩展之间以空格分隔,如果这些扩展中包含GL_ARB_imaging,那么你就可以使用glBlendEquation这个函数了。当然,这样查询的只是gl扩展,还可以用gluGetString获得glu扩展。在判断了显卡所支持的扩展以后,就可以使用该扩展中所包含的函数了。

4使用glext

这里下载:(http://graphics.ethz.ch/pointsho ... lext_8h-source.html)

a)头文件的包含 这个文件并不是Windows系统中原有的,需要到网上下载。使用的时候有一点要注意,如果程序中还用到了glut.h文件,那么一定要把glext.h放在glut.h的后面,因为glext.h要用到gl.h,而glut.h中包含了gl.h,如果顺序搞错了,编译的时候会有一大堆错误,正确的顺序如下:

#include <iostream>

#include <windows.h>

#include <GL/glut.h>

#include <GL/glext.h>

b)获取函数指针

先定义函数指针,PFNGLBLENDEQUATIONPROC  glBlendEquation = NULL;

再获取函数地址使用wglGetProcAddress函数,注意这一句要加在使用glBlendEquation函数的语句之前才有效,最后后面紧跟着使用glBlendEquation的函数语句,切记不要加在所有子程序的外面,否则获取的指针是无效的

glBlendEquation = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation");

例如可以这样加:

PFNGLBLENDEQUATIONPROC glBlendEquation = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation");

switch(key)

{ case 'a':

case 'A':  //Note: glBlendEquation is a subset of GL_ARB_imaging, please call glGetString

//first to confirm whether your video card support this extension.
                   glBlendEquation(GL_FUNC_ADD) ;

 break ;

         case 's':

         case 'S':

                   glBlendEquation(GL_FUNC_SUBTRACT) ;

                   break ;

4.2 使用glew

glew也是一个扩展库,包含了OpenGL中许多核心及扩展函数,现在的版本是1.3.5,支持OpenGL2.1,可以到这里下载:

http://glew.sourceforge.net/

上面的方法可能有些麻烦,如果已经下载了glew库的话,那么可以直接使用该扩展,但是使用之前首先要确定你的显卡是否支持该扩展。方法如下:首先还是要判断显卡是否支持该扩展,我们这里假定已经支持,

1).包含头文件glew.h,注意这里和上面不同,这回glut.h要放在glew.h的后面了
像下面这样
#include <GL/glew.h>

#include <GL/glut.h>
然后就可以在程序中直接使用glBlendEquation了,其他扩展的判断和使用方法与此类似。
最后还有一点切记!那就是还要调用glewInit() ;来初始化一下方可使用扩展,如下:
GLenum err = glewInit() ;

         if (GLEW_OK != err)
         {
                   MessageBoxA(NULL, "error", "My Window", 1) ;
         }

   你现在可以使用扩展了!

(整理文章)


LinuxOpenGL开发

环境是Fedora 7
首先需要安装OpenGL的开发环境。现在Linux下有很多OpenGL的实现,Fedora 7中已经附带了Mesa,这是OpenGL一个开源的实现。安装Fedora时如果选中了开发环境,那么Mesa可能就已经安装好了。如果你和我一样安装的时候没有选择开发,那么,可以通过yum来在线安装Mesa

首先查找Mesa相关的包:
    yum list mesa*

返回结果应该是和Mesa相关的Lib以及开发包。 

引用:

    Installed Packages
    mesa-libGL.i386                          6.5.2-13.fc7           installed       
    mesa-libGL-devel.i386                    6.5.2-13.fc7           installed       
    mesa-libGLU.i386                         6.5.2-13.fc7           installed       
    mesa-libGLU-devel.i386                   6.5.2-13.fc7           installed       
    mesa-libGLw.i386                         6.5.1-2.fc7            installed       
    mesa-libGLw-devel.i386                   6.5.1-2.fc7            installed       
    mesa-libOSMesa.i386                      6.5.2-13.fc7           installed       
    mesa-libOSMesa-devel.i386                6.5.2-13.fc7           installed       
    mesa-source.i386                         6.5.2-13.fc7           installed

然后安装这些包:
    yum install mesa*

安装完成后,我们就拥有了一个基础的OpenGL开发环境了。

但是仅仅是基础的开发环境是不够的,一般来讲,我们还要安装一个叫做Glut的库,这是一个OpenGL的辅助库,可以让我们创建与平台无关的OpenGL窗口。因此,安装Glut也是必要的。 Glut有很多种实现,在这里我用的是freeglut,是我在Fedore 7的源中找到的。当然还有其他的实现。

查找Glut库的命令如下:
    yum list *glut*

返回结果是 

引用:

    Loading "installonlyn" plugin
    Installed Packages
    freeglut.i386                            2.4.0-11.fc7           installed       
    freeglut-devel.i386                      2.4.0-11.fc7           installed           
    Available Packages
    hugs98-glut.i386                         2006.09-3.fc7          fedora

然后可以从结果中选择自己偏爱的库进行安装,我选的是freeglut,安装命令是
    yum install freeglut*

安装成后,我们就可以开始写我们第一个Linux下的OpenGL程序了。 

引用:

1  /* light.c
此程序利用GLUT绘制一个OpenGL窗口,并显示一个加以光照的球。
3 */
4 /* 由于头文件glut.h中已经包含了头文件gl.hglu.h,所以只需要include 此文件*/
5 # include <GL/glut.h>
6 # include <stdlib.h>
7  
8 /* 初始化材料属性、光源属性、光照模型,打开深度缓冲区 */
9 void init ( void )
10 {
11     GLfloat mat_specular [ ] = { 1.0, 1.0, 1.0, 1.0 };
12     GLfloat mat_shininess [ ] = { 50.0 };
13     GLfloat light_position [ ] = { 1.0, 1.0, 1.0, 0.0 };
14 
15     glClearColor ( 0.0, 0.0, 0.0, 0.0 );
16     glShadeModel ( GL_SMOOTH );
17 
18     glMaterialfv ( GL_FRONT, GL_SPECULAR, mat_specular);
19     glMaterialfv ( GL_FRONT, GL_SHININESS, mat_shininess);
20     glLightfv ( GL_LIGHT0, GL_POSITION, light_position);
21 
22     glEnable (GL_LIGHTING);
23     glEnable (GL_LIGHT0);
24     glEnable (GL_DEPTH_TEST);
25 }
26 
27 /*调用GLUT函数,绘制一个球*/
28 void display ( void )
29 {
30     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
31     glutSolidSphere (1.0, 40, 50);
32     glFlush ();
33 }
34 
35 
36 /* 定义GLUTreshape函数,wh分别是当前窗口的宽和高*/
37 void reshape (int w, int h)
38 {
39     glViewport (0, 0, (GLsizei) w, (GLsizei) h);
40     glMatrixMode (GL_PROJECTION);
41     glLoadIdentity ( );
42     if (w <= h)
43         glOrtho (-1.5, 1.5, -1.5 * ( GLfloat ) h / ( GLfloat ) w, 1.5 * ( GLfloat ) h / ( GLfloat ) w, -10.0, 10.0 );
44     else
45         glOrtho (-1.5 * ( GLfloat ) w / ( GLfloat ) h, 1.5 * ( GLfloat ) w / ( GLfloat ) h, -1.5, 1.5, -10.0, 10.0);
46     glMatrixMode ( GL_MODELVIEW );
47     glLoadIdentity ( ) ;
48 }
49 
50 
51 /* 定义对键盘的响应函数 */
52 void keyboard ( unsigned char key, int x, int y)
53 {
54     /*Esc键退出*/
55     switch (key) 
56     {
57         case 27:
58         exit ( 0 );
59         break;
60     }
61 }
62 
63 
64 int main(int argc, char** argv)
65 {
66     /* GLUT环境初始化*/
67     glutInit (&argc, argv);
68     /* 显示模式初始化 */
69     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
70     /* 定义窗口大小 */
71     glutInitWindowSize (300, 300);
72     /* 定义窗口位置 */
73     glutInitWindowPosition (100, 100);
74     /* 显示窗口,窗口标题为执行函数名 */
75     glutCreateWindow ( argv [ 0 ] );
76     /* 调用OpenGL初始化函数 */
77     init ( );
78     /* 注册OpenGL绘图函数 */
79     glutDisplayFunc ( display );
80     /* 注册窗口大小改变时的响应函数 */
81     glutReshapeFunc ( reshape );
82     /* 注册键盘响应函数 */
83     glutKeyboardFunc ( keyboard );
84     /* 进入GLUT消息循环,开始执行程序 */
85     glutMainLoop( );
86     return 0;
87 }

编译并运行:

    gcc -lglut -o light light.c
    ./light

至此第一个Linux下的OpenGL程序便诞生了.Enjoy it !

linuxopengl编程

linuxopengl编程,首先需要安装glut包。
安装glut
1)下载地址: 
http://fidelio.cacs.louisiana.edu/resources/linux/glut.zip

2)将glut.zip解压:
unzip glut.zip
解压后,里面有一个rpm安装包,一个测试文件,一个glut.h,一个makefile, 这几个文件都非常重要。

3)安装:
pm -i glut-3.7-8.i386.rpm
 (note:  If you already have a later glut, use 
 rpm -i --force glut-3.7-8.i386.rpm)

4)把 "glut.h" 移到"/usr/include/GL":
        mv glut.h /usr/include/GL

5cd /usr/lib
6cp libglut.so.3.7 libglut.so
7)回到glut.zip的目录,运行make ,然后./cube
     会看到测试图形 

#include <GL/glut.h>

void display(void)
{
/* clear all pixels */
   glClear (GL_COLOR_BUFFER_BIT);

/* draw white polygon (rectangle) with corners at
* (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0)
*/
   
   glBegin(GL_POLYGON);
      glColor3f (0.0, 1.0, 1.0);
      glVertex3f (0.25, 0.25, 0.0);
      glColor3f (0.0, 0.0, 1.0);
      glVertex3f (0.75, 0.25, 0.0);
      glColor3f (1.0, 0.0, 0.0);
      glVertex3f (0.75, 0.75, 0.0);
      glColor3f (0.0, 1.0, 0.0);
      glVertex3f (0.25, 0.75, 0.0);
   glEnd();

/* don't wait!
* start processing buffered OpenGL routines
*/
   glFlush ();
}

void init (void)
{
/* select clearing color     */
   glClearColor (0.5, 0.5, 0.0, 0.0);

/* initialize viewing values */
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}

/*
* Declare initial window size, position, and display mode
* (single buffer and RGBA). Open window with "hello"
* in its title bar. Call initialization routines.
* Register callback function to display graphics.
* Enter main loop and process events.
*/
int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize (250, 250);
   glutInitWindowPosition (100, 100);
   glutCreateWindow ("hello");
   init ();
   glutDisplayFunc(display);
   glutMainLoop();
   return 0; /* ANSI C requires main to return int. */
}

////////// gcc -lglut gl.c -o test
先装个freeglut或者mesa
freeglut举例,装好后会在/usr/include/GL中出现glut.h,在/usr/lib下出现libglut.so,如果没有就自己拷一下。

linux下编写OpenGL程序的一些准备工作

需要用到的软件包有两个,glut tmake,分别可以从以下两个网址下载:
http://www.opengl.org/resources/libraries/glut/glut-3.7.tar.gz
ftp://ftp.trolltech.com/freebies/tmake/tmake-1.8.tar.gz

下载后的文件假设都放在/usr/src

首先是安装glut库,以下是从www.linux.com找到的编译glut库的手册。

Install GLUT 3.7 Distribution (optional)

If you installed the MesaDemos/MesaLib package, then you have already installed GLUT 3.7 since it is included with MesaDemos. However, you may be interested in installing the GLUT

manpages and you can skip right to the "Install GLUT manual pages", below ...

Installing GLUT is a bit tricky. I'm not too familiar with imake, the program that it uses to manage the Makefiles, and didn't quite see how to get GLUT to install to where I wanted it (/usr/lib,

but MesaDemos will do this without any trouble though). It can be done manually anyhow:

 cd /usr/src
 tar -xvzf glut-3.7.tar.gz
 cd glut-3.7

 Read the file: README.linux
 cd linux
 READ the file: README
 cp Glut.cf ..
 cd ..
 Edit Glut.cf: remove any Mesa references.
 Replace any -lMesaGL -lMesaGLU with -lGL -lGLU if needed.
 In particular, replace:
  OPENGL = $(TOP)/../lib/libMesaGL.so
  GLU = $(TOP)/../lib/libMesaGLU.so
 with:
  OPENGL = -lGL
  GLU = -lGLU

 ./mkmkfiles.imake
 cd lib/glut
 cp /usr/src/glut-3.7/linux/Makefile .
 Edit the Makefile: remove any Mesa references.
 Replace any -lMesaGL -lMesaGLU with -lGL -lGLU if needed.
 In particular, replace:
  OPENGL = $(TOP)/../lib/libMesaGL.so
  GLU = $(TOP)/../lib/libMesaGLU.so
 with:
  OPENGL = -lGL
  GLU = -lGLU

 make
 ln -s libglut.so.3.7 libglut.so
 ln -s libglut.so.3.7 libglut.so.3
 cp -d libglut.* /usr/lib
 cd ..
 cd gle
 # make a shared lib for libgle
 make
 gcc -shared -o libgle.so.3.7 *.o
 ln -s libgle.so.3.7 libgle.so
 ln -s libgle.so.3.7 libgle.so.3
 cp -d libgle.* /usr/lib
 cd ..
 cd mui
 # make a shared lib for libmui
 make
 gcc -shared -o libmui.so.3.7 *.o
 ln -s libmui.so.3.7 libmui.so
 ln -s libmui.so.3.7 libmui.so.3
 cp -d libmui.* /usr/lib

        # Install the GLUT manual pages (not included with MesaDemos)
 cd /usr/src/glut-3.7
 make SUBDIRS=man Makefile
 cd man/glut
 make install.man
 ldconfig

 cd ../../progs/demos/ideas
 # edit the Makefile, change OPENGL = -lGL and GLU = -lGLU
 make
 ./ideas
 # test compiling some demos
 # take a look at which libraries have to be linked (-lX11 ...) in
 # the Makefiles.  Qt's tmake program available atwww.troll.no
 # is a quick way to make a Makefile but you have to edit it
 # and add the -l needed.
ideas如果运行成功的话,说明glut已经可以用了。

上面的几步中,下载的glut包放在/usr/src目录下,如果放在其他目录下,将/usr/src改为相应的目录即可。
此外应该注意的是两个Makefile文件的修改
  
·  OPENGL = $(TOP)/../lib/libMesaGL.so
  GLU = $(TOP)/../lib/libMesaGLU.so
 
  OPENGL = -lGL
  GLU = -lGLU
因为所指定的目录中没有libMesaGL.solibMesaGLU.so

之后是tmake的配置,后面我们可以用它来生成pro工程文件和makefile文件。

先将下载的tmake解压缩,tar  -zxvf  tmake-1.8.tar.gz
得到tmake-1.8目录,之后设置两个环境变量:PATHTMAKEPATH
PATH=$PATH:/usr/src/tmake-1.8/bin
export PATH
TMAKEPATH=/usr/src/tmake-1.8/lib/linux-g++
export TMAKEPATH

新建一个测试目录test,将glut-3.7目录下的progs/redbook目录下的hello.c复制到test目录中

之后生成一个pro文件:progen  -o hello.pro

然后生成makefile文件:tmake hello.pro -o Makefile

编辑生成的Makefile文件,在加载动态连接库的行里面加入 -lglut -lXi -lXmu

保存,make

./hello 可以看到运行结果就可以了。

首先需要安装glut包。

安装glut

1)下载glut

2)将glut.zip解压:unzip glut.zip解压后,里面有一个rpm安装包,一个测试文件,一个glut.h,一个makefile, 这几个文件都非常重要。

3)安装:pm -i glut-3.7-8.i386.rpm (note: If you already have a later glut, use rpm -i --force glut-3.7-8.i386.rpm)

4)把 "glut.h" 移到"/usr/include/GL":

mv glut.h /usr/include/GL

5cd /usr/lib

6cp libglut.so.3.7 libglut.so

7)回到glut.zip的目录,运行make ,然后./cube

会看到测试图形 

先装个freeglut或者mesa。以freeglut举例,装好后会在/usr/include/GL中出现glut.h,在/usr/lib下出现libglut.so,如果没有就自己拷一下。

然后写个测试程序,如test.c,用以下命令编译:

gcc -lglut test.c -o test

生成可执行文件test,然后:

./test

看到方框说明安装成功:)

如手上没有现成的测试例子,附件是openGL红宝书的第一个例子hello.c

#include 

void display(void)

{

/* clear all pixels */

glClear (GL_COLOR_BUFFER_BIT);

/* draw white polygon (rectangle) with corners at

* (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0) 

*/

glColor3f (1.0, 1.0, 1.0);

glBegin(GL_POLYGON);

glVertex3f (0.25, 0.25, 0.0);

glVertex3f (0.75, 0.25, 0.0);

glVertex3f (0.75, 0.75, 0.0);

glVertex3f (0.25, 0.75, 0.0);

glEnd();

/* don't wait! 

* start processing buffered OpenGL routines 

*/

glFlush ();

}

void init (void) 

{

/* select clearing color */

glClearColor (0.0, 0.0, 0.0, 0.0);

/* initialize viewing values */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

}

/* 

* Declare initial window size, position, and display mode

* (single buffer and RGBA). Open window with "hello"

* in its title bar. Call initialization routines.

* Register callback function to display graphics.

* Enter main loop and process events.

*/

int main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize (250, 250); 

glutInitWindowPosition (100, 100);

glutCreateWindow ("hello");

init ();

glutDisplayFunc(display); 

glutMainLoop();

return 0; /* ANSI C requires main to return int. */

}

Linux环境下开发OpenGL程序,阅读nehe的源代码并注释,这是基于SDL的。第一篇《简单的OpenGL程序》

只有个黑色的窗口 ;-)

################### lesson01.c #######################

#include <stdio.h> 

#include <stdlib.h>

#include <GL/gl.h>

#include <GL/glu.h>

#include "SDL.h"

/* 屏幕宽,高和颜色位数 */

#define SCREEN_WIDTH 640

#define SCREEN_HEIGHT 480

#define SCREEN_BPP 16

/* 设置布尔值 */

#define TRUE 1

#define FALSE 0

/* SDL表面 */

SDL_Surface *surface;

/* 用来释放/销毁程序资源,并返回桌面 */

void Quit( int returnCode )

{

/* 清除窗口 */

SDL_Quit( );

/* 退出 */

exit( returnCode );

}

/* 窗口更改后重新设置视点(观察点) */

int resizeWindow( int width, int height )

{

/* 高与宽的比例 */

GLfloat ratio;

/* 防止除零 */

if ( height == 0 )

height = 1;

ratio = ( GLfloat )width / ( GLfloat )height;

/* 设置视点 */

glViewport( 0, 0, ( GLint )width, ( GLint )height );

/* 选择投影矩阵 */

glMatrixMode( GL_PROJECTION );

glLoadIdentity( );

/* 设置透视 */

gluPerspective( 45.0f, ratio, 0.1f, 100.0f );

/* 选择模型观察矩阵 */

glMatrixMode( GL_MODELVIEW );

/* 重置模型观察矩阵 */

glLoadIdentity( );

return( TRUE );

}

/* 获得键盘按键事件 */

void handleKeyPress( SDL_keysym *keysym )

{

switch ( keysym->sym )

{

case SDLK_ESCAPE:

/* ESC按下时 */

Quit( 0 );

break;

case SDLK_F1:

/* F1按下时

触发全屏模式

*/

SDL_WM_ToggleFullScreen( surface );

break;

default:

break;

}

return;

}

/* OpenGL初始化函数 */

int initGL( GLvoid )

{

/* 启用阴影平滑 */

glShadeModel( GL_SMOOTH );

/* 设置黑色背景 */

glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

/* 设置深度缓存 */

glClearDepth( 1.0f );

/* 启用深度测试 */

glEnable( GL_DEPTH_TEST );

/* 所作深度测试类型 */

glDepthFunc( GL_LEQUAL );

/* 告知系统对透视进行修正 */

glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );

return( TRUE );

}

/* 绘制代码 */

int drawGLScene( GLvoid )

{

/* 计算fps */

static GLint T0 = 0;

static GLint Frames = 0;

/* 清除屏幕及深度缓冲 */

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glLoadIdentity( );

/* 绘制屏幕 */

SDL_GL_SwapBuffers( );

/* 自增长桢的计算 */

Frames++;

{

GLint t = SDL_GetTicks();

if (t - T0 >= 5000) {

GLfloat seconds = (t - T0) / 1000.0;

GLfloat fps = Frames / seconds;

printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);

T0 = t;

Frames = 0;

}

}

return( TRUE );

}

/* 程序主函数 */

int main( int argc, char **argv )

{

/* 通过SDL_SetVideoMode标志 */

int videoFlags;

/* 主循环变量 */

int done = FALSE;

/* SDL事件 */

SDL_Event event;

/* 显示一些信息在屏幕 */

const SDL_VideoInfo *videoInfo;

/* 窗口激活标志 */

int isActive = TRUE;

/* 初始化 SDL */

if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )

{

fprintf( stderr, "Video initialization failed: %s\n",

SDL_GetError( ) );

Quit( 1 );

}

/* 获得视频信息 */

videoInfo = SDL_GetVideoInfo( );

if ( !videoInfo )

{

fprintf( stderr, "Video query failed: %s\n",

SDL_GetError( ) );

Quit( 1 );

}

/* 通过SDL_SetVideoMode标志 */

videoFlags = SDL_OPENGL; /* SDL中启用OpenGL */

videoFlags |= SDL_GL_DOUBLEBUFFER; /* 启用双缓冲 */

videoFlags |= SDL_HWPALETTE; /* 硬件保存调色板 */

videoFlags |= SDL_RESIZABLE; /* 窗口可更改 */

/* 检测表面是否可以保存入内存 */

if ( videoInfo->hw_available )

videoFlags |= SDL_HWSURFACE;

else

videoFlags |= SDL_SWSURFACE;

/* 测试硬件翻转 */

if ( videoInfo->blit_hw )

videoFlags |= SDL_HWACCEL;

/* 设置OpenGL双缓冲 */

SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

/* 获得SDL表面 */

surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,

videoFlags );

/* 验证表面 */

if ( !surface )

{

fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) );

Quit( 1 );

}

/* 初始化 OpenGL */

if ( initGL( ) == FALSE )

{

fprintf( stderr, "Could not initialize OpenGL.\n" );

Quit( 1 );

}

/* 初始化窗口 */

resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );

/* 等待事件 */

while ( !done )

{

/* 获得事件队列 */

while ( SDL_PollEvent( &event ) )

{

switch( event.type )

{

case SDL_ACTIVEEVENT:

/* 不在焦点时候或最小化,不需要绘制

*/

if ( event.active.gain == 0 )

isActive = FALSE;

else

isActive = TRUE;

break;

case SDL_VIDEORESIZE:

/* 获得改变窗口事件 */

surface = SDL_SetVideoMode( event.resize.w,

event.resize.h,

16, videoFlags );

if ( !surface )

{

fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );

Quit( 1 );

}

resizeWindow( event.resize.w, event.resize.h );

break;

case SDL_KEYDOWN:

/* 获得键盘按下 */

handleKeyPress( &event.key.keysym );

break;

case SDL_QUIT:

/* 获得退出请求 */

done = TRUE;

break;

default:

break;

}

}

/* 绘制场景 */

if ( isActive )

drawGLScene( );

}

/* 清除本身并退出 */

Quit( 0 );

/* 不可能执行这里了 */

return( 0 );

}

#################### Makefile ###########################

CC = gcc -Wall -ansi

all:

$(CC) lesson01.c -o lesson01 -lGL -lGLU `sdl-config --cflags --libs`

clean:

@echo Cleaning up...

@rm lesson01

@echo Done.

GLUT 教程

"GLUT"[I] 全称为 OpenGL Utility Toolkit.[/I] Mark J. Kilgard 创作的 GLUT 是我们创建完全独立于窗口系统的 OpenGL 程序成为可能感谢 GLUT, 我们能够在不了解 X Windows 或者 Microsoft Windows 窗口系统本身的情况下编写3D应用程序. Kilgard 编写了GLUT的 X Windows 版本后来, Nate Robins 又将之移植到 Microsoft Windows 系统之上谢谢你们二位你们完成了一项伟大的工作.



在这份教程里, 我将向你介绍一些关于编写 GLUT 应用程序的一些基础为了简单起见这片教程不会介绍复杂的视觉效果.



你需要什么?

首先, 你需要一份最新版本的 GLUT (在这份文档编写的时候我相信是 3.7). 当你完成了这份基础教程后你可以在 GLUT主页 中你可以找到大量的实例.



通过 C语言编写 GLUT 程序你需要以下三个文件

GLUT.H - 你需要在你的源代码中包含这个文件通常情况下这个文件应该放在你系统的包含目录下的 GL 文件夹中 

GLUT.LIB (SGI windows版本以及 glut32.lib (微软版本) - 这个文件必须被连接到你的程序中确保它放在 LIB 目录中 

glut32.dll (Windows) 和 glut.dll (SGI Windows版本) - 根据你所使用的OpenGL选择一个如果你正在使用微软公司的版本那么你必须选择 glut32.dll. 你应该把DLL放置在你的系统文件夹中

设置Visual C/C++ 6.0

Visual C/C++的工程有两个重要选项: Console (控制台和 Win32. 应用程序将会有两个窗口一个控制台窗口以及一个 OpenGL 窗口选择 Win32 仍然可以让你在不需要关心Windows程序设计的情况下编写 GLUT 程序你需要做以下设置

选择 Project -> settings 

选择 Link 选项卡 

从 Category 中选择 Output 

在 Entry-point synmbol 文本框中键入 mainCRTStartup

对于已存在的控制台工程, 有一个简单的办法将它转换成Win32应用程序

根据上面的步骤修改入口点 

在 Project options 文本框中用 subsystem:windows 覆盖 subsystem:console

或者你可以直接在你的源代码开头处添加:



代码 



// #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) 



注意: 这是一行注释

如此一来, 应用程序就不会出现控制台窗口而只是一个 OpenGL 窗口了Visual C/C++ 中你需要一下步骤来连接一个 GLUT 程序

选择 Proejct/Settings 

选择 LINK 选项卡 

添加一下文件到 Object/library: opengl32.lib glut32.lib glu32.lib

请注意: 我同时添加了glu32.lib 和 opengl32.lib. 他们是标准OpenGL.



好的,现在一切准备就绪我们可以开始编写 GLUT 应用程序了如果有任何不清楚的地方请您告诉我您的回馈非常之重要.

在这一节中, 我们将会建造应用程序的主函数(main function). 主函数将会将会完成程序的初始化并启动事件处理循环所有函数都有一个前缀 glut , 初始化函数的前缀是 glutInit. 我们首先必须调用函数 glutInit.



代码 



void glutInit(int *argc, char **argv); 

//参数:

//argc - 一个指向主函数 argc 变量的 未经修改 的指针

//argv - 一个指向主函数 argv 变量的 未经修改 的指针

 

初始化 GLUT 本身以后我们将会定义我们的窗口首先我们建立窗口的位置例如在窗口的左上角要实现这个功能我们需要调用函数 glutWindowsPosition.



代码 



void glutInitWindowPosition(int x, int y); 

//参数:

//x- 距离屏幕左边的像素数默认值是 -1, Windows系统决定窗口的位置如果没有没有采用默认值那么你应该使用一个合适正值作为实参.

//y- 距离屏幕屏幕顶端的像素数其余同上.

请注意, 这些参数只是给窗口管理器的一个建议值我们创建的窗口可能会处于不同的位置上不过这很少发生接下来我们要决定窗口的大小为了做到这一点我们需要使用函数 glutInitWindowSize.



代码 



void glutInitWindowSize(int width, int height); 

参数:

width - 窗口的宽度

height - 窗口的高度

 

同样的, 高和宽也只是一个建议值请避免使用负值.

然后我们需要定义显示模式, 我们使用 glutInitDisplayMode 函数.



代码 



void glutInitDisplayMode(unsigned int mode) 

参数:

mode - 指定显示模式

//mode 参数是一个 GLUT 预定义常数的复合布尔型 (位或). 你可以使用 mode 来指定颜色以及缓冲区的数量和类型.



这些常数是:

GLUT_RGBA or GLUT_RGB - 默认颜色模式 

GLUT_INDEX - 颜色索引(?) 模式



显示模式允许你选择单或双缓冲区窗口. 相关常数是:

GLUT_SINGLE - 单缓冲区窗口 

GLUT_DOUBLE - 双缓冲区平滑动画需要



这里还有更多关于缓冲区的常数:

GLUT_ACCUM - 聚集缓冲区 

GLUT_STENCIL - The stencil buffer (...翻译不出来

GLUT_DEPTH - 深度缓冲区



现在, 假如你想要创建一个RGB窗口单缓冲以及一个深度缓冲区你需要把相关的常数去 OR 在一起来创建一个正确的常口



代码 

...

glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT DEPTH);

...

经过以上步骤, 我们可以调用 glutCreateWindow 函数了



代码 



int glutCreateWindow(char *title); 



参数:

title - 窗口标题

 

glutCreateWindows 函数的返回值是索创建窗口的标示符你以后会用到这个标示符.

现在, 我们把上面的代码集合起来看看一次完整的窗口初始化:



代码 



#include 



void main(int argc, char **argv) {

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);

glutInitWindowPosition(100,100);

glutInitWindowSize(320,320);

glutCreateWindow("3D Tech- GLUT Tutorial");

}

 

请注意包含文件, 我们需要 GLUT 的包含文件.



如果你运行了这段代码, 那么你将看到一个黑色的控制台窗口但是没有任何OpenGL窗口几秒钟以后这个窗口也消失了在我们开始渲染之前 我们还要做两件事情首先是告诉 GLUT 系统负责渲染的函数:

我们来创建一个渲染函数的例子. 这个函数将会清空颜色缓冲区并画出两个三角形:



代码 



void renderScene(void) {

glClear(GL_COLOR_BUFFER_BIT);

glBegin(GL_TRIANGLES);

 glVertex3f(-0.5,-0.5,0.0);

 glVertex3f(0.5,0.0,0.0);

 glVertex3f(0.0,0.5,0.0);

glEnd();

glFlush();

}



你可以给函数起任意的名字. 然而你必须告诉 GLUT 来使用这个函数进行渲染这叫做 注册回叫(callback) 函数. GLUT 将会在需要渲染的时候呼叫这个函数现在我们来告诉 GLUT 一旦我们的窗口被破坏(注意当窗口第一次被创建的时候这个函数也会被呼叫)

, 就调用renderScene函数. GLUT 中有一个函数接受一个函数指针作为参数它将这个指针指向的函数作为渲染函数



代码 



void glutDisplayFunc(void (*func)(void)); 

参数:

func - 渲染函数指针, NULL在这里非法 

 

One last thing missing, that is telling GLUT that we're ready to get in the application event processing loop. GLUT provides a function that gets the application in a never ending loop, always waiting for the next event to process. The GLUT function is glutMainLoop, and the syntax is as follows: 



我们最后要做, 就是让程序进入事件处理循环. GLUT 给我们准备了一个函数来使程序进入一个无限循环(死循环), 永远在等待下一个需要处理的事件这个函数就是 glutMainLoop:



代码 



void glutMainLoop(void) 

 

The code so far is presented bellow. Note that we've added an include statement in order to start using standard OpenGL functions, like glClear, glBegin, glVertex3f, and glEnd. 



以下是完整的代码. 我们添加了一个新的包含文件以便于我们使用OpenGL的函数比如 glClear, glBegin, glVertex3f 和 glEnd.



如果你运行这你将会看到一个控制台窗口, 然后是一个画有白色三角形OpenGL窗口

代码 

#include "gl/glut.h"

void renderScene(void) {

glClear(GL_COLOR_BUFFER_BIT);

glBegin(GL_TRIANGLES);

glVertex3f(-0.5,-0.5,0.0);

glVertex3f(0.5,0.0,0.0);

glVertex3f(0.0,0.5,0.0);

glEnd();

glFlush();

}

void main(int argc, char **argv) {

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);

glutInitWindowPosition(100,100);

glutInitWindowSize(320,320);

glutCreateWindow("3D Tech- GLUT Tutorial");

glutDisplayFunc(renderScene);

glutMainLoop();

}

GLUT基础

[译者注] 我是一个OpenGL新手,这是我第一次翻译OpenGL文章,翻译不足之处请多见谅! 

         希望和大家,特别的OpenGL的热爱者多交流。 

 MSN:wangzhi0417@hotmail.com 

在本篇教程中我将谈及如何在VC++中设置和使用OpengGL和GLUT。我将引导你初始化你的GLUT显示,打开一个窗口和显示一个三角形。你将学习的内容是你以后创建更加复杂的GLUT工程的基础。 

  

    

什么是GLUT? 

GLUT代表OpenGL Utility Toolkit。它是由Mark Kilgard为OpenGL写的一个API。创建使用GLUT比传统的Win32 OpenGL更加容易,对初学者来说,是大有裨益的。因为GLUT处理输入和窗体的创建,GLUT代码和平台无关,意味着你写的任何应用都可以在任何平台上运行(除非你开始添加DirectSound代码)。 

  

获得GLUT文件 

你可以从这里下载GLUT最新的版本。 

当你已经下载并解压了文件,拷贝glut32.dll到你的windows\system目录,拷贝glut32.lib到你的编译器的lib目录并将glut.h拷贝到你的编译器的include\gl目录。现在你准备就绪了。 

创建你的GLUT工程 

启动VC++,建立一个空的控制台应用程序。 

在project>settings中设置链接到glut32.lib,glu32.lib和opengl32.lib。 

  

程序 

以下代码包含了要用到的库的头文件并且声明我们的函数。 

#include <windows.h>          //header file for windows 

#include <gl\gl.h>            //header file for openGL 

#include <gl\glu.h>           //header file for the openGL utility library 

#include <gl\glut.h>         //header file for GLUT 

  

static void redraw(void);          //declarations 

int main(int argc, char **argv); 

  

变量argc包含了传递到程序的参数的数目,argv是一个指向参数的指针。我们不需要特别地为这两个参数担忧,只需要将他们传给glutInit(),让其能够处理发送到GLUT的任何命令行参数。 

  

glutInitDisplayMode函数用来设置显示模式。我们可以用以下的flags来调用它: 

GLUT_RGB 指明我们想在我们的窗口中使用一个RGB颜色缓存区。 

GLUT_DOUBLE 指明我们想要一个双缓冲区。双缓冲区使我们在图像被送到屏幕前完成绘制,从而防止闪烁。 

GLUT_DEPTH 指明我们想要一个深度缓冲区。深度缓冲区确保靠近camera的物体永远在较远的物体上面,否则输出容易杂乱。当我们只绘制单个的三角形的时候,这就没有必要,这是一个很好的应用,所以我们将一直包含它。 

  

  

glutCreateWindow()函数创建供我们绘制的窗口。glutDisplayFunc()指明我们绘制屏幕的函数,我们将在下面介绍。GLUT在显示需要更新的时候调用这个函数。 

int main(int argc, char **argv) 

  glutInit(&argc,argv);                  //initializes the GLUT framework 

  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);  

//sets up the display mode 

  glutCreateWindow("My first GLUT program");            //creates a window 

  glutDisplayFunc(redraw);                //specifies our redraw function 

  

下面我们需要设置投影矩阵(projection matrix)。投影矩阵是一个4 x4的矩阵,用来将点从他们的和camera有关的位置转换到屏幕上的位置。我们用它来指明我们的场景(scene)怎样投影到屏幕。为了改变它,我们需要用GL_PROJECTION参数调用glMatrixMode()。gluPerspective()函数为我们创建一个透视变换的投影矩阵。我们所要做的是指定视角(view angle),宽高比(aspect ratio)和远近的剪切平面的位置。 

  

glMatrixMode(GL_PROJECTION);   //changes the current matrix to the //projection matrix 

  

  //sets up the projection matrix for a perspective transform 

  gluPerspective(45,     //view angle 

                 1.0,    //aspect ratio 

                 10.0,   //near clip 

                 200.0); //far clip 

  

当我们完成时,我们将当前的矩阵切换成modelview矩阵。modelview矩阵是一个4 x4矩阵,用来将点从它们的实际位置(world space)转换成相对于camera的位置。这个矩阵被我们用来指定我们camera的位置和我们想绘制的任何物体的位置,glutMainLoop()函数是GLUT框架中的主循环函数,我们下一步将调用它。 

  

  glMatrixMode(GL_MODELVIEW);   //changes the current matrix to the  //modelview matrix 

  glutMainLoop();               //the main loop of the GLUT framework 

  

  return 0; 

  

下一步我们需要创建我们的redraw()函数,其作用是绘制我们的三角形。用GL_COLOR_BUFFER_BIT和GL_DEPTH_BUFFER_BIT调用glClear()将清空我们窗口的颜色和深度缓冲区。我们需要在我们绘制之前做这个工作。 

  

  

static void redraw(void)                       //all drawing code goes here 

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  

//clears the colour and depth buffers 

现在我们差不多准备开始绘制了。首先我们需要用glPushMatrix()来存储我们camera的位置(在x,y,z轴的(0,0,0) - 我们世界的中心),并且将它在Z轴移动100,有效地将照相机向后移,使我们能看清楚我们所绘制的图形。因为modelview矩阵指定了相对于camera的绘制位置,为移动camera我们需要以camera相反的转换来变换modelview矩阵,所以移动照相机到(0,0,100),我们变换modelview矩阵为(0,0,-100)。这和移动我们的三角形到(0,0,-100)有相同的效果。 

glPushMatrix();   //saves the current matrix on the top of the matrix stack 

  glTranslatef(0,0,-100); //translates the current matrix 0 in x, 0 in //y and -100 in z 

现在我们开始绘制三角形。为了做这个,我们需要调用glBegin(GL_TRIGANGLES),它将告诉OpenGL我们将要开始绘制三角形。OpenGL而后将每三个顶点视作一个三角形的顶点,并且在调用glEnd()时将三角形绘制到我们的窗口。 

  

在glBegin()和glEnd()之间,我们需要用glVertex3f指定3个顶点。在每个glVertex3f()调用中的3个值是顶点在世界空间中的X,Y和Z坐标。我们也能用在调用glVertex3f前调用glColor3f()指定每个顶点的颜色。我们调用glColor3f()的参数是组合成颜色的红色、绿色和蓝色分量(从0到1)。OpenGL将在三角形中混合这些颜色。 

  

  

  

  glBegin(GL_TRIANGLES);  //tells OpenGL that we're going to start  //drawing triangles 

  glColor3f(1,0,0);       //sets the current colour to red 

  glVertex3f(-30,-30,0);  //specifies the first vertex of our triangle 

  

  glColor3f(0,1,0);       //sets the current colour to green 

  glVertex3f(30,-30,0);   //specifies the second vertex of our triangle 

  

  glColor3f(0,0,1);       //sets the current colour to blue 

  glVertex3f(-30,30,0);   //specifies the third vertex of our triangle 

  glEnd();                //tells OpenGL that we've finished drawing 

  

  

下一步我们用glPopMatrix()从矩阵栈(matrix stack)中重新得到我们先前保存的矩阵,将camera的位置设置回(0,0,0),为下一帧做准备。因为我们使用了双缓冲,所有的绘制工作在后缓冲区(back buffer)(不可见的缓冲区)中完成。现在帧绘制完成,我们调用glutSwapBuffers()来交换前缓冲区(可见的缓冲区)和后缓冲区,使我们所绘制的可见。 

  glPopMatrix();         //retrieves our saved matrix from the top of the // matrix stack 

  glutSwapBuffers();      //swaps the front and back buffers 

}                         //The end of our program! 

  

好的!在我们程序和教程的结束,编译你的程序试试。 

希望通过本篇教程的帮助,你现在应该能建立和初始化一个GLUT程序并绘制三角形。如果你想对这片教程反馈意见或是有任何问题,请发邮件给我. 

GLUT 教程

                                            体系 

  

GLUT 代表OpenGL Utility TookitMark J.Kilgard 为了使OpenGL应用程序结构能够真正独立于窗口系统构思了GLUT库。感谢GLUT,使我们可以写程序而不必去学关于X windows或者微软自己的窗口系统。KilgardX windows上应用这个库,后来Nate Robins把它扩展到微软的窗口系统。感谢他们,他们做的太棒了。 

  

在这个教程里,我将给你介绍基本的使用GLUT建立一个应用程序。这个教程将不介绍如何去渲染那些比较精美的视觉场景。这是为了保持代码尽可能的简洁。 

  

你需要什么! 

为了能够使用GLUT写程序,你应该有最新版本的GLUT库。(GLUT库的下载,网上搜一下,很多的。) 

http://www.opengl.org/documentation/specs/glut/spec3/spec3.html 这个网站里有很多GLUT库里函数的原型定义。 

  

为了用GLUT写一个C语言程序你需要有三个文件: 

1glut.h—这个头文件是要包含到你的代码里的去的。一般把这个文件放到、include\gl文件夹里。 

2glut.libglut32.libglut.libSGI的,glut32.libMicrosoft的。好像就是看你用的什么操作系统了。一般down的这两个文件都有)这个文件必须连接到你的程序。所以必须放在lib文件夹里。 

3:glut32.dllwindows)和glut.dllSGI--这个文件必须放在system32文件夹里。 

  

VC/VC6.0里的设置 

Visual C/C++里建立工程可以有两个选择:控制台(console)和Win32。第一个是最常用的,选第一个的话,应用程序将会有两个窗口,一个控制台窗口(就是命令行那样的窗口)一个OpenGL窗口。选择Win32的也有可能用GLUTwindows编程结合建立一个应用程序。所有你必须做的是改变一个设置。 

  

主菜单中选择“工程”(project->“设置”(setting) 

对话框中选择“连接”(link)标签。 

在“分类”(Category)组合框里选择“输出”(output) 

再在“入口点”(Entry-point symbol)文本框里键入“mainCRTStartup” 

  

对一个现有的控制台应用程序,有一个简单的办法把它转换成Win32应用程序,这样可以摆脱那个命令行窗口。 

1:接着上面的添加入口点的那个标签。 

2:在“工程选项”(Project options)文本框里把“subsystem:console”替换成“subsystem:windows” 

  

你也可以仅仅在你的代码的开头添加下面的这一行代码,而不进行上述设置。 

  

#pragma commentlinker,/subsystem:\windows\/entry:\mainCRTStartup\””) 

  

现在这个应用程序就没有控制台窗口,只有OpenGL窗口。为了把GLUT连接到一个程序里,你还得进行以下几步。 

1:选择“工程”(project->“设置”(settings)。 

2:选择“连接”(Link)标签。 

3:增加下面的文件到“对象/库模块”(Object/library modules):OpenGL32.lib,glut32.lib,glu32.lib.(一般加一个glut32.lib就可以了)。 

  

上面添加了glut32.lib,和opengl32.lib。这两个都是标准OpenGL的库,glu是一个API来自标准的OpenGL扩充。 

  

VS.NET里使用OpenGL 

很多人在使用VS.NET来建立OpenGL应用程序时,都遇到了一个小问题:一个编译器错误。根据我所知道的,好像仅存在与VS 2003VS2005的编译器里。下面是VS2005里产生的错误。 

c:\programas\microsoft visual studio 8\vc\include\stdlib.h(406) :  
         error C2381: 'exit' : redefinition; __declspec(noreturn) differs 
        c:\opengl\toolkits\includes\gl\glut.h(146) : see declaration of 'exit' 
  

这个问题好像是因为包含文件时glut.hstdlib.h的前面。改下顺序就可以解决这个问题。 

把 
#include <GL/glut.h> 
#include <stdlib.h> 
改成 
#include <stdlib.h> 
#include <GL/glut.h> 
  
OK,所有的都设置好了,让我们开始学习怎么去写GLUT程序。如果这里还有什么地方不清楚的请告诉我,我会试着改进的,你的反馈很总要。 

  

(这是本人翻译的第一个网上的英文教程。我的英语水平很不好。所以很多地方没说明白。还望各位指正。这也是我学习英语的一个过程。谢谢。 

原文来自http://www.lighthouse3d.com/opengl/glut/。)

初始化设置 

  

在这个部分我们将在我们的程序里建立一个main函数,这个main函数将完成必须的初始化和开启事件处理循环。所有的GLUT函数都有glut前缀并且那些完成一些初始化的函数有glutInit前缀。你首先要做的是调用函数glutInit()。 

Void glutInit(int*argc,char**argv); 

参数: 

Argc:一个指针,指向从main()函数传递过来的没更改的argc变量。 

Argv:一个指针,指向从main()函数传递过来的没更改的argv变量。 

在初始化GLUT后,我们开始定义我们的窗口。首先确定窗口位置(它默认的是屏幕左上角),我们使用函数glutInitWindowPosition()。 

Void glutInitWindowPositon(int x,int y); 

参数: 

X: 距离屏幕左边的像素数。-1是默认值,意思就是由窗口管理程序决定窗口出现在哪里。如果不使用默认值,那你就自己设置一个值。 

Y:距离屏幕上边的像素数。和X一样。 

注意,参数仅仅是对窗口管理程序的一个建议。尽管你精心的设置了窗口位置,window返回的可能是不同的位置。如果你设置了,一般会得到你想要的结果。接下来我们设置窗口大小,使用函数glutInitWindowSize()。 

Void glutInitWindowSize(int width,int height); 

参数: 

Width:窗口的宽度。 

Height:窗口的高度。 

  

同样widthheight也只是一个参考数字。避免使用负数。 

  

接下来。你应该使用函数glutInitDisplayMode()定义显示方式。 

Void glutInitDisplayMode(unsighed int mode) 

参数: 

Mode――可以指定下列显示模式 

Mode参数是一个GLUT库里预定义的可能的布尔组合。你使用mode去指定颜色模式,数量和缓冲区类型。 

指定颜色模式的预定义常量有: 

1GLUT_RGBA或者GLUT_RGB。指定一个RGBA窗口,这是一个默认的颜色模式。 

2GLUT_INDEX。指定颜色索引模式。 

这个显示模式还允许你选择单缓冲区或双缓冲区窗口。 

1GLUT_SINGLE.单缓冲区窗口。 

2GLUT_BUFFER.双缓冲区窗口,这是产生流畅动画必须选的。 

还可以指定更多,如果你想指定一组特殊的缓冲的话,用下面的变量: 

1GLUT_ACCUM.累积缓冲区。 

2GLUT_STENCIL.模板缓冲区。 

3GLUT_DEPTH.深度缓冲区。 

  

假定你想要一个有单缓冲区,深度缓冲区的RGB窗口,你用“或“(|)操作符来建立你想要的显示模式。 

……………. 

glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE|GLUT|DEPTH); 

……………. 

  

经过上面的这些步骤后,就可以调用函数glutCreateWindow()来创建窗口了。 

Int glutCreateWindow(char* title); 

参数: 

Title:设置窗口的标题。 

glutCreateWindow()的返回值是一个窗口标识符。后面你可以在GLUT里使用这个标识符,不过这个超出了本小节的范围。 

  

现在就有一些代码来完成所有的初始化操作。 

#include<gl/glut.h> 

void main(int argc,char**argv) 

     glutInit(&argc,argv); 

     glutInitDisplayMode(GLUT_DEPTH|GLUT_SINGLE|GLUT_RGBA); 

     glutInitWindowPosition(100,100); 

glutInitWindowSize(320,320); 

glutCreateWindow(“GLUT Tutorial”); 

如果你运行上述代码,你将会得到一个空的黑的控制台窗口,而没有OpenGL窗口。并且控制台窗口将很快消失。 

在我们渲染一些东西前,还有两件事需要处理。第一告诉GLUT哪个函数负责渲染。我们创建一个简单的渲染的函数。下面的这个函数将会清除颜色缓冲区并画一个三角形。 

... 

void renderScene(void) { 

         glClear(GL_COLOR_BUFFER_BIT); 

         glBegin(GL_TRIANGLES); 

                 glVertex3f(-0.5,-0.5,0.0); 

                 glVertex3f(0.5,0.0,0.0); 

                 glVertex3f(0.0,0.5,0.0); 

         glEnd(); 

         glFlush(); 

上面的函数的名字你可以自己取一个。现在你必须告诉GLUT使用我们上面的函数来进行渲染。这个叫寄存回调。。让我们告诉GLUT这个函数renderScene应该被使用。当需要重画的时候GLUT有一个只传递一个函数名称参数的函数(以函数名为形参的函数)就会被调用。 

void glutDisplayFunc(void (*func)(void)); 

参数: 

func: 当窗口需要被重绘是调用的函数的名称。注意使用NULL作为实参是错误的。 

最后一件事是告诉GLUT我们准备进入应用程序事件处理循环。GLUT提供了一个函数让程序进入一个永不结束的循环。一直等待处理下一个事件。函数是glutMainLoop()。 

void glutMainLoop(void) 

到目前为止所有的代码都列在下面。如果你运行代码,将会得到一个控制台窗口,和一个画着一个白色三角形的OpenGL窗口,出现在你设置的位置,并有着你设置的尺寸。 

#include <GL/glut.h> 

  

  

void renderScene(void) { 

         glClear(GL_COLOR_BUFFER_BIT); 

         glBegin(GL_TRIANGLES); 

                 glVertex3f(-0.5,-0.5,0.0); 

                 glVertex3f(0.5,0.0,0.0); 

                 glVertex3f(0.0,0.5,0.0); 

         glEnd(); 

         glFlush(); 

  

void main(int argc, char **argv) { 

         glutInit(&argc, argv); 

         glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); 

         glutInitWindowPosition(100,100); 

         glutInitWindowSize(320,320); 

         glutCreateWindow("3D Tech- GLUT Tutorial"); 

         glutDisplayFunc(renderScene); 

         glutMainLoop(); 

GLUT教程 

                                  为改造窗口做准备 

下载下面的VC工程并运行它(glut0.zip)(这个就是上一节的工程)。你将看到两个窗口:一个控制台窗口,一个OpenGL窗口。现在改变窗口大小使高度与宽度不再相等,这时三角形发生变形。这会发生是因为你没有正确设置投影矩阵。默认的是透视投影矩阵且高宽比为1.因此高宽比改变了,投影就会变形。因此只要高宽比改变了,投影就应该重新计算。 

  

GLUT定义了当窗口大小改变时哪一个函数应该被调用。此外,这个函数还会在窗口初次被创建时调用,保证初始化窗口不是正方形的时候渲染也不会变形出错。 

  

这个函数是glutReshapeFunc()。 

void glutReshapeFunc(void(*func)int width,int height); 

参数: 

func: 指负责设置正确投影的函数的名称。 

因此我们必须做的第一件事是回到main()函数。在上一章的代码里加入对glutReshapeFunc()的调用,让我们把负责窗口尺寸的函数叫做changeSize。现在的代码如下。 

void main(int argc, char **argv) { 

         glutInit(&argc, argv); 

         glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); 

         glutInitWindowPosition(100,100); 

         glutInitWindowSize(320,320); 

         glutCreateWindow("3D Tech- GLUT Tutorial"); 

         glutDisplayFunc(renderScene); 

          

         // Here is our new entry in the main function  

         glutReshapeFunc(changeSize); 

          

         glutMainLoop(); 

下面我们需要做的就是定义函数changeSize()。从glutReshapeFunc()函数的声明可以看到,changSize()函数有两个形参。。这两个参数代表新的窗口高度和宽度。 

void changeSize(int w, int h) { 

  

         // 防止除数即高度为

         // (你可以设置窗口宽度为0). 

         if(h == 0) 

                 h = 1; 

  

         float ratio = 1.0* w / h; 

  

         // 单位化投影矩阵。 

         glMatrixMode(GL_PROJECTION); 

         glLoadIdentity(); 

          

         // 设置视口大小为增个窗口大小 

         glViewport(0, 0, w, h); 

  

         // 设置正确的投影矩阵 

         gluPerspective(45,ratio,1,1000); 

        //下面是设置模型视图矩阵 

         glMatrixMode(GL_MODELVIEW); 

         glLoadIdentity(); 

         gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0,0.0f,1.0f,0.0f); 

我们在上一小段代码里引进了一些函数。下面让我们详细讲解,以免让你感到很迷茫。 

第一步是计算高宽比(wight/height)。注意为了计算正确,我们必须保证高度不为0。 

  

接着,我们设置当前矩阵为投影矩阵,这个矩阵定义了一个可视空间(viewing volume)。 

我们调用一个单位矩阵来初始化投影矩阵。然后我们用函数glViewport把视口设置为整个窗口。你也可以设置不同的值。函数中(00)指定了视口的左下角,(w,h)指定了视口矩形的大小。注意这个坐标是和客户区域有关的,而不是屏幕坐标。。 

  

gluPerspective函数是其他OpenGL库(GLU库)里的一个函数。(gluPerspective函数的参数,设置请参见其他书籍。我并不想在GLUT讲解里再加入其他一些OpenGL内容的讲解。) 

  

最后就是设置模型观测矩阵。调用GL_MODELVIEW把当前矩阵设为模型观测矩阵。gluLookAt()也是GLU库里的一个函数,其参数详细设置参见其他书籍。 

  

下面是这章的VC工程(glut1.zip),你可以自己设置大小,改变参数值。要真正弄懂程序究竟是怎样运行的。 

GLUT教程 

                      动画 

到现在为止,我们有了一个画着一个白色三角形的OpenGL窗口,但一点也不激动人心。现在让我们在这节教程里,让这个三角形自己旋转起来。 

  

让我们回到main()函数,增加些额外的设置。首先告诉GLUT我们想要一个双缓冲区。双缓冲区通过在后一个缓冲区里绘画,并不停交换前后缓冲区(可见缓冲区),来产生平滑的动画。使用双缓冲区可以预防闪烁。 

…………. 

glutInitDisplayMode(GL_DEPTH|GLUT_DOUBLE|GLUT_RGBA); 

………… 

接着我们要做的是告诉GLUT,当应用程序空闲的时候渲染函数应该被调用。这导致GLUT一直调用渲染函数而产生动画。GLUT提供了一个函数:glutIdleFunc.这个函数使另一个函数在程序空闲的时候就会被调用。 

void glutIdleFunc(void(*func)(void)); 

参数: 

func:在程序空闲的时候就会被调用的函数的函数名。 

按照我们的想法,当程序空闲时应该调用的函数是我们先前定义的渲染函数: renderScene。由于OpenGL默认没有开启深度测试,我们还要开启它,这样我们才能知道哪个物体在前面,哪个物体在后面。深度测试的开启在main()函数里,下面看看现在的main函数。 

void main(int argc, char **argv) { 

         glutInit(&argc, argv); 

          

         // 在这里设置双缓冲区。 

         glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 

          

         glutInitWindowPosition(100,100); 

         glutInitWindowSize(320,320); 

         glutCreateWindow("3D Tech- GLUT Tutorial"); 

         glutDisplayFunc(renderScene); 

          

         // 这里让程序空闲时调用renderScene, 

         glutIdleFunc(renderScene); 

          

         glutReshapeFunc(changeSize); 

          

         //开启深度测试。 

         glEnable(GL_DEPTH_TEST); 

         glutMainLoop(); 

下面就是设置渲染函数renderScene。我们定义了一个浮点型变量并初始化为0.0,下面在renderScene函数加一些必须的东西。 

  

float angle=0.0; 

  

void renderScene(void) { 

  

         //注意我们这里清除了深度缓冲区。 

         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

          

         //保存当前模型视图矩阵。 

         glPushMatrix(); 

         

         glRotatef(angle,0.0,1.0,0.0); 

         glBegin(GL_TRIANGLES); 

                 glVertex3f(-0.5,-0.5,0.0); 

                 glVertex3f(0.5,0.0,0.0); 

                 glVertex3f(0.0,0.5,0.0); 

         glEnd(); 

          

         // 弹出堆栈 

         glPopMatrix(); 

          

         // 交换缓冲区 

         glutSwapBuffers(); 

          

         // angle自动增加。 

         angle++; 

glutSwapBuffers函数交换了前后缓冲区,函数原型如下: 

void glutSwapBuffers(); 

好了,我们得到了一个旋转的三角形,你可以下载这个VC工程在这里(glut2.zip)。很棒吧?。但再次说下,我们不会渲染一些十分精美的画面,这是为了保持代码的简洁。也因为主要是学习GLUT。 

GLUT教程 

             键盘输入 

GLUT允许我们编写程序,在里面加入键盘输入控制,包括了普通键,和其他特殊键(如F1,UP)。在这一章里我们将学习如何去检测哪个键被按下,可以从GLUT里得到些什么信息,和如何处理键盘输入。 

  

到现在,你应该注意到了,只要你想控制一个事件的处理,你就必须提前告诉GLUT,哪个函数将完成这个任务。到现在为止,我们已经使用GLUT告诉窗口系统,当窗口重绘时我们想调用哪个渲染函数,但系统空闲时,哪个函数被调用。和当窗口大小改变时,哪个函数又将被调用。 

  

相似的,我们必须做同样的事来处理按键消息。我们必须使用GLUT通知窗口系统,当某个键被按下时,哪个函数将完成所要求的操作。我们同样是调用一个函数注册相关的回调函数。 

  

当你按下一个键后,GLUT提供了两个函数为这个键盘消息注册回调。第一个是glutKeyboardFunc。这个函数是告诉窗口系统,哪一个函数将会被调用来处理普通按键消息。 

普通键是指字母,数字,和其他可以用ASCII代码表示的键。函数原型如下: 

void glutKeyboardFunc(void(*func)(unsigned char key,int x,int y)); 

参数: 

func: 处理普通按键消息的函数的名称。如果传递NULL,则表示GLUT忽略普通按键消息。 

这个作为glutKeyboardFunc函数参数的函数需要有三个形参。第一个表示按下的键的ASCII码,其余两个提供了,当键按下时当前的鼠标位置。鼠标位置是相对于当前客户窗口的左上角而言的。 

  

一个经常的用法是当按下ESCAPE键时退出应用程序。注意,我们提到过,glutMainLoop函数产生的是一个永无止境的循环。唯一的跳出循环的方法就是调用系统exit函数。这就是我们函数要做的,当按下ESCAPE键调用exit函数终止应用程序(同时要记住在源代码包含头文件stdlib.h)。下面就是这个函数的代码: 

void processNormalKeys(unsigned char key,int x,int y) 

      if(key==27) 

            Exit(0); 

  

下面让我们控制特殊键的按键消息。GLUT提供函数glutSpecialFunc以便当有特殊键按下的消息时,你能注册你的函数。函数原型如下: 

void glutSpecialFunc(void (*func)(int key,int x,int y)); 

参数: 

func: 处理特殊键按下消息的函数的名称。传递NULL则表示GLUT忽略特殊键消息。 

  

下面我们写一个函数,当一些特殊键按下的时候,改变我们的三角形的颜色。这个函数使在按下F1键时三角形为红色,按下F2键时为绿色,按下F3键时为蓝色。 

  

void processSpecialKeys(int key, int x, int y) { 

  

         switch(key) { 

                 case GLUT_KEY_F1 :  

                                   red = 1.0;  

                                   green = 0.0;  

                                   blue = 0.0; break; 

                 case GLUT_KEY_F2 :  

                                   red = 0.0;  

                                   green = 1.0;  

                                   blue = 0.0; break; 

                 case GLUT_KEY_F3 :  

                                   red = 0.0;  

                                   green = 0.0;  

                                   blue = 1.0; break; 

         } 

上面的GLUT_KEY_*glut.h里已经被预定义为常量。这组常量如下: 

GLUT_KEY_F1               F1 function key 

GLUT_KEY_F2               F2 function key 

GLUT_KEY_F3               F3 function key 

GLUT_KEY_F4               F4 function key 

GLUT_KEY_F5               F5 function key 

GLUT_KEY_F6               F6 function key 

GLUT_KEY_F7               F7 function key 

GLUT_KEY_F8               F8 function key 

GLUT_KEY_F9               F9 function key 

 

 

  

 作者: 無與JAY倫比  2007-12-12 00:15   回复此发言    

 

--------------------------------------------------------------------------------

 

2 OpenGL---GLUT教程(五) GLUT键盘控制  

 GLUT_KEY_F10              F10 function key 

GLUT_KEY_F11              F11 function key 

GLUT_KEY_F12              F12 function key 

GLUT_KEY_LEFT             Left function key 

GLUT_KEY_RIGHT            Up function key 

GLUT_KEY_UP               Right function key 

GLUT_KEY_DOWN             Down function key 

GLUT_KEY_PAGE_UP          Page Up function key 

GLUT_KEY_PAGE_DOWN        Page Down function key 

GLUT_KEY_HOME             Home function key 

GLUT_KEY_END              End function key 

GLUT_KEY_INSERT           Insert function key 

为了让上面processSpecialKeys函数能过编译通过,我们还必须定义,redgreenblue三个变量。此外为了得到我们想要的结果,我们还必须修改renderScene函数。 

... 

// 所有的变量被初始化为1,表明三角形最开始是白色的。 

float red=1.0, blue=1.0, green=1.0; 

  

  

  

void renderScene(void) { 

         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

         glPushMatrix(); 

         glRotatef(angle,0.0,1.0,0.0); 

  

         // glColor3f设置绘制三角形的颜色。 

         glColor3f(red,green,blue); 

  

         glBegin(GL_TRIANGLES); 

                 glVertex3f(-0.5,-0.5,0.0); 

                 glVertex3f(0.5,0.0,0.0); 

                 glVertex3f(0.0,0.5,0.0); 

         glEnd(); 

         glPopMatrix(); 

         angle++; 

         glutSwapBuffers(); 

 。下面我们就该告诉GLUT,我们刚刚定义的函数用来处理,按键消息。也就是该调用glutKeyboardFuncglutSpecialFunc函数。我们在main函数里调用它们。下面就是最新的main函数。 

VC工程可以在这里下载(glut3.zip) 

  

CTRL,ALTSHIFT 

  

一些时候我们想知道要是一个组合键(modifier key)也就是CTRL,ALT或者SHIFT被按下该如何处理。GLUT提供了一个函数来检测时候有组合键被按下。这个函数仅仅只能在处理按键消息或者鼠标消息函数里被调用。函数原型如下: 

int glutGetModifiers(void); 

这个函数的返回值是三个glut.h里预定义的常量里的一个,或它们的或组合。这三个常量是: 

1GLUT_ACTIVE_SHIFT: 返回它,当按下SHIFT键或以按下CAPS LOCK,注意两者同时按下时,不会返回这个值。 

2GLUT_ACTIVE_CTRL: 返回它,当按下CTRL键。 

3GLUT_ACTIVE_ATL:返回它,当按下ATL键。 

注意,窗口系统可能会截取一些组合键(modifiers),这是就没有回调发生。现在让我们扩充processNormalKeys,处理组合键。按下r键时red变量被设置为0.0,当按下ATL+rred被设置为1.0。代码如下: 

void processNormalKeys(unsigned char key, int x, int y) { 

  

         if (key == 27)  

                 exit(0); 

         else if (key=='r') { 

                 int mod = glutGetModifiers(); 

                 if (mod == GLUT_ACTIVE_ALT) 

                          red = 0.0; 

                 else 

                          red = 1.0; 

         } 

注意如果我们按下R键,将不会有什么发生,因为Rr键的ASCII码不同。即这是两个不同的键。最后就是如何检测按键CTRL+ALT+F1?。这种情况下,我们必须同时检测两个组合键,为了完成操作我们需要使用或操作符。下面的代码段,使你按下CTRL+ALT+F1时颜色改变为红色。 

void processSpecialKeys(int key, int x, int y) { 

  

         int mod; 

         switch(key) { 

                 case GLUT_KEY_F1 :  

                    mod = glutGetModifiers(); 

                    if (mod == (GLUT_ACTIVE_CTRL|GLUT_ACTIVE_ALT)) { 

                          red = 1.0; green = 0.0; blue = 0.0; 

                    } 

                    break; 

                 case GLUT_KEY_F2 :  

                    red = 0.0;  

                    green = 1.0;  

                    blue = 0.0; break; 

                 case GLUT_KEY_F3 :  

                    red = 0.0;  

                    green = 0.0;  

                    blue = 1.0; break; 

         } 

  

 

 

GLUT教程 

               键盘控制例子:场景漫游 

让我们看一个比较好的使用键盘控制的例子。这一章我们将建立一个应用程序。这个程序绘制了一个小的居住着雪人的世界。并且我们将用方向键来移动照相机(即移动视点在场景中漫游)。左右方向键,将照相机绕y轴旋转,上下方向键,将前后方向移动照相机。 

  

这个例子的代码放在下面。首先我们处理初始状态。 

#include <math.h> 

#include <GL/glut.h> 

  

#include <stdlib.h> 

  

static float angle=0.0,ratio; 

static float x=0.0f,y=1.75f,z=5.0f; 

static float lx=0.0f,ly=0.0f,lz=-1.0f; 

static GLint snowman_display_list; 

注意我们包含了math.h头文件。我们需要计算旋转角。上面变量的含义到后面你就会清楚了,但我们还是简单的描述下: 

1angle:绕y轴的旋转角,这个变量允许我们旋转照相机。 

2x,y,z照相机位置。 

3lx,ly,lz:一个向量用来指示我们的视线方向。 

4ratio:窗口宽高比(width/height)。 

5snowman_display_list:一个雪人的显示列表索引。 

  

注意:如果你不愿意用显示列表,你也可以忽略它,这并不影响,教程。 

  

接下来,我们用一个公共的函数来处理窗口尺寸。唯一的区别是函数glutLookAt的参数用变量而不是固定的值。gluLookAt函数提供了一个简单直观的方法来设置照相机的位置和方向。它有三组参数,每一组由三个浮点型数组成。前三个参数表明照相机的位置,第二组参数定义照相机观察的方向,最后一组表明向上的向量,这个通常设为(0.01.00.0)。也就是说照相机并没有倾斜。如你想看到所有的物体都是倒置的则可以设置为(0.0-1.00.0)。 

  

上面提到的变量x,y,z表示照相机位置,因此这三个变量也就对应着函数gluLookAt里的第一组向量。第二组参数观察方向,是通过定义视线的向量和照相机位置相加得到的: 

Look At Point=Line Of Sight+ Camera Position 

  

void changeSize(int w, int h) 

         { 

  

         // 防止被0

         if(h == 0) 

                 h = 1; 

  

         ratio = 1.0f * w / h; 

         // Reset the coordinate system before modifying 

         glMatrixMode(GL_PROJECTION); 

         glLoadIdentity(); 

          

         //设置视口为整个窗口大小 

         glViewport(0, 0, w, h); 

  

         //设置可视空间 

         gluPerspective(45,ratio,1,1000); 

         glMatrixMode(GL_MODELVIEW); 

         glLoadIdentity(); 

         gluLookAt(x, y, z,  

                          x + lx,y + ly,z + lz, 

                          0.0f,1.0f,0.0f); 

         } 

下面我们定义显示列表,绘制雪人,初始化场景,渲染场景。 

void drawSnowMan() { 

  

         glColor3f(1.0f, 1.0f, 1.0f); 

  

//画身体 

         glTranslatef(0.0f ,0.75f, 0.0f); 

         glutSolidSphere(0.75f,20,20); 

  

  

// 画头 

         glTranslatef(0.0f, 1.0f, 0.0f); 

         glutSolidSphere(0.25f,20,20); 

  

// 画眼睛 

         glPushMatrix(); 

         glColor3f(0.0f,0.0f,0.0f); 

         glTranslatef(0.05f, 0.10f, 0.18f); 

         glutSolidSphere(0.05f,10,10); 

         glTranslatef(-0.1f, 0.0f, 0.0f); 

         glutSolidSphere(0.05f,10,10); 

         glPopMatrix(); 

  

// 画鼻子 

         glColor3f(1.0f, 0.5f , 0.5f); 

         glRotatef(0.0f,1.0f, 0.0f, 0.0f); 

         glutSolidCone(0.08f,0.5f,10,2); 

  

GLuint createDL() { 

         GLuint snowManDL; 

  

         //生成一个显示列表号 

         snowManDL = glGenLists(1); 

  

         // 开始显示列表 

         glNewList(snowManDL,GL_COMPILE); 

高级键盘控制(keyboard features) 

  

这节我们将去介绍4个新的处理键盘输入的函数。 

  

第一个函数允许我们去禁止keyboard repeat。函数原型如下: 

int glutSetKeyRepeat(int repeatMode); 

参数: 

repeatMode开启,禁用,或恢复auto repeat模式,下面是它可能的取值。 

RepeatMode的可能取值如下: 

 GLUT_KEY_REPEAT_OFF关闭auto repeat模式。 

 GLUT_KEY_REPEAT_ON开启auto repeat模式。 

 GLUT_KEY_REPEAT_DEFAULT把auto repeat模式恢复到默认状态。 

  

注意这个函数,作用范围是全局性的。也就是,它会影响所有窗口的repeat模式。不仅仅是我们应用程序这一个。因此注意当使用这个函数关闭auto repeat模式后,有必要在程序结束时将auto repeat模式重设到默认模式。 

  

GLUT提供我们另外一个简单的函数,来禁用keyboard repeat,这个让我们安全的忽视keyboard repeat,而不会影响其他程序。函数原型如下: 

Int glutIgnoreKeyRepeat(int repeatMode); 

参数: 

RepeatMode:传递0,开启auto repeat,非0则禁用auto repeat。 

在一些情况下,当key repeat发生时,我们将不接受函数回调。然而如果你想在一个key被按下后,执行一个动作,你就需要知道这个key什么时候松开。GLUT提供了两个函数注册相关的回调函数。 

Void glutKeyboardUpFunc(void (*func)(unsigned char key,int x,int y)); 

Void glutSpecialUpFunc(void (*func)(int key,int x,int y)); 

参数: 

Func:回调函数的函数名。 

我们在下一节,提供一个程序也就是上一节的代码,来看看这些函数怎么工作。 

  

(这章很不好翻译。好多都不知道怎么说,汗。- -|| 有需要的看原文。http://www.lighthouse3d.com/opengl/glut/index.php?7    我感觉原文写的也不咋清楚。还是看下一节的例子。 呵呵。) 

GLUT教程 

            键盘例子------场景漫游II 

  

这一节里,我们再来看看上次的例子,这次我们讲使用高级的键盘控制。 

  

在初始化那部分,我们有两个变量:deltaAngledeltaMode。这些变量控制旋转和移动照相机。当为非0时,照相机执行一些动作,当为0时,照相机就不动,这两个变量的初始值是0,也就是说,照相机初始状态是不动的。 

  

#include <math.h> 

#include <GL/glut.h> 

  

float angle=0.0,deltaAngle = 0.0,ratio; 

float x=0.0f,y=1.75f,z=5.0f; 

float lx=0.0f,ly=0.0f,lz=-1.0f; 

GLint snowman_display_list; 

int deltaMove = 0; 

  

  

void changeSize(int w, int h) 

         { 

         // Prevent a divide by zero, when window is too short 

         // (you cant make a window of zero width). 

         if(h == 0) 

                 h = 1; 

  

         ratio = 1.0f * w / h; 

         // 重置投影矩阵 

         glMatrixMode(GL_PROJECTION); 

         glLoadIdentity(); 

          

         // 设置视口大小。 

         glViewport(0, 0, w, h); 

  

         // 设置可视空间 

         gluPerspective(45,ratio,1,1000); 

         glMatrixMode(GL_MODELVIEW); 

         glLoadIdentity(); 

         gluLookAt(x, y, z,  

                       x + lx,y + ly,z + lz, 

                           0.0f,1.0f,0.0f); 

  

  

         } 

  

  

void drawSnowMan() { 

         glColor3f(1.0f, 1.0f, 1.0f); 

// Draw Body      

         glTranslatef(0.0f ,0.75f, 0.0f); 

         glutSolidSphere(0.75f,20,20); 

  

// Draw Head 

         glTranslatef(0.0f, 1.0f, 0.0f); 

         glutSolidSphere(0.25f,20,20); 

  

// Draw Eyes 

         glPushMatrix(); 

         glColor3f(0.0f,0.0f,0.0f); 

         glTranslatef(0.05f, 0.10f, 0.18f); 

         glutSolidSphere(0.05f,10,10); 

         glTranslatef(-0.1f, 0.0f, 0.0f); 

         glutSolidSphere(0.05f,10,10); 

         glPopMatrix(); 

  

// Draw Nose 

         glColor3f(1.0f, 0.5f , 0.5f); 

         glRotatef(0.0f,1.0f, 0.0f, 0.0f); 

         glutSolidCone(0.08f,0.5f,10,2); 

  

GLuint createDL() {                          //返回一个显示列表 

         GLuint snowManDL; 

  

         // Create the id for the list 

         snowManDL = glGenLists(1); 

  

         // start list 

         glNewList(snowManDL,GL_COMPILE); 

  

         // call the function that contains  

         // the rendering commands 

                 drawSnowMan(); 

  

         // endList 

         glEndList(); 

  

         return(snowManDL); 

  

void initScene() { 

  

         glEnable(GL_DEPTH_TEST); 

         snowman_display_list = createDL(); 

  

  

void orientMe(float ang) { 

         lx = sin(ang); 

         lz = -cos(ang); 

         glLoadIdentity(); 

         gluLookAt(x, y, z,  

                       x + lx,y + ly,z + lz, 

                           0.0f,1.0f,0.0f); 

  

void moveMeFlat(int i) { 

         x = x + i*(lx)*0.1; 

         z = z + i*(lz)*0.1; 

         glLoadIdentity(); 

         gluLookAt(x, y, z,  

                       x + lx,y + ly,z + lz, 

                           0.0f,1.0f,0.0f); 

下面的代码和以前的有些不同了。下面这个函数最开始,检查我们定义的那两个变量是否为0,如果不为0就调用相应的函数,来控制照相机的移动,和旋转。 

void renderScene(void) { 

 

 

  

 作者: 無與JAY倫比  2007-12-12 00:18   回复此发言    

 

--------------------------------------------------------------------------------

 

2 OpenGL---GLUT教程(八) GLUT场景漫游II  

   

         if (deltaMove) 

                 moveMeFlat(deltaMove); 

         if (deltaAngle) { 

                 angle += deltaAngle; 

                 orientMe(angle); 

         } 

         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

// Draw ground 

         glColor3f(0.9f, 0.9f, 0.9f); 

         glBegin(GL_QUADS); 

                 glVertex3f(-100.0f, 0.0f, -100.0f); 

                 glVertex3f(-100.0f, 0.0f, 100.0f); 

                 glVertex3f( 100.0f, 0.0f, 100.0f); 

                 glVertex3f( 100.0f, 0.0f, -100.0f); 

         glEnd(); 

// Draw 36 SnowMen 

         for(int i = -3; i < 3; i++) 

                 for(int j=-3; j < 3; j++) { 

                          glPushMatrix(); 

                          glTranslatef(i*10.0,0,j * 10.0); 

                          glCallList(snowman_display_list);; 

                          glPopMatrix(); 

                 } 

         glutSwapBuffers(); 

下面的函数,分别是我们注册的特殊键控制的回调函数,和键的释放(键的松开)。 

void pressKey(int key, int x, int y) { 

  

         switch (key) { 

                 case GLUT_KEY_LEFT :  

                          deltaAngle = -0.01f;break; 

                 case GLUT_KEY_RIGHT :  

                          deltaAngle = 0.01f;break; 

                 case GLUT_KEY_UP :  

                          deltaMove = 1;break; 

                 case GLUT_KEY_DOWN :  

                          deltaMove = -1;break; 

         } 

  

void releaseKey(int key, int x, int y) { 

  

         switch (key) { 

                 case GLUT_KEY_LEFT :  

                 case GLUT_KEY_RIGHT :  

                          deltaAngle = 0.0f;break; 

                 case GLUT_KEY_UP :  

                 case GLUT_KEY_DOWN :  

                          deltaMove = 0;break; 

         } 

Main函数里,有三行新的代码行。 

  

glutIgnoreKeyRepeat函数,传递了一个非0值告诉GLUT不发送keyborad repeat消息,然后,glutSpecialUpFuncglutKeyboardUpFunc调用注册的回调函数。 

  

  

int main(int argc, char **argv) 

         glutInit(&argc, argv); 

         glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 

         glutInitWindowPosition(100,100); 

         glutInitWindowSize(640,360); 

         glutCreateWindow("SnowMen from 3D-Tech"); 

  

         initScene(); 

  

         glutIgnoreKeyRepeat(1); 

         glutSpecialFunc(pressKey); 

         glutSpecialUpFunc(releaseKey); 

  

         glutDisplayFunc(renderScene); 

         glutIdleFunc(renderScene); 

  

         glutReshapeFunc(changeSize); 

  

         glutMainLoop(); 

  

         return(0); 

可以在这里下载这节的VC6.0工程(glut7.zip)。还可以自己改下照相机设置的函数。 

 (原文地址:http://www.lighthouse3d.com/opengl/glut/index.php?8) 

http://tieba.baidu.com/f?kw=glut

 

 glut库下的主要函数: 

一。初始化 

 void glutInit(int* argc,char** argv) 

 这个函数用来初始化GLUT库。对应main函数的形式应是:int main(int argc,char* argv[]); 

 这个函数从main函数获取其两个参数。 

  

 void glutInitWindowSize(int width,int height); 

 void glutInitWindowPosition(int x,int y); 

 这两个函数很好理解是设置glut程序要产生的窗口的大小和位置(左上角)。以像素为单位。 

 void glutInitDisplayMode(unsigned int mode); 

 设置图形显示模式。参数mode的可选值为: 

 GLUT_RGBA:当未指明GLUTRGBAGLUTINDEX时,是默认使用的模式。表明欲建立RGBA模式的窗口。 

 GLUT_RGB:与GLUTRGBA作用相同。 

 GLUT_INDEX:指明为颜色索引模式。 

 GLUT_SINGLE:只使用单缓存 

 GLUT_DOUBLE:使用双缓存。以避免把计算机作图的过程都表现出来,或者为了平滑地实现动画。 

 GLUT_ACCUM:让窗口使用累加的缓存。 

 GLUT_ALPHA:让颜色缓冲区使用alpha组件。 

 GLUT_DEPTH:使用深度缓存。 

 GLUT_STENCIL:使用模板缓存。 

 GLUT_MULTISAMPLE:让窗口支持多例程。 

 GLUT_STEREO:使窗口支持立体。 

 GLUT_LUMINACE:luminance是亮度的意思。但是很遗憾,在多数OpenGL平台上,不被支持。 

-------------------------------------------------------------------------------- 

二。事件处理(Event Processing) 

 void  glutMainLoop(void) 

 让glut程序进入事件循环。在一个glut程序中最多只能调用一次。一旦调用,会直到程序结束才返回。  

-------------------------------------------------------------------------------- 

三。窗口管理(Window Management) 

 int glutCreateWindow(char* name); 

 产生一个顶层的窗口。name 作为窗口的名字,也就是窗口标题栏显示的内容。 

 返回值是生成窗口的标记符,可用函数glutGetWindow()加以引用。 

 int glutCreateSubWindow(int win,int x,int y,int width,int height); 

 创建一个子窗口。win是其父窗口的标记符。x,y是相对父窗口的位移,以像素表示。 

 width,height是子窗口的宽和高。 

 void glutSetWindow(int win); 

 int glutGetWindow(void); 

 功能分别是:设置标记符为win的窗口为当前窗口;返回当前窗口的标记符。 

 void glutDestroyWindow(int win); 

 销毁以win标记的窗口。 

 void glutPostRedisplay(void); 

 将当前窗口打上标记,标记其需要再次显示。 

 void glutSwapBuffers(void); 

 当窗口模式为双缓存时,此函数的功能就是把后台缓存的内容交换到前台显示。当然,只有单缓存时,使用它的功能跟用glFlush()一样。 

 而使用双缓存是为了把完整图画一次性显示在窗口上,或者是为了实现动画。 

 void glutPositionWindow(int x,int y); 

 改变当前窗口的位置:当前窗口是顶层窗口时,x,y是相对于屏幕的的位移;当前窗口若是子窗口时,x,y是相对其父窗口原点的位移。 

 void glutReshapeWindow(int width,int height); 

 改变当前窗口的大小。 

 width,height是当前窗口新的宽度和高度值,当然只能是正值。 

 void glutFullscreen(void); 

 让当前窗口全屏显示。当前窗口是顶层窗口时才有效。 

 void glutPopWindow(void); 

 void glutPushWindow(void); 

 对顶层窗口和子窗口均有效。改变当前窗口在栈中相对于其它窗口的次序。 

 void glutShowWindow(void); 

 void glutHideWindow(void); 

 void glutIconifyWindow(void); 

 这三个函数作用是改变当前窗口的显示状态。 

 glutShowWindow让当前窗口可视(这时它还是可能被其它窗口挡住)。 

 glutHideWindow让当前窗口成为不可视状态。 

 glutIconifyWindow让当前窗口成为一个图标,也即是最小化。 

 glutSetWindowTitle(char* name); 

 glutSetIconTitle(char* name); 

 设置当前窗口(必须是顶层窗口)的标题和图标化时的标题。 

 glutSetCursor(int cursor); 

 设置当前窗口的光标样式。 

 cursor可选值有许多:如GLUT_CURSOR_RIGHT_ARROW指向右边的光标,GLUT_CURSOR_LEFT_ARROW指向左边的光标,GLUT_CURSOR_INFO成为手状。 

GLUT_CURSOR_DESTROY呈叉状,GLUT_CURSOR_HELP呈现问号的形状。 

等等。  

-------------------------------------------------------------------------------- 

四。窗口的覆盖管理 

void glutEstablishOverlay(void); 

对当前窗口创建覆盖图层。该覆盖图的模式由初始化显示模式函数glutDisplayMode()决定。glutLayerGet(GLUT_OVERLAY_POSSIBLE)可用以设置对于当前窗口,是否允许产生由初始化显示模式函数规定其模式的覆盖图层。 

void glutUserLayer(GLenum layer); 

枚举量layer可选值为:GLUT_NORMAL,GLUT_OVERLAY.分别选取正常位平面或覆盖平面。 

void glutRemoveLayer(void); 

除去覆盖图。当没有覆盖图层时,调用这条语句也是安全的,这时系统不做任何事。 

void glutPostOverlayRedisplay(void); 

标记该覆盖图层为需要重新显示的状态。 

void glutShowOverlay(void); 

void glutHideOverlay(void); 

显示当前窗口的覆盖图层;隐藏覆盖图层。这两条语句即时执行。注意一下,只有窗口可视时,使用glutShowOverlay才能使其覆盖图层可视。当窗口被其他窗口遮挡时,其覆盖图层也被遮挡从而不可视。 

 

二。事件处理(Event Processing) 

 void  glutMainLoop(void) 

 让glut程序进入事件循环。在一个glut程序中最多只能调用一次。一旦调用,会直到程序结束才返回。 

三。窗口管理(Window Management) 

 int glutCreateWindow(char* name); 

 产生一个顶层的窗口。name 作为窗口的名字,也就是窗口标题栏显示的内容。 

 返回值是生成窗口的标记符,可用函数glutGetWindow()加以引用。 

 int glutCreateSubWindow(int win,int x,int y,int width,int height); 

 创建一个子窗口。win是其父窗口的标记符。x,y是相对父窗口的位移,以像素表示。 

 width,height是子窗口的宽和高。 

 void glutSetWindow(int win); 

 int glutGetWindow(void); 

 功能分别是:设置标记符为win的窗口为当前窗口;返回当前窗口的标记符。 

 void glutDestroyWindow(int win); 

 销毁以win标记的窗口。 

 void glutPostRedisplay(void); 

 将当前窗口打上标记,标记其需要再次显示。 

 void glutSwapBuffers(void); 

 当窗口模式为双缓存时,此函数的功能就是把后台缓存的内容交换到前台显示。当然,只有单缓存时,使用它的功能跟用glFlush()一样。 

 而使用双缓存是为了把完整图画一次性显示在窗口上,或者是为了实现动画。 

 void glutPositionWindow(int x,int y); 

 改变当前窗口的位置:当前窗口是顶层窗口时,x,y是相对于屏幕的的位移;当前窗口若是子窗口时,x,y是相对其父窗口原点的位移。 

 void glutReshapeWindow(int width,int height); 

 改变当前窗口的大小。 

 width,height是当前窗口新的宽度和高度值,当然只能是正值。 

 void glutFullscreen(void); 

 让当前窗口全屏显示。当前窗口是顶层窗口时才有效。 

 void glutPopWindow(void); 

 void glutPushWindow(void); 

 对顶层窗口和子窗口均有效。改变当前窗口在栈中相对于其它窗口的次序。 

 void glutShowWindow(void); 

 void glutHideWindow(void); 

 void glutIconifyWindow(void); 

 这三个函数作用是改变当前窗口的显示状态。 

 glutShowWindow让当前窗口可视(这时它还是可能被其它窗口挡住)。 

 glutHideWindow让当前窗口成为不可视状态。 

 glutIconifyWindow让当前窗口成为一个图标,也即是最小化。 

 glutSetWindowTitle(char* name); 

 glutSetIconTitle(char* name); 

 设置当前窗口(必须是顶层窗口)的标题和图标化时的标题。 

 glutSetCursor(int cursor); 

 设置当前窗口的光标样式。 

 cursor可选值有许多:如GLUT_CURSOR_RIGHT_ARROW指向右边的光标,GLUT_CURSOR_LEFT_ARROW指向左边的光标,GLUT_CURSOR_INFO成为手状。 

GLUT_CURSOR_DESTROY呈叉状,GLUT_CURSOR_HELP呈现问号的形状。 

等等。 

四。窗口的覆盖管理 

void glutEstablishOverlay(void); 

对当前窗口创建覆盖图层。该覆盖图的模式由初始化显示模式函数glutDisplayMode()决定。glutLayerGet(GLUT_OVERLAY_POSSIBLE)可用以设置对于当前窗口,是否允许产生由初始化显示模式函数规定其模式的覆盖图层。 

void glutUserLayer(GLenum layer); 

枚举量layer可选值为:GLUT_NORMAL,GLUT_OVERLAY.分别选取正常位平面或覆盖平面。 

void glutRemoveLayer(void); 

除去覆盖图。当没有覆盖图层时,调用这条语句也是安全的,这时系统不做任何事。 

void glutPostOverlayRedisplay(void); 

标记该覆盖图层为需要重新显示的状态。 

void glutShowOverlay(void); 

void glutHideOverlay(void); 

显示当前窗口的覆盖图层;隐藏覆盖图层。这两条语句即时执行。注意一下,只有窗口可视时,使用glutShowOverlay才能使其覆盖图层可视。当窗口被其他窗口遮挡时,其覆盖图层

原创粉丝点击