本文将要实现的功能是绘制一个立方体,并且在六个面贴上不同的纹理(由外部导入图片)。按下x、y、z按键可以分别围绕x、y、z轴旋转。
在这里我使用的是GLUT库。
【1】读入bmp图片的信息采用了auxDIBImageLoad函数,它被包含在头文件glaux.h中。
实际上是一个宏,返回类型是AUX_RGBImageRec *。可以在头文件glaux.h中找到它的定义:
- #ifdef UNICODE
- #define auxDIBImageLoad auxDIBImageLoadW
- #else
- #define auxDIBImageLoad auxDIBImageLoadA
- #endif
- AUX_RGBImageRec * APIENTRY auxDIBImageLoadA(LPCSTR);
- AUX_RGBImageRec * APIENTRY auxDIBImageLoadW(LPCWSTR);
AUX_RGBImageRec 是一个结构体类型,这是它在头文件glaux.h中的定义:
- typedef struct _AUX_RGBImageRec {
- GLint sizeX, sizeY;
- unsigned char *data;
- } AUX_RGBImageRec;
需要注意的是:导入作为纹理的bmp图像的高度和宽度必须为2的整数次幂,而且至少是64个像素。为了保持兼容性,也不应该超过256个像素。
为了使用纹理,需要执行下列步骤:
1、创建纹理对象,并为它指定一个纹理;
2、确定纹理如何应用到每个像素上;
3、启用纹理贴图功能;
4、绘制场景,提供纹理坐标和几何图形坐标。
注意:纹理坐标必须在RGBA模式下才可以使用。在颜色索引模式下使用纹理贴图的结果是难以预料的。
创建纹理的核心代码:
- glGenTextures(1,&texture[i]);//命名纹理对象
- glBindTexture(GL_TEXTURE_2D,texture[i]);//绑定纹理
- glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TextureImage[i]->sizeX,
- TextureImage[i]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,
- TextureImage[i]->data);//指定纹理
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//指定过滤模式
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
注意:我们需要再次绑定纹理,以确定需要使用的纹理。
【3】使用SOIL库代替glaux加载纹理
由于glaux在很长时间内受到反对,我们可以使用SOIL(Simple OpenGL Image Library)库来实现加载图像作为纹理。SOIL库可以在这里下载:SOIL库
在程序中需要包含头文件SOIL.h,并且连接SOIL.lib库文件。
而且SOIL库比glaux更方便,直接加载磁盘上的图像成为纹理。
我们所需要对代码做的修改就是修改LoadGLTextures函数:
- //load the bitmap and convert it into a texture
- int LoadGLTextures()
- {
- int Status = 1;
- char *bmpFile[6] = {"BmpFile/Ferrary.bmp","BmpFile/Honda.bmp","BmpFile/Hust.bmp",
- "BmpFile/Lamborghini.bmp","BmpFile/NeHe.bmp","BmpFile/Porsche.bmp"};
- for (int i = 0;i < 6;++i)
- {
- texture[i] = SOIL_load_OGL_texture(
- bmpFile[i],
- SOIL_LOAD_AUTO,
- SOIL_CREATE_NEW_ID,
- SOIL_FLAG_INVERT_Y);
- printf("texture[%d]: %d\n",i,texture[i]);
- if(texture[i] == 0)
- Status = 0;
- glBindTexture(GL_TEXTURE_2D,texture[i]);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
- }
- return Status;
- }
【4】详细代码实现(使用glaux):
- #include <GL/glut.h>
- #include <GL/glaux.h>
- #include <stdio.h>
- #include <stdlib.h>
- GLuint texture[6];//6 textures for 6 faces of the cube
- GLfloat xRot,yRot,zRot;//control cube's rotation
- //read bmp image file
- AUX_RGBImageRec *LoadBMP(char *FileName)
- {
- FILE *File = NULL;
- if(!FileName)
- return NULL;
- File = fopen(FileName,"r");
- if (File)
- {
- fclose(File);
- return auxDIBImageLoad(FileName);
- }
- return NULL;
- }
- //load the bitmap and convert it into a texture
- int LoadGLTextures()
- {
- int Status = FALSE;
- char *bmpFile[6] = {"BmpFile/Ferrary.bmp","BmpFile/Honda.bmp","BmpFile/Hust.bmp",
- "BmpFile/Lamborghini.bmp","BmpFile/NeHe.bmp","BmpFile/Porsche.bmp"};
- //AUX_RGBImageRec *TextureImage[6] = new AUX_RGBImageRec[6];//create storage for the texture
- AUX_RGBImageRec *TextureImage[6] = {NULL,NULL,NULL,NULL,NULL,NULL};
- for(int i = 0;i < 6;++i)
- {
- //memset(TextureImage[i],0,sizeof(void*) * 1);//set the point to NULL
- if (TextureImage[i] = LoadBMP(bmpFile[i]))
- {
- Status = TRUE;
- glGenTextures(1,&texture[i]);//命名纹理对象
- glBindTexture(GL_TEXTURE_2D,texture[i]);//绑定纹理
- glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TextureImage[i]->sizeX,
- TextureImage[i]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,
- TextureImage[i]->data);//指定纹理
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//指定过滤模式
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
- }
- if (TextureImage[i])
- {
- if (TextureImage[i]->data)
- free(TextureImage[i]->data);
- free(TextureImage[i]);
- }
- }
- return Status;
- }
- int init()
- {
- if(!LoadGLTextures())
- return FALSE;
- glEnable(GL_TEXTURE_2D);
- glShadeModel(GL_SMOOTH);
- glClearColor(0.0f,0.0f,0.0f,0.5f);
- glClearDepth(1.0f);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
- return TRUE;
- }
- void display()
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glLoadIdentity();
- glTranslatef(0.0f,0.0f,-5.0f);
- glRotatef(xRot,1.0f,0.0f,0.0f);
- glRotatef(yRot,0.0f,1.0f,0.0f);
- glRotatef(zRot,0.0f,0.0f,1.0f);
- //glRotatef(45,1.0f,0.0f,0.0f);
- //glRotatef(45,0.0f,1.0f,0.0f);
- glBindTexture(GL_TEXTURE_2D,texture[0]);
- glBegin(GL_QUADS);
- // Front Face
- // Bottom Left Of The Texture and Quad
- glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
- // Bottom Right Of The Texture and Quad
- glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
- // Top Right Of The Texture and Quad
- glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
- // Top Left Of The Texture and Quad
- glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
- glEnd();
- glBindTexture(GL_TEXTURE_2D,texture[1]);
- glBegin(GL_QUADS);
- // Back Face
- // Bottom Right Of The Texture and Quad
- glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
- // Top Right Of The Texture and Quad
- glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
- // Top Left Of The Texture and Quad
- glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
- // Bottom Left Of The Texture and Quad
- glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
- glEnd();
- glBindTexture(GL_TEXTURE_2D,texture[2]);
- glBegin(GL_QUADS);
- // Top Face
- // Top Left Of The Texture and Quad
- glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
- // Bottom Left Of The Texture and Quad
- glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
- // Bottom Right Of The Texture and Quad
- glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
- // Top Right Of The Texture and Quad
- glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
- glEnd();
- glBindTexture(GL_TEXTURE_2D,texture[3]);
- glBegin(GL_QUADS);
- // Bottom Face
- // Top Right Of The Texture and Quad
- glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
- // Top Left Of The Texture and Quad
- glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
- // Bottom Left Of The Texture and Quad
- glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
- // Bottom Right Of The Texture and Quad
- glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
- glEnd();
- glBindTexture(GL_TEXTURE_2D,texture[4]);
- glBegin(GL_QUADS);
- // Right face
- // Bottom Right Of The Texture and Quad
- glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
- // Top Right Of The Texture and Quad
- glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
- // Top Left Of The Texture and Quad
- glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
- // Bottom Left Of The Texture and Quad
- glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
- glEnd();
- glBindTexture(GL_TEXTURE_2D,texture[5]);
- glBegin(GL_QUADS);
- // Left Face
- // Bottom Left Of The Texture and Quad
- glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
- // Bottom Right Of The Texture and Quad
- glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
- // Top Right Of The Texture and Quad
- glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
- // Top Left Of The Texture and Quad
- glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
- glEnd();
- /*xRot += 0.3f;
- yRot += 0.4f;
- zRot += 0.5f;*/
- glutSwapBuffers();
- }
- void reshape(int w,int h)
- {
- if (0 == h)
- h = 1;
- glViewport(0,0,(GLsizei)w,(GLsizei)h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(60.0f,(GLfloat)w / (GLfloat)h,1,100);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
- void keyboard(unsigned char key,int x,int y)
- {
- switch(key){
- case 'x':
- xRot += 1.0f;
- glutPostRedisplay();
- break;
- case 'y':
- yRot += 1.0f;
- glutPostRedisplay();
- break;
- case 'z':
- zRot += 1.0f;
- glutPostRedisplay();
- break;
- default:
- break;
- }
- }
- int main(int argc,char** argv)
- {
- glutInit(&argc,argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
- glutInitWindowSize(400,400);
- glutInitWindowPosition(100,100);
- glutCreateWindow("Texture Map");
- init();
- glutDisplayFunc(display);
- glutReshapeFunc(reshape);
- glutKeyboardFunc(keyboard);
- glutMainLoop();
- return 0;
- }