OpenGL学习笔记 (6) —— 纹理映射

    技术2022-05-20  38

    2011-04-15 wcdj

     

     

    学习Texture Map纹理映射(贴图)有很多好处。比方说您想让一颗导弹飞过屏幕。根据前几课的知识,我们最可行的办法可能是很多个多边形来构建导弹的轮廓并加上有趣的颜色。使用纹理映射,您可以使用真实的导弹图像并让它飞过屏幕。您觉得哪个更好看?照片还是一大堆三角形和四边形?使用纹理映射的好处还不止是更好看,而且您的程序运行会更快。导弹贴图可能只是一个飞过窗口的四边形。一个由多边形构建而来的导弹却很可能包括成百上千的多边形。很显然,贴图极大的节省了CPU时间。 现在我们在第一课的代码开始处增加五行新代码。新增的第一行是#include <stdio.h> 。它允许我们对文件进行操作,为了在后面的代码中使用fopen(),我们增加了这一行。然后我们增加了三个新的浮点变量 xrot、 yrot、zrot。这些变量用来使立方体绕X、Y、Z轴旋转。最后一行GLuint texture[1]为一个纹理分配存储空间。如果您需要不止一个的纹理,应该将数字1改成您所需要的数字。 #include <stdio.h> // 标准输入/输出库的头文件 GLfloat xrot; // X 旋转量 GLfloat yrot; // Y 旋转量 GLfloat zrot; // Z 旋转量 GLuint texture[1]; // 存储一个纹理 紧跟上面的代码在ReSizeGLScene()之前,我们增加了下面这一段代码。这段代码用来加载位图文件。如果文件不存在,返回NULL告知程序无法加载位图。在我开始解释这段代码之前,关于用作纹理的图像我想有几点十分重要,并且您必须明白。此图像的宽和高必须是2的n次方 ;宽度和高度最小必须是64像素 ;并且出于兼容性的原因,图像的宽度和高度不应超过256像素 。如果您的原始素材的宽度和高度不是64,128,256象素的话,使用图像处理软件重新改变图像的大小 。可以肯定有办法能绕过这些限制,但现在我们只需要用标准的纹理尺寸。 步骤 : (1) 首先,我们创建一个文件句柄。句柄是个用来鉴别资源的数值,它使程序能够访问此资源。我们开始先将句柄设为NULL 。 (2) 下一部分代码载入位图(调用上面的代码)并转换成纹理。 (3) 只在 InitGL 中增加很少的几行代码。 (4) 现在我们绘制贴图(纹理映射)过的立方体。 注意 : 不能在glBegin()和glEnd()之间绑定纹理,必须在glBegin()之前或 glEnd()之后绑定。 为了将纹理正确的映射到四边形上,您必须将纹理的右上角映射到四边形的右上角,纹理的左上角映射到四边形的左上角,纹理的右下角映射到四边形的右下角,纹理的左下角映射到四边形的左下角。如果映射错误的话,图像显示时可能上下颠倒,侧向一边或者什么都不是。 (5) 现在增加xrot、yrot及zrot的值。尝试变化每次各变量的改变值来及调节立方体的旋转速度,或改变+/-号来调节立方体的旋转方向。 现在您应该比较好的理解纹理映射(贴图)了。您应该掌握了给任意四边形表面贴上您所喜爱的图像的技术。一旦您对2D纹理映射的理解感到自信的时候,试试给立方体的六个面贴上不同的纹理。 当您理解纹理坐标的概念后,纹理映射并不难理解。 You should now have a better understanding of texture mapping. You should be able to texture map the surface of any quad with an image of your choice. Once you feel confident with your understanding of 2D texture mapping, try adding six different textures to the cube. Texture mapping isn't to difficult to understand once you understand texture coordinates. 主要修改下面三个函数: AUX_RGBImageRec *LoadBMP(char *Filename); // Loads A Bitmap Image int LoadGLTextures(); // Load Bitmaps And Convert To Textures int DrawGLScene(GLvoid); // Here's Where We Do All The Drawing 完整代码:(因为是在Lesson 5基础上修改的,所以有点儿乱)

    // OpenGLWin32GUI.cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include "OpenGLWin32GUI.h" // #include <windows.h> // Windows的头文件 #include <stdio.h> // 标准输入/输出库的头文件 // 系统默认已有的头文件 #include <gl/gl.h> // OpenGL32库的头文件 #include <gl/glu.h> // GLu32库的头文件 #include <gl/glaux.h> // GLaux库的头文件 // 使用另外下载的glut工具包 //#include <gl/glut.h> // 附加lib文件 #pragma comment( lib, "opengl32.lib") // OpenGL32连接库 #pragma comment( lib, "glu32.lib") // GLu32连接库 #pragma comment( lib, "glaux.lib") // GLaux连接库 //#pragma comment(lib, "glut32.lib") HGLRC hRC=NULL; // 永久着色描述表 HDC hDC=NULL; // 私有GDI设备描述表 HWND hWnd=NULL; // 保存我们的窗口句柄 HINSTANCE hInstance; // 保存程序的实例 bool keys[256]; // 用于键盘例程的数组 bool active=TRUE; // 窗口的活动标志,缺省为TRUE bool fullscreen=TRUE; // 全屏标志缺省设定成全屏模式 GLfloat rtri; // 用于三角形的角度 GLfloat rquad; // 用于四边形的角度 GLfloat xrot; // X 旋转量 GLfloat yrot; // Y 旋转量 GLfloat zrot; // Z 旋转量 GLuint texture[1]; // 存储一个纹理 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);// WndProc的定义 AUX_RGBImageRec *LoadBMP(char *Filename)// Loads A Bitmap Image { FILE *File=NULL; if (!Filename)// Make Sure A Filename Was Given { return NULL;// If Not Return NULL } File=fopen(Filename,"r");// Check To See If The File Exists if (File)// Does The File Exist? { fclose(File); // Close The Handle return auxDIBImageLoad(Filename);// Load The Bitmap And Return A Pointer } return NULL;// If Load Failed Return NULL } int LoadGLTextures() // Load Bitmaps And Convert To Textures { int Status=FALSE;// Status Indicator AUX_RGBImageRec *TextureImage[1];// Create Storage Space For The Texture memset(TextureImage,0,sizeof(void *)*1);// Set The Pointer To NULL // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit if (TextureImage[0]=LoadBMP("Data/1.bmp")) { Status=TRUE;// Set The Status To TRUE glGenTextures(1, &texture[0]);// Create The Texture // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, texture[0]); // Generate The Texture glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);// Linear Filtering glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);// Linear Filtering } if (TextureImage[0])// If Texture Exists { if (TextureImage[0]->data)// If Texture Image Exists { free(TextureImage[0]->data);// Free The Texture Image Memory } free(TextureImage[0]);// Free The Image Structure } return Status;// Return The Status } GLvoid ReSizeGLScene(GLsizei width, GLsizei height)// 重置并初始化GL窗口大小 { if (height==0)// 防止被零除 { height=1;// 将Height设为1 } glViewport(0, 0, width, height);// 重置当前的视口(Viewport) glMatrixMode(GL_PROJECTION);// 选择投影矩阵 glLoadIdentity();// 重置投影矩阵 // 计算窗口的外观比例 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW);// 选择模型观察矩阵 glLoadIdentity();// 重置模型观察矩阵 } int InitGL(GLvoid)// 此处开始对OpenGL进行所有设置 { if (!LoadGLTextures())// 调用纹理载入子例程 { return FALSE;// 如果未能载入,返回FALSE } glEnable(GL_TEXTURE_2D);// 启用纹理映射 glShadeModel(GL_SMOOTH);// 启用阴影平滑 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);// 黑色背景 glClearDepth(1.0f);// 设置深度缓存 glEnable(GL_DEPTH_TEST);// 启用深度测试 glDepthFunc(GL_LEQUAL);// 所作深度测试的类型 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// 真正精细的透视修正 return TRUE;// 初始化 OK } int DrawGLScene(GLvoid)// 从这里开始进行所有的绘制 { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清除屏幕和深度缓存 glLoadIdentity();// 重置当前的模型观察矩阵 /*******************************************************/ // 增加新的物体 glTranslatef(0.0f,0.0f,-5.0f);// Move Into The Screen 5 Units glRotatef(xrot,1.0f,0.0f,0.0f);// Rotate On The X Axis glRotatef(yrot,0.0f,1.0f,0.0f);// Rotate On The Y Axis glRotatef(zrot,0.0f,0.0f,1.0f);// Rotate On The Z Axis glBindTexture(GL_TEXTURE_2D, texture[0]);// Select Our Texture glBegin(GL_QUADS); // Front Face glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad // Back Face glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad // Top Face glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad // Bottom Face glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad // Right face glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad // Left Face glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad glEnd(); xrot+=0.3f;// X Axis Rotation yrot+=0.2f;// Y Axis Rotation zrot+=0.4f;// Z Axis Rotation // // [1] 三角形 -> 四棱锥 // glTranslatef(-1.5f, 0.0f, -6.0f);// 左移1.5单位,并移入屏幕6.0 // glRotatef(rtri, 0.0f, 1.0f, 0.0f);// 绕Y轴旋转三角形 // // // glBegin(GL_TRIANGLES);// 绘制三角形 // // /* 前侧面 */ // glColor3f(1.0f, 0.0f, 0.0f); // 红色 // glVertex3f(0.0f, 1.0f, 0.0f); // 上顶点 // glColor3f(0.0f, 1.0f, 0.0f); // 绿色 // glVertex3f(-1.0f,-1.0f, 1.0f); // 左下 // glColor3f(0.0f, 0.0f, 1.0f); // 蓝色 // glVertex3f(1.0f, -1.0f, 1.0f); // 右下 // // /* 右侧面 */ // glColor3f(1.0f, 0.0f, 0.0f); // 红色 // glVertex3f(0.0f, 1.0f, 0.0f); // 三角形的上顶点 // glColor3f(0.0f, 0.0f, 1.0f); // 蓝色 // glVertex3f(1.0f, -1.0f, 1.0f); // 三角形的左下顶点 // glColor3f(0.0f, 1.0f, 0.0f); // 绿色 // glVertex3f(1.0f, -1.0f, -1.0f); // 三角形的右下顶点 // // /* 后侧面 */ // glColor3f(1.0f, 0.0f, 0.0f); // 红色 // glVertex3f(0.0f, 1.0f, 0.0f); // 三角形的上顶点 // glColor3f(0.0f, 1.0f, 0.0f); // 绿色 // glVertex3f(1.0f, -1.0f, -1.0f); // 三角形的左下顶点 // glColor3f(0.0f, 0.0f, 1.0f); // 蓝色 // glVertex3f(-1.0f, -1.0f, -1.0f);// 三角形的右下顶点 // // /* 左侧面 */ // glColor3f(1.0f, 0.0f, 0.0f); // 红色 // glVertex3f(0.0f, 1.0f, 0.0f); // 三角形的上顶点 // glColor3f(0.0f, 0.0f, 1.0f); // 蓝色 // glVertex3f(-1.0f, -1.0f, -1.0f);// 三角形的左下顶点 // glColor3f(0.0f, 1.0f, 0.0f); // 绿色 // glVertex3f(-1.0f, -1.0f, 1.0f); // 三角形的右下顶点 // // glEnd();// 三角形绘制结束 // // // // // [2] 正方形 -> 立方体 // // glLoadIdentity();// 重置模型观察矩阵 // glTranslatef(1.5f, 0.0f, -7.0f); // 右移1.5单位,并移入屏幕7.0 // //glTranslatef(1.5f, 0.0f, -6.0f); // 右移1.5单位,并移入屏幕6.0 // //glTranslatef(3.0f, 0.0f, 0.0f); // 右移3单位 // glRotatef(rquad, 1.0f, 1.0f, 1.0f); // 在XYZ轴上旋转立方体 // //glRotatef(rquad, 1.0f, 0.0f, 0.0f); // 绕X轴旋转四边形 // // // glBegin(GL_QUADS);// 绘制正方形 // // // glColor3f(0.5f,0.5f,1.0f);// 一次性将当前色设置为蓝色 // // glVertex3f(-1.0f, 1.0f, 0.0f);// 左上 // // glVertex3f( 1.0f, 1.0f, 0.0f);// 右上 // // glVertex3f( 1.0f,-1.0f, 0.0f);// 右下 // // glVertex3f(-1.0f,-1.0f, 0.0f);// 左下 // // /* Top */ // glColor3f(0.0f, 1.0f, 0.0f); // Set The Color To Green // glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Top) // glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Top) // glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top) // glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top) // // /* Bottom */ // glColor3f(1.0f, 0.5f, 0.0f); // Set The Color To Orange // glVertex3f( 1.0f,-1.0f, 1.0f); // Top Right Of The Quad (Bottom) // glVertex3f(-1.0f,-1.0f, 1.0f); // Top Left Of The Quad (Bottom) // glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Bottom) // glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Bottom) // // /* Front */ // glColor3f(1.0f, 0.0f, 0.0f); // Set The Color To Red // glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front) // glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front) // glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Front) // glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Front) // // /* Back */ // glColor3f(1.0f, 1.0f, 0.0f); // Set The Color To Yellow // glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Back) // glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Back) // glVertex3f(-1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Back) // glVertex3f( 1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Back) // // /* Left */ // glColor3f(0.0f, 0.0f, 1.0f); // Set The Color To Blue // glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left) // glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Left) // glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Left) // glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Left) // // /* Right */ // glColor3f(1.0f, 0.0f, 1.0f); // Set The Color To Violet // glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Right) // glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right) // glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Right) // glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Right) // // glEnd();// 正方形绘制结束 // // rtri+=1.0f; // 增加三角形的旋转变量 // //rtri+=0.2f; // 增加三角形的旋转变量 // rquad-=0.15f; // 减少四边形的旋转变量 /*******************************************************/ return TRUE; } GLvoid KillGLWindow(GLvoid)// 正常销毁窗口 { if (fullscreen)// 处于全屏模式吗 { ChangeDisplaySettings(NULL,0);// 是的话,切换回桌面 ShowCursor(TRUE);// 显示鼠标指针 } if (hRC)// 拥有着色描述表吗 { if (!wglMakeCurrent(NULL,NULL))// 能否释放DC和RC描述表 { MessageBox(NULL,_T("Release Of DC And RC Failed."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION); } if (!wglDeleteContext(hRC))// 能否删除RC { MessageBox(NULL,_T("Release Rendering Context Failed."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION); } hRC=NULL;// 将RC设为NULL } if (hDC && !ReleaseDC(hWnd,hDC))// 能否释放DC { MessageBox(NULL,_T("Release Device Context Failed."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION); hDC=NULL;// 将DC设为NULL } if (hWnd && !DestroyWindow(hWnd))// 能否销毁窗口 { MessageBox(NULL,_T("Could Not Release hWnd."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION); hWnd=NULL;// 将hWnd设为NULL } if (!UnregisterClass(_T("OpenGL"),hInstance))// 能否注销窗口类 { MessageBox(NULL,_T("Could Not Unregister Class."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION); hInstance=NULL;// 将hInstance设为NULL } } BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) //BOOL CreateGLWindow(LPCWSTR title, int width, int height, int bits, bool fullscreenflag) { GLuint PixelFormat; // 保存查找匹配的结果 WNDCLASS wc; // 窗口类结构 DWORD dwExStyle; // 扩展窗口风格 DWORD dwStyle; // 窗口风格 RECT WindowRect; // 取得矩形的左上角和右下角的坐标值 WindowRect.left=(long)0; // 将Left设为 0 WindowRect.right=(long)width; // 将Right设为要求的宽度 WindowRect.top=(long)0; // 将Top设为 0 WindowRect.bottom=(long)height; // 将Bottom设为要求的高度 fullscreen=fullscreenflag; // 设置全局全屏标志 hInstance = GetModuleHandle(NULL); // 取得窗口的实例 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // 移动时重画,并为窗口取得DC wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc处理消息 wc.cbClsExtra = 0; // 无额外窗口数据 wc.cbWndExtra = 0; // 无额外窗口数据 wc.hInstance = hInstance; // 设置实例 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // 装入缺省图标 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 装入鼠标指针 wc.hbrBackground = NULL; // GL不需要背景 wc.lpszMenuName = NULL; // 不需要菜单 wc.lpszClassName = _T("OpenGL"); // 设定类名字 if (!RegisterClass(&wc)) // 尝试注册窗口类 { MessageBox(NULL,_T("Failed To Register The Window Class."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 退出并返回FALSE } if (fullscreen)// 要尝试全屏模式吗 { DEVMODE dmScreenSettings; // 设备模式 memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // 确保内存分配 dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Devmode 结构的大小 dmScreenSettings.dmPelsWidth = width; // 所选屏幕宽度 dmScreenSettings.dmPelsHeight = height; // 所选屏幕高度 dmScreenSettings.dmBitsPerPel = bits; // 每象素所选的色彩深度 dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; // 尝试设置显示模式并返回结果。注: CDS_FULLSCREEN 移去了状态条。 if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { // 若模式失败,提供两个选项:退出或在窗口内运行。 if (MessageBox(NULL,_T("The Requested Fullscreen Mode Is Not Supported By/nYour Video Card. Use Windowed Mode Instead?"),_T("NeHe GL"),/ MB_YESNO|MB_ICONEXCLAMATION)==IDYES) { fullscreen=FALSE;// 选择窗口模式(Fullscreen=FALSE) } else { // Pop Up A Message Box Letting User Know The Program Is Closing. MessageBox(NULL,_T("Program Will Now Close."),_T("ERROR"),MB_OK|MB_ICONSTOP); return FALSE;//退出并返回FALSE } } } if (fullscreen)// 仍处于全屏模式吗 { dwExStyle=WS_EX_APPWINDOW; // 扩展窗体风格 dwStyle=WS_POPUP; // 窗体风格 ShowCursor(FALSE); // 隐藏鼠标指针 } else { dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // 扩展窗体风格 dwStyle=WS_OVERLAPPEDWINDOW; // 窗体风格 } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);// 调整窗口达到真正要求的大小 if (!(hWnd=CreateWindowEx( dwExStyle, // 扩展窗体风格 _T("OpenGL"), // 类名字 title, // 窗口标题 WS_CLIPSIBLINGS | // 必须的窗体风格属性 WS_CLIPCHILDREN | // 必须的窗体风格属性 dwStyle, // 选择的窗体属性 0,0, // 窗口位置 WindowRect.right-WindowRect.left, // 计算调整好的窗口宽度 WindowRect.bottom-WindowRect.top, // 计算调整好的窗口高度 NULL, // 无父窗口 NULL, // 无菜单 hInstance, // 实例 NULL))) // 不向WM_CREATE传递任何东东 { KillGLWindow();// 重置显示区 MessageBox(NULL,_T("Window Creation Error."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 返回 FALSE } static PIXELFORMATDESCRIPTOR pfd = //pfd 告诉窗口我们所希望的东东 { sizeof(PIXELFORMATDESCRIPTOR), //上述格式描述符的大小 1, // 版本号 PFD_DRAW_TO_WINDOW | // 格式必须支持窗口 PFD_SUPPORT_OPENGL | // 格式必须支持OpenGL PFD_DOUBLEBUFFER, // 必须支持双缓冲 PFD_TYPE_RGBA, // 申请 RGBA 格式 bits, // 选定色彩深度 0, 0, 0, 0, 0, 0, // 忽略的色彩位 0, // 无Alpha缓存 0, // 忽略Shift Bit 0, // 无聚集缓存 0, 0, 0, 0, // 忽略聚集位 16, // 16位 Z-缓存 (深度缓存) 0, // 无模板缓存 0, // 无辅助缓存 PFD_MAIN_PLANE, // 主绘图层 0, // 保留 0, 0, 0 // 忽略层遮罩 }; if (!(hDC=GetDC(hWnd)))// 取得设备描述表了么 { KillGLWindow();// 重置显示区 MessageBox(NULL,_T("Can't Create A GL Device Context."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 返回 FALSE } if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))// Windows 找到相应的象素格式了吗 { KillGLWindow();// 重置显示区 MessageBox(NULL,_T("Can't Find A Suitable PixelFormat."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 返回 FALSE } if(!SetPixelFormat(hDC,PixelFormat,&pfd))// 能够设置象素格式么 { KillGLWindow();// 重置显示区 MessageBox(NULL,_T("Can't Set The PixelFormat."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 返回 FALSE } if (!(hRC=wglCreateContext(hDC)))// 能否取得着色描述表 { KillGLWindow();// 重置显示区 MessageBox(NULL,_T("Can't Create A GL Rendering Context."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 返回 FALSE } if(!wglMakeCurrent(hDC,hRC))// 尝试激活着色描述表 { KillGLWindow();// 重置显示区 MessageBox(NULL,_T("Can't Activate The GL Rendering Context."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 返回 FALSE } ShowWindow(hWnd,SW_SHOW); // 显示窗口 SetForegroundWindow(hWnd); // 略略提高优先级 SetFocus(hWnd); // 设置键盘的焦点至此窗口 ReSizeGLScene(width, height); // 设置透视 GL 屏幕 if (!InitGL())// 初始化新建的GL窗口 { KillGLWindow();// 重置显示区 MessageBox(NULL,_T("Initialization Failed."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); return FALSE;// 返回 FALSE } return TRUE;// 成功 } LRESULT CALLBACK WndProc( HWND hWnd, // 窗口的句柄 UINT uMsg, // 窗口的消息 WPARAM wParam, // 附加的消息内容 LPARAM lParam) // 附加的消息内容 { switch (uMsg)// 检查Windows消息 { case WM_ACTIVATE:// 监视窗口激活消息 { if (!HIWORD(wParam))// 检查最小化状态 { active=TRUE;// 程序处于激活状态 } else { active=FALSE;// 程序不再激活 } return 0;// 返回消息循环 } case WM_SYSCOMMAND:// 中断系统命令Intercept System Commands { switch (wParam)// 检查系统调用Check System Calls { case SC_SCREENSAVE:// 屏保要运行? case SC_MONITORPOWER:// 显示器要进入节电模式? return 0;// 阻止发生 } break;// 退出 } case WM_CLOSE:// 收到Close消息? { PostQuitMessage(0);// 发出退出消息 return 0; } case WM_KEYDOWN:// 有键按下么? { keys[wParam] = TRUE;// 如果是,设为TRUE return 0;// 返回 } case WM_KEYUP:// 有键放开么? { keys[wParam] = FALSE;// 如果是,设为FALSE return 0;// 返回 } case WM_SIZE: { ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); return 0; } } // 向DefWindowProc传递所有未处理的消息。 return DefWindowProc(hWnd,uMsg,wParam,lParam); } int WINAPI WinMain( HINSTANCE hInstance, // 实例 HINSTANCE hPrevInstance, // 前一个实例 LPSTR lpCmdLine, // 命令行参数 int nCmdShow) // 窗口显示状态 { MSG msg; // Windowsx消息结构 BOOL done=FALSE; // 用来退出循环的Bool 变量 // 提示用户选择运行模式 if (MessageBox(NULL,_T("Would You Like To Run In Fullscreen Mode?"),_T("Start FullScreen?"),MB_YESNO|MB_ICONQUESTION)==IDNO) { fullscreen=FALSE; // 窗口模式 } // 创建OpenGL窗口 if (!CreateGLWindow(_T("WCDJ's OpenGL Framework"),640,480,16,fullscreen)) { return 0;// 失败退出 } while(!done)// 保持循环直到 done=TRUE { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))// 有消息在等待吗? { if (msg.message==WM_QUIT)// 收到退出消息? { done=TRUE;// 是,则done=TRUE } else// 不是,处理窗口消息 { TranslateMessage(&msg); // 翻译消息 DispatchMessage(&msg); // 发送消息 } } else// 如果没有消息 { // 绘制场景。监视ESC键和来自DrawGLScene()的退出消息 if (active)// 程序激活的么? { if (keys[VK_ESCAPE])// ESC 按下了么? { done=TRUE;// ESC 发出退出信号 } else// 不是退出的时候,刷新屏幕 { DrawGLScene();// 绘制场景 SwapBuffers(hDC);// 交换缓存 (双缓存) } } if (keys[VK_F1])// 允许用户按下F1键在全屏模式和窗口模式间切换 { keys[VK_F1]=FALSE;// 若是,使对应的Key数组中的值为 FALSE KillGLWindow();// 销毁当前的窗口 fullscreen=!fullscreen; // 切换 全屏 / 窗口 模式 // 重建 OpenGL 窗口 if (!CreateGLWindow(_T("WCDJ's OpenGL Framework"),640,480,16,fullscreen)) { return 0;// 如果窗口未能创建,程序退出 } } } } // 关闭程序 KillGLWindow();// 销毁窗口 return (msg.wParam);// 退出程序 }

     

     

    显示效果图片:

     

     

    留一个问题

    如何将bmp图片资源集成在可执行文件里,而不是单独地放在一个文件夹里?

     

    参考 : http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=06 nehe-src-cn —— Nehe的OpenGL教程中文版及代码下载 http://code.google.com/p/nehe-src-cn/downloads/list Nehe的OpenGL教程中文版及代码下载 http://www.yakergong.com/nehe/

     


    最新回复(0)