【OpenGL】(NeHe教程学习)纹理映射及代码实现

本文将要实现的功能是绘制一个立方体,并且在六个面贴上不同的纹理(由外部导入图片)。按下x、y、z按键可以分别围绕x、y、z轴旋转。

在这里我使用的是GLUT库。


【1】读入bmp图片的信息采用了auxDIBImageLoad函数,它被包含在头文件glaux.h中。

实际上是一个宏,返回类型是AUX_RGBImageRec *。可以在头文件glaux.h中找到它的定义:

  1. #ifdef UNICODE  
  2. #define auxDIBImageLoad auxDIBImageLoadW  
  3. #else  
  4. #define auxDIBImageLoad auxDIBImageLoadA  
  5. #endif  
  6. AUX_RGBImageRec * APIENTRY auxDIBImageLoadA(LPCSTR);  
  7. AUX_RGBImageRec * APIENTRY auxDIBImageLoadW(LPCWSTR);  

AUX_RGBImageRec 是一个结构体类型,这是它在头文件glaux.h中的定义:

  1. typedef struct _AUX_RGBImageRec {  
  2.     GLint sizeX, sizeY;  
  3.     unsigned char *data;  
  4. } AUX_RGBImageRec;  

需要注意的是:导入作为纹理的bmp图像的高度和宽度必须为2的整数次幂,而且至少是64个像素。为了保持兼容性,也不应该超过256个像素。


【2】我们需要创建六个纹理,以给六个面以不同的效果。

为了使用纹理,需要执行下列步骤:

1、创建纹理对象,并为它指定一个纹理;

2、确定纹理如何应用到每个像素上;

3、启用纹理贴图功能;
4、绘制场景,提供纹理坐标和几何图形坐标。

注意:纹理坐标必须在RGBA模式下才可以使用。在颜色索引模式下使用纹理贴图的结果是难以预料的。

创建纹理的核心代码:

  1. glGenTextures(1,&texture[i]);//命名纹理对象  
  2. glBindTexture(GL_TEXTURE_2D,texture[i]);//绑定纹理  
  3. glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TextureImage[i]->sizeX,  
  4.                 TextureImage[i]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,  
  5.                 TextureImage[i]->data);//指定纹理  
  6. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//指定过滤模式  
  7. 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函数:

  1. //load the bitmap and convert it into a texture  
  2. int LoadGLTextures()  
  3. {  
  4.     int Status = 1;  
  5.     char *bmpFile[6] = {"BmpFile/Ferrary.bmp","BmpFile/Honda.bmp","BmpFile/Hust.bmp",  
  6.         "BmpFile/Lamborghini.bmp","BmpFile/NeHe.bmp","BmpFile/Porsche.bmp"};  
  7.     for (int i = 0;i < 6;++i)  
  8.     {  
  9.         texture[i] = SOIL_load_OGL_texture(  
  10.             bmpFile[i],  
  11.             SOIL_LOAD_AUTO,  
  12.             SOIL_CREATE_NEW_ID,  
  13.             SOIL_FLAG_INVERT_Y);  
  14.         printf("texture[%d]: %d\n",i,texture[i]);  
  15.         if(texture[i] == 0)  
  16.             Status = 0;  
  17.         glBindTexture(GL_TEXTURE_2D,texture[i]);  
  18.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);  
  19.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);  
  20.     }  
  21.     return Status;  
  22. }  


【4】详细代码实现(使用glaux):

  1. #include <GL/glut.h>  
  2. #include <GL/glaux.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5.   
  6. GLuint texture[6];//6 textures for 6 faces of the cube  
  7.   
  8. GLfloat xRot,yRot,zRot;//control cube's rotation  
  9.   
  10. //read bmp image file  
  11. AUX_RGBImageRec *LoadBMP(char *FileName)  
  12. {  
  13.     FILE *File = NULL;  
  14.     if(!FileName)  
  15.         return NULL;  
  16.     File = fopen(FileName,"r");  
  17.     if (File)  
  18.     {  
  19.         fclose(File);  
  20.         return auxDIBImageLoad(FileName);  
  21.     }  
  22.     return NULL;  
  23. }  
  24.   
  25. //load the bitmap and convert it into a texture  
  26. int LoadGLTextures()  
  27. {  
  28.     int Status = FALSE;  
  29.     char *bmpFile[6] = {"BmpFile/Ferrary.bmp","BmpFile/Honda.bmp","BmpFile/Hust.bmp",  
  30.         "BmpFile/Lamborghini.bmp","BmpFile/NeHe.bmp","BmpFile/Porsche.bmp"};  
  31.     //AUX_RGBImageRec *TextureImage[6] = new AUX_RGBImageRec[6];//create storage for the texture  
  32.     AUX_RGBImageRec *TextureImage[6] = {NULL,NULL,NULL,NULL,NULL,NULL};  
  33.     for(int i = 0;i < 6;++i)  
  34.     {  
  35.         //memset(TextureImage[i],0,sizeof(void*) * 1);//set the point to NULL  
  36.         if (TextureImage[i] = LoadBMP(bmpFile[i]))  
  37.         {  
  38.             Status = TRUE;  
  39.             glGenTextures(1,&texture[i]);//命名纹理对象  
  40.             glBindTexture(GL_TEXTURE_2D,texture[i]);//绑定纹理  
  41.             glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TextureImage[i]->sizeX,  
  42.                 TextureImage[i]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,  
  43.                 TextureImage[i]->data);//指定纹理  
  44.             glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//指定过滤模式  
  45.             glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);  
  46.         }  
  47.   
  48.         if (TextureImage[i])  
  49.         {  
  50.             if (TextureImage[i]->data)  
  51.                 free(TextureImage[i]->data);  
  52.             free(TextureImage[i]);  
  53.         }  
  54.     }  
  55.   
  56.     return Status;  
  57. }  
  58.   
  59. int init()  
  60. {  
  61.     if(!LoadGLTextures())  
  62.         return FALSE;  
  63.     glEnable(GL_TEXTURE_2D);  
  64.     glShadeModel(GL_SMOOTH);  
  65.     glClearColor(0.0f,0.0f,0.0f,0.5f);  
  66.     glClearDepth(1.0f);  
  67.     glEnable(GL_DEPTH_TEST);  
  68.     glDepthFunc(GL_LEQUAL);  
  69.     glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);  
  70.     return TRUE;  
  71. }  
  72.   
  73. void display()  
  74. {  
  75.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  76.     glLoadIdentity();  
  77.     glTranslatef(0.0f,0.0f,-5.0f);  
  78.     glRotatef(xRot,1.0f,0.0f,0.0f);  
  79.     glRotatef(yRot,0.0f,1.0f,0.0f);  
  80.     glRotatef(zRot,0.0f,0.0f,1.0f);  
  81.   
  82.     //glRotatef(45,1.0f,0.0f,0.0f);  
  83.     //glRotatef(45,0.0f,1.0f,0.0f);  
  84.   
  85.     glBindTexture(GL_TEXTURE_2D,texture[0]);  
  86.   
  87.     glBegin(GL_QUADS);   
  88.     // Front Face   
  89.     // Bottom Left Of The Texture and Quad   
  90.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);   
  91.     // Bottom Right Of The Texture and Quad   
  92.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);   
  93.     // Top Right Of The Texture and Quad   
  94.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);   
  95.     // Top Left Of The Texture and Quad   
  96.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);   
  97.     glEnd();   
  98.   
  99.     glBindTexture(GL_TEXTURE_2D,texture[1]);  
  100.     glBegin(GL_QUADS);   
  101.     // Back Face   
  102.     // Bottom Right Of The Texture and Quad   
  103.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);   
  104.     // Top Right Of The Texture and Quad   
  105.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);   
  106.     // Top Left Of The Texture and Quad   
  107.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);   
  108.     // Bottom Left Of The Texture and Quad   
  109.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);   
  110.     glEnd();   
  111.   
  112.     glBindTexture(GL_TEXTURE_2D,texture[2]);  
  113.     glBegin(GL_QUADS);   
  114.     // Top Face   
  115.     // Top Left Of The Texture and Quad   
  116.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);   
  117.     // Bottom Left Of The Texture and Quad   
  118.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);   
  119.     // Bottom Right Of The Texture and Quad   
  120.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);   
  121.     // Top Right Of The Texture and Quad   
  122.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);   
  123.     glEnd();   
  124.   
  125.     glBindTexture(GL_TEXTURE_2D,texture[3]);  
  126.     glBegin(GL_QUADS);   
  127.     // Bottom Face   
  128.     // Top Right Of The Texture and Quad   
  129.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);   
  130.     // Top Left Of The Texture and Quad   
  131.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);   
  132.     // Bottom Left Of The Texture and Quad   
  133.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);   
  134.     // Bottom Right Of The Texture and Quad   
  135.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);   
  136.     glEnd();   
  137.   
  138.     glBindTexture(GL_TEXTURE_2D,texture[4]);  
  139.     glBegin(GL_QUADS);   
  140.     // Right face   
  141.     // Bottom Right Of The Texture and Quad   
  142.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);   
  143.     // Top Right Of The Texture and Quad   
  144.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);   
  145.     // Top Left Of The Texture and Quad   
  146.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);   
  147.     // Bottom Left Of The Texture and Quad   
  148.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);   
  149.     glEnd();   
  150.   
  151.     glBindTexture(GL_TEXTURE_2D,texture[5]);  
  152.     glBegin(GL_QUADS);   
  153.     // Left Face   
  154.     // Bottom Left Of The Texture and Quad   
  155.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);   
  156.     // Bottom Right Of The Texture and Quad   
  157.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);   
  158.     // Top Right Of The Texture and Quad   
  159.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);   
  160.     // Top Left Of The Texture and Quad   
  161.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);   
  162.     glEnd();   
  163.   
  164.     /*xRot += 0.3f; 
  165.     yRot += 0.4f; 
  166.     zRot += 0.5f;*/  
  167.   
  168.     glutSwapBuffers();  
  169. }  
  170.   
  171. void reshape(int w,int h)  
  172. {  
  173.     if (0 == h)  
  174.         h = 1;  
  175.       
  176.     glViewport(0,0,(GLsizei)w,(GLsizei)h);  
  177.     glMatrixMode(GL_PROJECTION);  
  178.     glLoadIdentity();  
  179.     gluPerspective(60.0f,(GLfloat)w / (GLfloat)h,1,100);  
  180.     glMatrixMode(GL_MODELVIEW);  
  181.     glLoadIdentity();  
  182. }  
  183.   
  184. void keyboard(unsigned char key,int x,int y)  
  185. {  
  186.     switch(key){  
  187.         case 'x':  
  188.             xRot += 1.0f;  
  189.             glutPostRedisplay();  
  190.             break;  
  191.         case 'y':  
  192.             yRot += 1.0f;  
  193.             glutPostRedisplay();  
  194.             break;  
  195.         case 'z':  
  196.             zRot += 1.0f;  
  197.             glutPostRedisplay();  
  198.             break;  
  199.         default:  
  200.             break;  
  201.     }  
  202. }  
  203.   
  204. int main(int argc,char** argv)  
  205. {  
  206.     glutInit(&argc,argv);  
  207.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);  
  208.     glutInitWindowSize(400,400);  
  209.     glutInitWindowPosition(100,100);  
  210.     glutCreateWindow("Texture Map");  
  211.     init();  
  212.     glutDisplayFunc(display);  
  213.     glutReshapeFunc(reshape);  
  214.     glutKeyboardFunc(keyboard);  
  215.     glutMainLoop();  
  216.     return 0;  
  217. }  
运行结果:


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建一个OpenGL窗口: 在这个教程里,我将教你在Windows环境中创建OpenGL程序.它将显示一个空的OpenGL窗口,可以在窗口和全屏模式下切换,按ESC退出.它是我们以后应用程序的框架. 理解OpenGL如何工作非常重要,你可以在教程的末尾下载源程序,但我强烈建议你至少读一遍教程,然后再开始编程. 2.你的第一个多边形: 在第一个教程的基础上,我们添加了一个三角形和一个四边形。也许你认为这很简单,但你已经迈出了一大步,要知道任何在OpenGL中绘制的模型都会被分解为这两种简单的图形。 读完了这一课,你会学到如何在空间放置模型,并且会知道深度缓存的概念。 3.添加颜色: 作为第二课的扩展,我将叫你如何使用颜色。你将理解两种着色模式,在左图中,三角形用的是光滑着色,四边形用的是平面着色。 注意三角形上的颜色是如何混合的。 颜色为OpenGlL 工程增加很多。通过理解平面着色(flat coloring)和平滑着色(smooth coloring),你能显著的改善你的OpenGL Demo的样子。 4.旋转: 在这一课里,我将教会你如何旋转三角形和四边形。左图中的三角形沿Y轴旋转,四边形沿着X 轴旋转。 这一章将引入两个变量, rtri 被用来存储三角形的角度, rquad存储四边形的角度。 和容易创建一个多边形组成的场景。让这些物体动起来是整个场景变得生动起来。在后面的课程钟我将教给你如何绕屏幕上的一个点旋转物体,使得物体绕屏幕而不是它的轴转动。 5.3D形体: 既然我们已经领会到多边形,方形,色彩和旋转。现在该建立3D物体了。我将使用多边形和矩形c创建3D物体。这次我们将扩展上一章的教程,并且将三角形转换成一个彩色的棱锥,把正方形变为一个实心正方体。棱锥使用混合色,正方体每个面使用一种颜色。在3D空间创建物体可能很费时间,但是所获得的结果(收获)值得这样做。充分发挥你的想象力吧。 6.纹理映射: 你想要它,它现在就在这里了,那就是 ... 纹理映射!!!在这一章我将教会你如何将一幅位图(bitmap)映射到正方体的六个面上去。我们将使用第一章的OpenGL代码来创建工程。创建一个空的窗口比修改上一课的代码更容易。 你将会发现第一章的代码在对于快速创建工程来说是及其有价值的。第一章的代码为你设置好了一切,你所需要做的只是集中精力为效果编程。 7.纹理滤波, 光照和键盘控制: 好的,我希望到现在你已经理解了所有的东西,因为这是一个巨大的教程。我想教给你两个新的方法来过滤(filter)你的纹理,简单的光照,键盘控制并且还可能更多 :) .如果你对到这一课为止你所学的东西并不充满信心,那就回头复习一下。玩一下其它课程的代码,不要操之过急。最好专心把每一课学好,而不是蜻蜓点水,只知道如何把东西做出来。 8.混合 有理由等一下,一个来自很酷的Hypercosm的程序员伙伴问(我)他是否可以写一章关于混合的教程。第八课通常正是讲混合的,所以太巧了。这一章教程扩展了第七章。混合是一项很酷的技术 .. 我希望你们能好好享受这一章教程。这一章的作者是Tom Stanis他在这制作一章上花费了很多精力,所以让他知道你觉得怎么样。混合可不是一个好讲的话题。 9.在3D空间中移动位图: 这一章覆盖了一些你们要求的主题,你想知道如何移动你在3D屏幕空间上创造的物体。你想要知道如何在屏幕上绘制一幅位图,并且位图的黑色部分不会覆盖它后面的东西。你想要简单的动画,想要更多的混合的应用,这一章将教会你所有这些。You'll notice there's no spinning boxes(yaker:很惭愧这一句我不是很明白)。前面的课程覆盖了OpenGL的基础,每一章都基于前面的内容。前面的课程涵盖了基础的OpenGL,每一课都是在前一课的基础上创建的。这一课是前面几课知识的综合,当你学习这课时,请确保你已经掌握了前面几课的知识。 10.加载3D世界,并在其中漫游: 你一直期待的教程来了!这一章友一个叫Lionel Brites的伙伴制作。这一课里你讲学到如何导入一个3D世界。代码仍然使用第一章的,但是,课程页面只是解释了新的部分,包括导入3D场景,在3D世界中移动。下载VC++代码并且在你阅读教程的同时阅读代码。按[B]键控制混合,[F]键控制滤波,[L]键控制光照(但光并不随场景移动),还有[Page UP]和[Page Down]键。我希望你能喜欢Lionel对网站的贡献。我有空的时候我会让这个教程更容易学习。 11.旗帜效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值