这篇文章主要是根据《OpenGL Shading Language Cookbook》一书翻译整理而得,介绍了环境的安装和一些基础知识。下面涉及到的库也可以到这里下载(Windows版)。
2014年9月26日更新:
擦!每次弄OpenGL光配置都弄得很头大。。。由于换了Mac电脑,下面补充了Mac下的注意事项(这时候突然觉得Windows这么方便。。。)
-----------------------------------------------------------------分割线-------------------------------------------------------------------
什么是GLSL
GLSL是OpenGL Shading Language的缩写,顾名思义就是OpenGL渲染语言,它允许我们通过一些接口直接利用现代的图形处理单元(GPUs)进行图形绘制等工作。GLSL语言必须协同OpenGL语言才可以工作。它们嵌入在更庞大的OpenGL语言里,这些迷你的代码通常被称为shader,它们运行在GPU而不是CPU上。从名字上可以看出来,GLSL大多跟3D图像的灯光、渲染等工作有关,但它们的能力绝不仅仅如此。它们还可以用于动画、曲面计算等更深的应用。
Shader语言被设计成可以直接运行在GPU上,并且通常是并行的。例如,对于每个像素,一个fragment shader,片段着色器,可能执行一次,并且是同时在不同的GPU单元上同时执行。显卡上处理器的数量决定了同时可以允许多少个同时执行。这样的特性使得shader具有很好的性能,并允许程序员进行并行运算。
现代显卡的计算能力是让人印象深刻的,下面的表格显示了NVIDIA GeForce 400系列显卡上处理器的数量:
设计者希望Shader程序可以替换传统OpenGL体系结构中的fixed-function pipeline,固定功能管道,部分。在之前,默认的灯光/阴影计算是这个管道的一个核心部分。但是,但我们想要它们实现更多更高级的功能时,我们就需要做非常的工作来实现,而实际上很多是它们无法做到的。GLSL的出现改变了这样的境地,它允许我们使用GLSL语言代替以前的“硬编码”,从而提供了更灵活、更高级的功能。
OpenGL 3.0进入了一个弃用的模型,也就是逐渐被OpenGL规格移除的功能。一些功能和特性可以说是被标志为被弃用了,这意味着它们在未来的OpenGL版本里将会被移除。例如,使用glBegin/glEnd的快速模式渲染在OpenGL 3.0中被标为弃用,在3.1版本里被移除。(我们现在上课还讲来着。。。)
而为了保持向后兼容性,OpenGL 3.2介绍了compatibility profiles,兼容配置文件的概念。如果程序员想要使用特定版本的OpenGL代码(不需要兼容),就可以使用所谓的core profile。而一些人可能希望可以向后兼容,那么就可以使用compatibility profiles。
选择一个a core profile或者a compatibility profile的步骤是跟窗口系统有关的。例如,在最新的Qt版本(现在最新的是5.0)中,我们可以使用下面的代码来选择一个 4.0 core profile :
- QGLFormat format;
- format.setVersion(4,0);
- format.setProfile(QGLFormat::CoreProfile);
- QGLWidget *myWidget = new QGLWidget(format);
GLEW
在Windows平台上OpenGL的版本被固定在1.1,这使得Windows平台的开发者不能直接访问最新的OpenGL版本的接口。我们需要进行一系列冗繁的工作来在运行时刻得到一个函数调用的指针,而且还会影响代码的整洁。而且,Windows自带的头文件是遵循OpenGL1.1版本,据称,Windows也不准备更新自带的gl.h和opengl32.lib。幸运的是,有人为我们做了这些事情还提供了相应的库和接口。GLEW就是其中一个。
安装GLEW
为了安装GLEW,以WIndows平台为例,我们可以到http://glew.sourceforge.net下载最新的glew版本,将其中的glew.h和wglew.h文件复制到编译器的对应文件夹下(例如VS的include文件夹),把glew32.lib文件复制到对应的库文件夹下(如VS的lib文件夹),以及glew32.dll复制到系统的根目录下(如system32/下)。
MAC版下的安装(以Qt为例):
Mac下没有现成的编译好的文件,需要下载源码然后用makefile。具体可以参见这里。也就是下面的做法:
- 下载 GLEW源码。
- 解压 GLEW。
- 打开命令行窗口,使用"cd"命令进入解压后的 GLEW 目录。
- 执行"make"命令,编译 GLEW。(注:要执行 make 命令,必须先确保 XCode 安装了 Command Line Tools)。
- 执行"sudo -s",进入管理员权限。
- 执行"make install",将 GLEW 的头文件和库文件分别复制到 /usr/include 和 /usr/include/GL 目录中。
- 在 Qt 工程中,右击项目图标,在弹出的快捷菜单中选择"Add Library..."命令。在弹出的向导对话框中选择"External Library",指定 GLEW 库文件和头文件的目录位置,在"Platform"中只勾选"Mac"一项。完成 GLEW 库的导入。
- 在 Qt 工程中,右击项目图标,在弹出的快捷菜单中选择"Add Library..."命令。在弹出的向导对话框中选择"System Library",指定 OpenGL.framework 的目录位置(在 /System/Library/Frameworks 目录下),在"Platform"中只勾选"Mac"一项。完成 OpenGL.framework 库的导入。
- 在 Qt 工程中,右击项目图标,在弹出的快捷菜单中选择"Add Library..."命令。在弹出的向导对话框中选择"System Library",指定 QtOpenGL.framework 的目录位置(在 Qt 安装目录的 lib 目录下),在"Platform"中只勾选"Mac"一项。完成 QtOpenGL.framework 库的导入。因为即使不使用
QtOpenGL 库中的 API,在使用 Qt 窗口框架时,还是会用到 QGLWidget 类的。
使用GLEW
为了使用glew,请确保在包含OpenGL头文件之前包含glew.h:
- #include <GL/glew.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
在初始化GL后、调用任何OpenGL代码前,加入以下代码:
- GLenum err = glewInit();
- if( GLEW_OK != err )
- {
- fprintf(stderr, "Error initializing GLEW: %s\n",
- glewGetErrorString(err) );
- }
其他库
另一个管理OpenGL扩展的库时GLEE,具体信息可见http://www.elf-stone.com/glee.php。它和GLEW类似,但是不需要在运行时刻初始化。
使用GLM库进行数学运算
在计算机图形学中,计算是一个核心的功能。以前的OpenGL版本提供了进行坐标变换和投影的标准矩阵栈(GL_MODELVIEW and GL_PROJECTION)。在最新的OpenGL 4.0里,这些功能都被移除了。因此,需要我们自己提供坐标和投影变换矩阵,然后将它们传递给shader。当然你还是可以自己写一个库来管理这些,但是不推荐这样。
一个类似的库时Christophe Riccio编写的GLM。它的设计是基于GLSL规则的,因此它的语法和GLSL语言很相似。同时,它提供了一些OpenGL扩展来弥补缺失的那些OpenGL功能,例如glOrtho,,glRotate, gluLookAt。
安装GLM
你可以在http://glm.g-truc.net网站下载安装包,解压后将glm文件夹复制到编译器对应的文件夹下(例如VS的include文件)。Mac下要把头文件放到usr/include下,然后在Qt项目的.pro文件中添加头文件目录。
使用GLM
和普通的核心头文件相似,你可以使用下面的代码来包含矩阵变换和transform2扩展:
- #include <glm/glm.hpp>
- #include <glm/gtc/matrix_transform.hpp>
- #include <glm/gtx/transform2.hpp>
然后你就可以使用glm命名空间进行编码了。下面是一个例子:
- glm::vec4 position = glm::vec4( 1.0f, 0.0f, 0.0f, 1.0f );
- glm::mat4 view = glm::lookAt( glm::vec3(0.0,0.0,5.0),
- glm::vec3(0.0,0.0,0.0),
- glm::vec3(0.0,1.0,0.0) );
- glm::mat4 model = glm::mat4(1.0f);
- model = glm::rotate( model, 90.0f, glm::vec3(0.0f,1.0f,0.0) );
- glm::mat4 mv = view * model;
- glm::vec4 transformed = mv * position;
不要使用下面的代码来引入glm的命名空间:
- using namespace glm;
这通常会引起命名空间的冲突。相反,你应该使用下面的代码来包含某一个符号:
- #include <glm/glm.hpp>
- using glm::vec3;
- using glm::mat4;
使用GLM作为OpenGL的输入
GLM支持使用OpenGL的向量函数(以"v"为后缀)直接向OpenGL传递一个GLM类型(通常是为了向shader传递参数)。例如:
- #include <glm/glm.hpp>
- #include <glm/gtc/matrix_transform.hpp>
- ...
- glm::mat4 proj = glm::perspective( viewAngle, aspect,
- nearDist, farDist );
- glUniformMatrix4fv(location, 1, GL_FALSE, &proj[0][0]);
更多文档可以详见http://glm.g-truc.net(需要翻墙)。
使用GLFW进行窗口管理
这里再介绍一个库GLFW。在以前的OpenGL版本里我们通常会使用glut来进行窗口的创建、按键监听等工作,但据说这个库已经很久没更新了,那么glfw就是一个可以作为替代的库。它是网址是http://www.glfw.org/。安装方法和上面两个库类似。使用方法可以详见自带的文档。
MAC下安装:
比较复杂,可以看Youtube上的一个视频。大概方法也是要生成头文件和库文件。然后在Qt中配置、包含进去。