最近学习用OpenGL3D库来构建一个3D场景,以及实现场景漫游、粒子系统等效果,最终算是是做了一个3D走迷宫游戏吧。感觉最近学了好多东西,所以有必要整理整理。
一 实现效果
OpenGL 渲染篇
Ubuntu 13.04 安装 OpenGL
Ubuntu下OpenGL编程基础解析
如何在Ubuntu使用eclipse for c++配置OpenGL
二 实现过程详解
1、3d场景构建
1)光照与材质
通过设置光照与材质,使得场景的显示效果更真实。opengl加光源的方法:
GLfloat light_position[] = {0.0, 80.0, 0.0};
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, light_diffuse);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
加一个光源至少要上面这些代码,通过glLightfv()函数给光源设置位置以及颜色,可以加环境光G_AMBIENT、漫射光GL_DIFFUSE或镜面光GLSPECULAR,可以同时加8个光源,上面的光源时GL_LIGHT0,其他的就是GL_LIGHT1、2等。
场景中一旦加了光源,物体就会根据自己的材质对RGB光成分反射程度而显示不同的颜色。OpenGL给一个物体设置材质的方法
GLfloat diffuse[] = {1.0, 0.9, 0.9};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, diffuse);
设置材质参数后接下来画的物体就具备了这种材质。通常使用参数GL_AMBIENT_AND_DIFFUSE给环境光和漫射光设置相同的反射程度。
2)纹理映射与多重纹理映射
给模型加纹理是为了在表面形成复杂图案,因为设置材质只是控制表面的显示颜色,实际上物体的表面信息要更复杂些。opengl提供了给物体贴纹理图的方法,实际上有多种方法,但我用的是 glaux库。
struct IMAGE
{
GLuint sizeX;
GLuint sizeY;
signed char* data;
};
IMAGE *Image[3];
GLuint Texture[3];
bool loadTexture()//设置各种纹理,从bmp图像读取
{
FILE* myFile;
if(!(myFile = fopen("wall.bmp", "r")))
return false;
Image[0] = (IMAGE*)auxDIBImageLoad("wall.bmp");
glGenTextures(3, &Texture[0]);
glBindTexture(GL_TEXTURE_2D, Texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, Image[0]->sizeX, Image[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image[0]->data);
if(!(myFile = fopen("floor.bmp", "r")))
return false;
Image[1] = (IMAGE*)auxDIBImageLoad("floor.bmp");
glBindTexture(GL_TEXTURE_2D, Texture[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, Image[1]->sizeX, Image[1]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image[1]->data);
if(!(myFile = fopen("water.bmp", "r")))
return false;
Image[2] = (IMAGE*)auxDIBImageLoad("water.bmp");
glBindTexture(GL_TEXTURE_2D, Texture[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, Image[2]->sizeX, Image[2]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image[2]->data);
//释放内存
if(Image[0])
{
if(Image[0]->data)
free(Image[0]->data);
free(Image[0]);
}
if(Image[1])
{
if(Image[1]->data)
free(Image[1]->data);
free(Image[1]);
}
if(Image[2])
{
if(Image[2]->data)
free(Image[2]->data);
free(Image[2]);
}
return true;
}
上面的代码生成了三种纹理。语句glGenTextures(3, &Texture[0])生成了三个纹理索引,存在了数组Texture中,以后每次要设置纹理信息或是想应用纹理,通过函数glBindTexture(GL_TEXTURE_2D, textureIndex)就可以取到对应的纹理,其中第二个参数就是纹理索引。