NeHe教程第6课纹理映射

http://blog.csdn.net/archielau/article/details/7366010

程序链接点击打开链接

必须启用纹理映射
glEnable(GL_TEXTURE_2D);//启用纹理映射

AUX_RGBImageRec在glaux.h中声明的

/*

** RGB Image Structure
*/
typedef struct _AUX_RGBImageRec {
  GLint sizeX, sizeY;
  unsigned char *data;

} AUX_RGBImageRec;

[cpp]  view plain copy
  1. #include <windows.h>      // Windows的头文件  
  2. #include <gl/glew.h>      // 包含最新的gl.h,glu.h库  
  3. #include <gl/glut.h>      // 包含OpenGL实用库  
  4. #include <gl/glaux.h>     // GLaux库的头文件  
  5. #include <stdio.h>            // 标准输入/输出库的头文件  
  6.   
  7. GLfloat xrot;  
  8. GLfloat yrot;  
  9. GLfloat zrot;  
  10. GLuint texture[1];          //存储纹理,如果纹理大于1个改为相应数值  
  11. HGLRC hRC=NULL;                     //窗口着色描述表句柄  
  12. HDC hDC=NULL;                       //设备渲染描述表句柄  
  13. HWND hWND=NULL;                     //窗口句柄  
  14. HINSTANCE hInstance;                //保存程序的实例  
  15.   
  16. bool keys[256];  
  17. bool active=TRUE;                   //窗口的活动状态,缺省为true  
  18. bool fullscreen=TRUE;               //全屏的缺省状态=true  
  19. GLfloat rtri=7;                     //用于三角形角度  
  20. GLfloat rquad=45;                       //用于四边形角度  
  21. LRESULT CALLBACK WndProc(HWNDUINT,WPARAMLPARAM);  
  22.   
  23.   
  24. /* 在 ReSizeGLScene() 之前,我们增加了下面这一段代码。这段代码用来加载位图文件。 
  25.  * 如果文件不存在,返回 NULL 告知程序无法加载位图。 
  26.  * 关于用作纹理的图像。图像的宽和高必须是2的n次方;宽度和高度最小必须是64象素; 
  27.  * 并且出于兼容性的原因,图像的宽度和高度不应超过256象素。如果您的原始素材的宽度 
  28.  * 和高度不是64,128,256象素的话,使用图像处理软件重新改变图像的大小。*/  
  29. AUX_RGBImageRec *LoadBMP(char*Filename)  
  30. {  
  31.     // 首先,我们创建一个文件句柄。句柄是个用来鉴别资源的数值,它使程序能够  
  32.     //访问此资源。我们开始先将句柄设为 NULL 。  
  33.     FILE *File=NULL;  
  34.     if (!Filename)      //确保文件名已提供  
  35.     {  
  36.         return NULL;  
  37.     }  
  38.     File=fopen(Filename,"r");  
  39.     if (File)// 文件存在么?  
  40.     {  
  41.         fclose(File);  
  42.         return auxDIBImageLoad(Filename);   // 载入位图并返回指针  
  43.     }  
  44.     return NULL;  
  45. }  
  46. int LoadGLTextures()//载入位图(调用上面的代码)并转换成纹理  
  47. {  
  48.     //然后设置一个叫做 Status 的变量。我们使用它来跟踪是否能够载入位图以及能否创建纹理。   
  49.     //Status 缺省设为 FALSE (表示没有载入或创建任何东东)。  
  50.     int Status=FALSE;  
  51.     //创建存储位图的图像记录。次记录包含位图的宽度、高度和数据。  
  52.     AUX_RGBImageRec *TextureImage[1];   // 创建纹理的存储空间  
  53.     //清除图像记录,确保其内容为空  
  54.     memset(TextureImage,0,sizeof(void *)*1);                // 将指针设为 NULL  
  55.     if (TextureImage[0]=LoadBMP("Data/Nehe.bmp"))  
  56.     {  
  57.         Status=true;  
  58.           
  59.         /* 
  60.         使用TextureImage[0] 的数据创建纹理。第一行 glGenTextures(1, &texture[0]) 告诉OpenGL 
  61.         我们想生成一个纹理名字(如果您想载入多个纹理,加大数字)。 
  62.         第二行 glBindTexture(GL_TEXTURE_2D, texture[0]) 告诉OpenGL将纹理名字 texture[0] 绑定 
  63.         到纹理目标上。2D纹理只有高度(在 Y 轴上)和宽度(在 X 轴上)。主函数将纹理名字指派给纹理 
  64.         数据。本例中我们告知OpenGL,&texture[0] 处的内存已经可用。我们创建的纹理将存储在  
  65.         &texture[0] 的 指向的内存区域。 
  66.         */  
  67.         glGenTextures(1,&texture[0]);  
  68.         glBindTexture(GL_TEXTURE_2D,texture[0]);  
  69.         /* 
  70.         下面一行告诉OpenGL此纹理是一个2D纹理 ( GL_TEXTURE_2D )。参数“0”代表图像的详细程度, 
  71.         通常就由它为零去了。参数三是数据的成分数。因为图像是由红色数据,绿色数据,蓝色数据 
  72.         三种组分组成。 TextureImage[0]->sizeX 是纹理的宽度。如果您知道宽度,您可以在这里填入, 
  73.         但计算机可以很容易的为您指出此值。 TextureImage[0]->sizey 是纹理的高度。参数零是边框 
  74.         的值,一般就是“0”。 GL_RGB 告诉OpenGL图像数据由红、绿、蓝三色数据组成。 
  75.         GL_UNSIGNED_BYTE 意味着组成图像的数据是无符号字节类型的。最后... TextureImage[0]->data 
  76.         告诉OpenGL纹理数据的来源。此例中指向存放在 TextureImage[0] 记录中的数据。 
  77.         */  
  78.         glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,  
  79.             GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);  
  80.         /* 
  81.         下面的两行告诉OpenGL在显示图像时,当它比放大得原始的纹理大 ( GL_TEXTURE_MAG_FILTER )或 
  82.         缩小得比原始得纹理小( GL_TEXTURE_MIN_FILTER )时OpenGL采用的滤波方式。通常这两种情况下 
  83.         我都采用 GL_LINEAR 。这使得纹理从很远处到离屏幕很近时都平滑显示。使用 GL_LINEAR 需要 
  84.         CPU和显卡做更多的运算。如果您的机器很慢,您也许应该采用 GL_NEAREST 。过滤的纹理在放大 
  85.         的时候,看起来斑驳的很『译者注:马赛克啦』。您也可以结合这两种滤波方式。在近处时使用  
  86.         GL_LINEAR ,远处时 GL_NEAREST 。 
  87.         */  
  88.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);  
  89.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//线性滤波  
  90.       
  91.     }  
  92.     /* 
  93.     现在我们释放前面用来存放位图数据的内存。我们先查看位图数据是否存放在此处。如果是的话,再查看 
  94.     数据是否已经存储。如果已经存储的话,删了它。接着再释放 TextureImage[0] 图像结构以保证所有 
  95.     的内存都能释放。 
  96.     */  
  97.     if (TextureImage[0])//纹理是否存在  
  98.     {  
  99.         if (TextureImage[0]->data)//纹理图像是否存在  
  100.         {  
  101.             free(TextureImage[0]->data);//释放纹理图像占用的内存  
  102.         }  
  103.         free(TextureImage[0]);//释放图像结构  
  104.     }  
  105.     return Status;  
  106. }  
  107.   
  108. GLvoid ReSizeGLScene(GLsizei width,GLsizei height)  
  109. {  
  110.     if (height==0)  
  111.     {  
  112.         height=1;  
  113.     }  
  114.     glViewport(0,0,width, height);  //重置当前视口  
  115.   
  116.     /////////////////////////////////////////////////////////  
  117. //  下面几行为透视图设置屏幕。意味着越远的东西看起来越小。这么做创建了一个现实外观的场景。  
  118. //      此处透视按照基于窗口宽度和高度的45度视角来计算。0.1f,100.0f是我们在场景中所能绘制深度的起点和终点。  
  119. //        
  120. //      glMatrixMode(GL_PROJECTION)指明接下来的两行代码将影响projection matrix(投影矩阵)。  
  121. //      投影矩阵负责为我们的场景增加透视。 glLoadIdentity()近似于重置。它将所选的矩阵状态恢复成其原始状态。  
  122. //      调用 glLoadIdentity()之后我们为场景设置透视图。  
  123. //      glMatrixMode(GL_MODELVIEW)指明任何新的变换将会影响 modelview matrix(模型观察矩阵)。  
  124. //      模型观察矩阵中存放了我们的物体讯息。最后我们重置模型观察矩阵。  
  125. //      如果您还不能理解这些术语的含义,请别着急。在以后的教程里,我会向大家解释。  
  126. //      只要知道如果您想获得一个精彩的透视场景的话,必须这么做。  
  127.         ////////////////////////////////////////////////////////////////  
  128.   
  129.     glMatrixMode(GL_PROJECTION);  
  130.     glLoadIdentity();  
  131.     //设置视口的大小,设置透视投影矩阵  
  132.     gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);//y轴倾斜角,宽高比,z轴近距>0,z轴远距》近距》0  
  133.   
  134.     glMatrixMode(GL_MODELVIEW);  
  135.     glLoadIdentity();               //重置模型视图矩阵  
  136. }  
  137.   
  138. int InitGL(GLvoid)                  //开始对GL进行所有设置  
  139. {  
  140.     if (!LoadGLTextures())  
  141.     {  
  142.         return FALSE;  
  143.     }  
  144.     glEnable(GL_TEXTURE_2D);//启用纹理映射  
  145.     //启用阴影平滑  
  146.     glShadeModel(GL_SMOOTH);  
  147.     //黑色背景  
  148.     glClearColor(0.0f,0.0f,0.0f,0.5f);  
  149.   
  150.     //设置深度缓存  
  151.     glClearDepth(1.0f);  
  152.     //启用深度缓存  
  153.     glEnable(GL_DEPTH_TEST);  
  154.     //所作深度测试的类型  
  155.     glDepthFunc(GL_LEQUAL);  
  156.   
  157.     //最好的透视修正  
  158.     glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);  
  159.   
  160.     return TRUE;  
  161.   
  162. }  
  163.   
  164. //绘图工作  
  165. int DrawGLScene(GLvoid)  
  166. {  
  167.     //清除屏幕和深度缓存  
  168.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  
  169.     //重置模型视图矩阵  
  170.     glLoadIdentity();  
  171.         glTranslatef(0.0f,0.0f,-5.0f);//移入屏幕5个单位  
  172.     //下面三行使立方体绕XYZ轴旋转  
  173.     glRotatef(xrot,1.0f,0.0f,0.0f);  
  174.     glRotatef(yrot,0.0f, 1.0f, 0.0f);  
  175.     glRotatef(zrot, 0.0f, 0.0f, 1.0f);  
  176. /************************************************************************/  
  177. /* 下一行代码选择我们使用的纹理。如果您在您的场景中使用多个纹理,您应该使用 
  178.     glBindTexture(GL_TEXTURE_2D, texture[ 所使用纹理对应的数字 ]) 选择要绑定 
  179.     的纹理。当您想改变纹理时,应该绑定新的纹理。有一点值得指出的是,您不能在 
  180.     glBegin() 和 glEnd() 之间绑定纹理,必须在 glBegin() 之前或 glEnd() 之后 
  181.     绑定。注意我们在后面是如何使用 glBindTexture 来指定和绑定纹理的。                                                                     */  
  182. /************************************************************************/  
  183.     glBindTexture(GL_TEXTURE_2D,texture[0]);//选择纹理  
  184.     /************************************************************************/  
  185.     /* 为了将纹理正确的映射到四边形上,您必须将纹理的右上角映射到四边形的右上角, 
  186.     纹理的左上角映射到四边形的左上角,纹理的右下角映射到四边形的右下角,纹理的 
  187.     左下角映射到四边形的左下角。如果映射错误的话,图像显示时可能上下颠倒,侧向 
  188.     一边或者什么都不是。 
  189.     glTexCoord2f 的第一个参数是X坐标。0.0f 是纹理的左侧. 0.5f 是纹理的中点,  
  190.     1.0f 是纹理的右侧。 glTexCoord2f 的第二个参数是Y坐标。 0.0f 是纹理的底部。 
  191.     0.5f 是纹理的中点, 1.0f 是纹理的顶部。 
  192.     所以纹理的左上坐标是 X:0.0f,Y:1.0f ,四边形的左上顶点是 X: -1.0f,Y:1.0f 。 
  193.     其余三点依此类推。 
  194.                                                                     */  
  195.     /************************************************************************/  
  196.   
  197.     glBegin(GL_QUADS);  
  198.     //顶面 蓝色  
  199.         //glColor3f(0.0f,0.0f,1.0f);  
  200.         glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f, 1.0f, -1.0f);//右上  
  201.         glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f, 1.0f, -1.0f);//左上  
  202.         glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f, 1.0f,1.0f);//左下  
  203.         glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,1.0f,1.0f);//右下  
  204.     //底面  
  205.     //  glColor3f(1.0f,0.5f,0.0f);          // 颜色改成橙色  
  206.         glTexCoord2f(1.0f,1.0f);glVertex3f( 1.0f,-1.0f, 1.0f);          // 四边形的右上顶点(底面)  
  207.         glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,-1.0f, 1.0f);          // 四边形的左上顶点(底面)  
  208.         glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);          // 四边形的左下顶点(底面)  
  209.         glTexCoord2f(1.0f,0.0f);glVertex3f( 1.0f,-1.0f,-1.0f);          // 四边形的右下顶点(底面)  
  210.     //前面  
  211.           
  212.         glTexCoord2f(1.0f,1.0f);glVertex3f( 1.0f, 1.0f, 1.0f);          // 四边形的右上顶点(前面)  
  213.         glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f, 1.0f, 1.0f);          // 四边形的左上顶点(前面)  
  214.         glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f, 1.0f);          // 四边形的左下顶点(前面)  
  215.         glTexCoord2f(1.0f,0.0f);glVertex3f( 1.0f,-1.0f, 1.0f);          // 四边形的右下顶点(前面)  
  216.     //后面  
  217.     //  glColor3f(1.0f,1.0f,0.0f);          // 颜色改成黄色  
  218.         glTexCoord2f(1.0f,1.0f);glVertex3f( 1.0f,-1.0f,-1.0f);          // 四边形的右上顶点(后面)  
  219.         glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,-1.0f,-1.0f);          // 四边形的左上顶点(后面)  
  220.         glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f, 1.0f,-1.0f);          // 四边形的左下顶点(后面)  
  221.         glTexCoord2f(1.0f,0.0f);glVertex3f( 1.0f, 1.0f,-1.0f);          // 四边形的右下顶点(后面)  
  222.     //左面  
  223.         //glColor3f(0.0f,1.0f,0.0f);            // 颜色改成绿色  
  224.         glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f, 1.0f, 1.0f);          // 四边形的右上顶点(左面)  
  225.         glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f, 1.0f,-1.0f);          // 四边形的左上顶点(左面)  
  226.         glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);          // 四边形的左下顶点(左面)  
  227.         glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f, 1.0f);          // 四边形的右下顶点(左面)  
  228.     //右面  
  229.         //glColor3f(1.0f,0.0f,1.0f);            // 颜色改成紫罗兰色  
  230.         glTexCoord2f(1.0f,1.0f);glVertex3f( 1.0f, 1.0f,-1.0f);          // 四边形的右上顶点(右面)  
  231.         glTexCoord2f(0.0f,1.0f);glVertex3f( 1.0f, 1.0f, 1.0f);          // 四边形的左上顶点(右面)  
  232.         glTexCoord2f(0.0f,0.0f);glVertex3f( 1.0f,-1.0f, 1.0f);          // 四边形的左下顶点(右面)  
  233.         glTexCoord2f(1.0f,0.0f);glVertex3f( 1.0f,-1.0f,-1.0f);          // 四边形的右下顶点(右面)  
  234.   
  235.   
  236.     glEnd();  
  237.   
  238.     rtri+=0.2f;  
  239.     //rquad+=0.1f;  
  240.     xrot+=0.3f;  
  241.     yrot+=0.2f;  
  242.     zrot+=0.4f;  
  243.     return TRUE;  
  244.   
  245. }  
  246.   
  247. //程序退出之前调用 依次释放着色描述表RC,设备描述表DC和窗口句柄  
  248. GLvoid KillGLWindow(GLvoid)  
  249. {  
  250.   
  251.     if (fullscreen)  
  252.     {  
  253.         ChangeDisplaySettings(NULL,0);  //Windows API 把缺省显示设备的设置改变为由第一个参数设定的图形模式  
  254.         ShowCursor(TRUE);               //Window32API 显示鼠标  
  255.   
  256.     }  
  257.     if (hRC)        //是否拥有渲染描述表  
  258.     {  
  259.           
  260.         if (!wglMakeCurrent(NULL,NULL))  
  261.         {  
  262.            
  263.             MessageBox(NULL,"释放DC或RC失败","Shutdown Error",MB_OK|MB_ICONINFORMATION);  
  264.         }  
  265.           
  266.         if (!wglDeleteContext(hRC))       
  267.         {  
  268.             MessageBox(NULL,"释放RC失败","Shutdown Error",MB_OK|MB_ICONINFORMATION);  
  269.         }  
  270.         hRC=NULL;                   //将hRC设为NULL  
  271.   
  272.     }  
  273.     if (hDC&&!ReleaseDC(hWND,hDC))  
  274.     {  
  275.         MessageBox(NULL,"不能释放DC失败","Shutdown Error",MB_OK|MB_ICONINFORMATION);  
  276.         hDC=NULL;  
  277.     }  
  278.   
  279.     if (hWND&&!DestroyWindow(hWND))  
  280.     {  
  281.         MessageBox(NULL,"释放窗口句柄失败","Shutdown Error",MB_OK|MB_ICONINFORMATION);  
  282.         hWND=NULL;  
  283.     }  
  284.   
  285.     if (!UnregisterClass("OpenGL",hInstance))  
  286.     {  
  287.         MessageBox(NULL,"不能注销窗口类","Shutdown Error",MB_OK|MB_ICONINFORMATION);  
  288.         hInstance=NULL;  
  289.     }  
  290. }  
  291.   
  292. //创建OpenGL窗口  窗口标题 宽 高 颜色位 全屏标志  
  293. BOOL CreateGLWindow(char* title,int width,int height,int bits,bool fullscreenflag)  
  294. {  
  295.     //保存Windows相匹配的像素格式值变量  
  296.     GLuint PixelFormat;  
  297.     //窗口类结构  
  298.     WNDCLASS wc;  
  299.   
  300.     DWORD dwStyle;//窗口风格  
  301.     DWORD dwExStyle;//扩展窗口风格  
  302.   
  303.     RECT WindowRect;  
  304.     WindowRect.left=(long)0;  
  305.     WindowRect.right=(long)width;  
  306.     WindowRect.top=(long)0;  
  307.     WindowRect.bottom=(long)height;  
  308.   
  309.     fullscreen=fullscreenflag;  
  310.   
  311.     hInstance=GetModuleHandle(NULL);//获取一个应用程序或动态链接库的模块句柄 ,NULL返回自身应用程序句柄  
  312.     wc.style=CS_VREDRAW|CS_HREDRAW|CS_OWNDC;//移动时重画,并为窗口取得DC  
  313.     wc.lpfnWndProc=(WNDPROC)WndProc;        //WndProc处理消息  
  314.     wc.cbClsExtra       = 0;                        // 无额外窗口数据  
  315.     wc.cbWndExtra       = 0;                        // 无额外窗口数据  
  316.     wc.hInstance=hInstance;                         //设置实例  
  317.     wc.hIcon=LoadIcon(NULL,IDI_WINLOGO);            //装入缺省图标  
  318.     wc.hCursor=LoadCursor(NULL,IDC_ARROW);          //装入鼠标指针  
  319.     wc.hbrBackground=NULL;                          //GL不需要背景  
  320.     wc.lpszMenuName=NULL;                           //不需要菜单  
  321.     wc.lpszClassName="OpenGL";                      //设定类名字  
  322.   
  323.     //注册窗口类  
  324.     if (!RegisterClass(&wc))  
  325.     {  
  326.         MessageBox(NULL,"注册窗口失败"," Error",MB_OK|MB_ICONEXCLAMATION);//EXCLAMATION感叹号  
  327.         return FALSE;  
  328.     }  
  329.   
  330.     if (fullscreen)//全屏模式  
  331.     {  
  332.         DEVMODE dmScreenSettings;                   //设备模式  
  333.         memset(&dmScreenSettings,0,sizeof(dmScreenSettings));//确保内存清空为0  
  334.         dmScreenSettings.dmSize=sizeof(dmScreenSettings);   //DEVMODE结构的大小  
  335.         dmScreenSettings.dmPelsWidth=width;  
  336.         dmScreenSettings.dmPelsHeight=height;               //所选屏幕高度  
  337.         dmScreenSettings.dmBitsPerPel=bits;                 //每像素颜色数  
  338.         dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSHEIGHT|DM_PELSWIDTH;  
  339.           
  340.         if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)  
  341.         {  
  342.             // 若模式失败,提供两个选项:退出或在窗口内运行。  
  343.             if (MessageBox(NULL,"全屏模式在当前显示卡上设置失败!\n使用窗口模式","Nehe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)  
  344.             {  
  345.                 fullscreen=false;  
  346.             }  
  347.             else//用户选择退出  
  348.             {  
  349.                 MessageBox(NULL,"程序将被关闭","Error",MB_OK|MB_ICONSTOP);  
  350.                 return FALSE;  
  351.             }  
  352.   
  353.         }  
  354.     }  
  355.       
  356.     if (fullscreen)  
  357.     {  
  358.         dwExStyle=WS_EX_APPWINDOW;  
  359.         dwStyle=WS_POPUP;  
  360.         ShowCursor(FALSE);      //隐藏鼠标指针  
  361.     }  
  362.     else//不是全屏  
  363.     {  
  364.         dwExStyle=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;  
  365.         dwStyle=WS_OVERLAPPEDWINDOW;  
  366.     }  
  367.     AdjustWindowRectEx(&WindowRect,dwStyle,FALSE,dwExStyle);    //Windows API真正适合窗口  
  368.   
  369.     if (!(hWND=CreateWindowEx(dwExStyle,  
  370.                             "OpenGL",  
  371.                             title,  
  372.                             WS_CLIPSIBLINGS|WS_CLIPCHILDREN|dwStyle,//必须的窗体风格属性  
  373.                             0,0,  
  374.                             WindowRect.right-WindowRect.left,  
  375.                             WindowRect.bottom-WindowRect.top,//计算调整好的窗口高度  
  376.                             NULL,//无父窗口  
  377.                             NULL,//无子菜单  
  378.                             hInstance,  
  379.                             NULL)))//不向WM_CREATE传递消息  
  380.     {  
  381.         KillGLWindow();  
  382.         MessageBox(NULL,"不能创建窗口","Error",MB_OK|MB_ICONEXCLAMATION);  
  383.         return FALSE;  
  384.     }  
  385.   
  386.     static  PIXELFORMATDESCRIPTOR pfd=                  // /pfd 告诉窗口我们所希望的东东,即窗口使用的像素格式  
  387.     {  
  388.         sizeof(PIXELFORMATDESCRIPTOR),                  // 上述格式描述符的大小  
  389.             1,                              // 版本号  
  390.             PFD_DRAW_TO_WINDOW |                        // 格式支持窗口  
  391.             PFD_SUPPORT_OPENGL |                        // 格式必须支持OpenGL  
  392.             PFD_DOUBLEBUFFER,                       // 必须支持双缓冲  
  393.             PFD_TYPE_RGBA,                          // 申请 RGBA 格式  
  394.             bits,                               // 选定色彩深度  
  395.             0, 0, 0, 0, 0, 0,                       // 忽略的色彩位  
  396.             0,                              // 无Alpha缓存  
  397.             0,                              // 忽略Shift Bit  
  398.             0,                              // 无累加缓存  
  399.             0, 0, 0, 0,                         // 忽略聚集位  
  400.             16,                             // 16位 Z-缓存 (深度缓存)  
  401.             0,                              // 无蒙板缓存  
  402.             0,                              // 无辅助缓存  
  403.             PFD_MAIN_PLANE,                         // 主绘图层  
  404.             0,                              // Reserved  
  405.             0, 0, 0                             // 忽略层遮罩  
  406.     };  
  407.   
  408.     if (!(hDC=GetDC(hWND)))  
  409.     {  
  410.         KillGLWindow();                         // 重置显示区  
  411.         MessageBox(NULL,"不能创建一种相匹配的像素格式","错误",MB_OK|MB_ICONEXCLAMATION);  
  412.         return FALSE;  
  413.     }  
  414.     if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))  
  415.     {  
  416.         KillGLWindow();  
  417.         MessageBox(NULL,"不能创建像素格式","错误",MB_OK|MB_ICONEXCLAMATION);  
  418.         return FALSE;  
  419.     }  
  420.     if(!SetPixelFormat(hDC,PixelFormat,&pfd))               // 能够设置象素格式么?  
  421.     {  
  422.         KillGLWindow();                         // 重置显示区  
  423.         MessageBox(NULL,"不能设置像素格式","错误",MB_OK|MB_ICONEXCLAMATION);  
  424.         return FALSE;                           // 返回 FALSE  
  425.     }  
  426.   
  427.     if (!(hRC=wglCreateContext(hDC)))  
  428.     {  
  429.         KillGLWindow();                         // 重置显示区  
  430.         MessageBox(NULL,"不能创建OpenGL渲染描述表","错误",MB_OK|MB_ICONEXCLAMATION);  
  431.         return FALSE;     
  432.     }  
  433.     if (!wglMakeCurrent(hDC,hRC))  
  434.     {  
  435.           
  436.         KillGLWindow();                         // 重置显示区  
  437.         MessageBox(NULL,"不能激活当前的OpenGL渲然描述表","错误",MB_OK|MB_ICONEXCLAMATION);  
  438.         return FALSE;         
  439.     }  
  440.   
  441.     ShowWindow(hWND,SW_SHOW);  
  442.     SetForegroundWindow(hWND);                  //提高优先级  
  443.     SetFocus(hWND);                             //设置焦点  
  444.     ReSizeGLScene(width,height);  
  445.   
  446.     if (!InitGL())                              // 初始化新建的GL窗口  
  447.     {  
  448.         KillGLWindow();                         // 重置显示区  
  449.         MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);  
  450.         return FALSE;                           // 返回 FALSE  
  451.     }  
  452.   
  453.   
  454.     return TRUE;  
  455.   
  456. }  
  457.   
  458. LRESULT CALLBACK WndProc(   HWND    hWnd,                   // 窗口的句柄  
  459.                 UINT    uMsg,                   // 窗口的消息  
  460.                 WPARAM  wParam,                 // 附加的消息内容  
  461.                 LPARAM  lParam)                 // 附加的消息内容  
  462. {  
  463.   
  464.      
  465.     
  466.      
  467.   
  468.     switch (uMsg)                               // 检查Windows消息  
  469.     {  
  470.         case WM_ACTIVATE:                       // 监视窗口激活消息  
  471.         {  
  472.             if (!HIWORD(wParam))                    // 检查最小化状态  
  473.             {  
  474.                 active=TRUE;                    // 程序处于激活状态  
  475.             }  
  476.             else  
  477.             {  
  478.                 active=FALSE;                   // 程序不再激活  
  479.             }  
  480.   
  481.             return 0;                       // 返回消息循环  
  482.         }  
  483.   
  484.   
  485.         case WM_SYSCOMMAND:                     // 系统中断命令  
  486.         {  
  487.             switch (wParam)                     // 检查系统调用  
  488.             {  
  489.                 case SC_SCREENSAVE:             // 屏保要运行?  
  490.                 case SC_MONITORPOWER:               // 显示器要进入节电模式?  
  491.                 return 0;                   // 阻止发生  
  492.             }  
  493.             break;                          // 退出  
  494.         }  
  495.   
  496.      
  497.         case WM_CLOSE:                          // 收到Close消息?  
  498.         {  
  499.             PostQuitMessage(0);                 // 发出退出消息  
  500.             return 0;                       // 返回  
  501.         }    
  502.   
  503.         case WM_KEYDOWN:                        // 有键按下么?  
  504.         {  
  505.             keys[wParam] = TRUE;                    // 如果是,设为TRUE  
  506.             return 0;                       // 返回  
  507.         }  
  508.   
  509.      
  510.   
  511.         case WM_KEYUP:                          // 有键放开么?  
  512.         {  
  513.             keys[wParam] = FALSE;                   // 如果是,设为FALSE  
  514.             return 0;                       // 返回  
  515.         }  
  516.   
  517.         case WM_SIZE:                           // 调整OpenGL窗口大小  
  518.         {  
  519.             ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));       // LoWord=Width,HiWord=Height  
  520.             return 0;                       // 返回  
  521.         }  
  522.     }  
  523.   
  524.   
  525.     return DefWindowProc(hWnd,uMsg,wParam,lParam);  
  526. }  
  527.      
  528.   
  529. int WINAPI WinMain( HINSTANCE   hInstance,              // 当前窗口实例  
  530.             HINSTANCE   hPrevInstance,              // 前一个窗口实例  
  531.             LPSTR       lpCmdLine,              // 命令行参数  
  532.             int     nCmdShow)               // 窗口显示状态  
  533. {  
  534.     
  535.   
  536.     MSG msg;                                // Windowsx消息结构  
  537.     BOOL    done=FALSE;                         // 用来退出循环的Bool 变量  
  538.   
  539.     if (MessageBox(NULL,"你想在全屏模式下运行么?""设置全屏模式",MB_YESNO|MB_ICONQUESTION)==IDNO)  
  540.     {  
  541.         fullscreen=FALSE;                       // FALSE为窗口模式  
  542.     }  
  543.   
  544.     if (!CreateGLWindow("NeHe's 3D空间",640,480,16,fullscreen))  
  545.     {  
  546.         return 0;                           // 失败退出  
  547.     }  
  548.     
  549.     while(!done)                                // 保持循环直到 done=TRUE  
  550.     {  
  551.         if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))           // 有消息在等待吗?  
  552.         {  
  553.   
  554.             if (msg.message==WM_QUIT)               // 收到退出消息?  
  555.             {  
  556.                 done=TRUE;                  // 是,则done=TRUE  
  557.             }  
  558.             else                            // 不是,处理窗口消息  
  559.             {  
  560.   
  561.                 TranslateMessage(&msg);             // 翻译消息  
  562.                 DispatchMessage(&msg);              // 发送消息  
  563.             }  
  564.         }  
  565.         else                                // 如果没有消息  
  566.         {  
  567.   
  568.             if (active)                     // 程序激活的么?  
  569.             {  
  570.                 if (keys[VK_ESCAPE])                // ESC 按下了么?  
  571.                 {  
  572.                     done=TRUE;              // ESC 发出退出信号  
  573.                 }  
  574.                   
  575.                 else                        // 不是退出的时候,刷新屏幕  
  576.                 {  
  577.    
  578.                     DrawGLScene();              // 绘制场景  
  579.                     SwapBuffers(hDC);           // 交换缓存 (双缓存)  
  580.                 }  
  581.             }  
  582.   
  583.             if (keys[VK_F1])                    // F1键按下了么?  
  584.             {  
  585.                 keys[VK_F1]=FALSE;              // 若是,使对应的Key数组中的值为 FALSE  
  586.                 KillGLWindow();                 // 销毁当前的窗口  
  587.                 fullscreen=!fullscreen;             // 切换 全屏 / 窗口 模式  
  588.                 // 重建 OpenGL 窗口  
  589.                 if (!CreateGLWindow("NeHe's 3D空间",640,480,16,fullscreen))  
  590.                 {  
  591.                     return 0;               // 如果窗口未能创建,程序退出  
  592.                 }  
  593.             }  
  594.         }  
  595.     }  
  596.   
  597.   
  598.     KillGLWindow();                             // 销毁窗口  
  599.     return (msg.wParam);                            // 退出程序  
  600. }  


你可能感兴趣的:(NeHe教程第6课纹理映射)