OpenGL扩展机制(OpenGL Extensions)是OpenGL的亮点之一。显卡的更新,带来了更多,更炫的新特性,使我们能够利用硬件的出色发挥来绘制出令人惊叹的3D画面。利用OpenGL的扩展机制,任何硬件厂商提供的新特性可以用方便的被我们的OpenGL程序所使用。(在这里不得不提一下OpenGL最强有力的对手Direct3D,Direct3D的更新机制是通过升级DirectX SDK开发包来实现了,这给我们的学习带来了不少的麻烦,我们不得不面对版本升级带来的各种问题,在这一点上,OpenGL的优势很明显)。
在使用OpenGL Extensions之前,一定要检查你的显卡是否支持这个扩展,只有确保了你的显卡支持这个扩展特性,才可以放心的使用。可以通过一些工具,如glview来完成这样的工作。
OpenGL的扩展机制使用起来并不复杂,但是仍然有一些人做了许多有益的工作,简化了我们使用OpenGL扩展的步骤,使我们使用OpenGL扩展就像OpenGL API自带的那样方便。这其中比较有名的是glext和GLEW,这这里我主要介绍GLEW.GLEW的全称是"OpenGL Extension Wrangler Library".GLEW主要帮助C/C++完成两项烦琐的任务:1)初始化和使用扩展;2)编写可移植的程序。有关GLEW更详细的资料和获取GLEW,可以查阅网站:http://glew.sourceforge.net/。
有了以上的预备知识,我们就可以在我们程序中使用一些新特性,下面以ARB_multiTexture为例,讲讲具体的操作:
预备工作:
硬件条件:一个支持ARB_multiTexture的显卡(怎么,不支持?要么升级显卡驱动,要么换个新的显卡吧:)
软件条件:GLUT3.7.6--http://www.xmission.com/~nate/glut.html
GLEW1.2.4--http://glew.sourceforge.net/
具体步骤:
1.确保GLUT和GLEW已经正确的安装。
2.包含头文件和连接库文件:
#include <GL/glew.h>
#include <GL/glut.h> //注意,glew.h必须放在最前面
连接库文件:opengl32.lib glu32.lib glut32.lib glew32.lib
3.glut和glew的初始化,glew必须在正确设定了Render Context后才能初始化,即在调用了glutCreateWindow()后才能初始话glew,相关的代码如下:
int _tmain(int argc, _TCHAR* argv[])
{
glutInit(&argc, argv);
glutCreateWindow("Multitexture");
glutInitWindowSize(500,500);
glutInitWindowPosition(0,0);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA);
glutDisplayFunc(display);
glutReshapeFunc(myReshape);
GLenum err=glewInit();
if( err!=GLEW_OK )
{
std::cout<<"Error:"<<glewGetErrorString(err);
return 1;
}
myinit();
glutMainLoop();
return 0;
}
4.在程序的初始化阶段,创建Texture Objects,使渲染阶段可以在不同的纹理之间切换:
void myinit()
{
glShadeModel(GL_FLAT);
glGenTextures(1,&floor);
glBindTexture(GL_TEXTURE_2D,floor);
LoadBMPff("floor.bmp");
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glGenTextures(1,&light);
glBindTexture(GL_TEXTURE_2D,light);
LoadBMPff("lightmap.bmp");
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
}
5.在实际的渲染阶段,调用扩展提供的函数glActiveTextureARB()来指定当前操作的是哪一个纹理单元,在下一次调用glActiveTextureARB之前所有的函数适用于当前选定的纹理单元。具体的代码:
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glBindTexture(GL_TEXTURE_2D,floor);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindTexture(GL_TEXTURE_2D,light);
glPushMatrix();
glBegin(GL_QUADS);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,0.0f);glVertex2f(-1.0,-1.0);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,1.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,1.0f);glVertex2f(-1.0,1.0);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,1.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,1.0f);glVertex2f(1.0,1.0);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,0.0f);glVertex2f(1.0,-1.0);
glEnd();
glPopMatrix();
glFlush();
}
在这段渲染代码中,指定了两个纹理单元.这两个纹理单元共同的作用结果(实际上是纹理图案象素值相乘的结果)渲染到一个矩形物体上。由于两个纹理图案,一个是普通的纹理,一个是lightmap,渲染的效果就像light mapping的效果,这个技术已经广泛的应用在游戏中,如著名的Quake.
参考文献:
1.http://glew.sourceforge.net
2.http://www.gamedev.net/reference/articles/article1929.asp
3.http://www.opengl.org/resources/tutorials/sig99/advanced99/notes/node61.html
-----------------------------致力于多媒体技术,成为有思想的软件工程师------------------------
此文章为我原创作品,若要转载,请和本人联系,或注明出处。
欢迎大家对文章内容提出宝贵意见,同时希望大家及时指出文中的错误之处,这样我可以及时更正。
我的联系方式:
QQ: 7578420
Email: jerrydong@tom.com
----------------------------------------------------------------------------------------