转某个修改过的nehe

学习了《NeHe's OpenGL Tutorials》后感觉其程序结构设计并不是太理想,因此在此基础之上重写了部分代码:

说明:

首先在在Visual C++6.0中建立一个Win32 Application的空Project;

其次在Visual C++6.0中配置OpenGL,方法有两种:1.Project->Settings->Link选项卡的Project Options栏中添加OpenGL32.lib GLu32.lib GLaux.lib于kernel32.lib之前,中间用空格隔开,点击“OK”退出。2.在WinMain函数同一文件中添加:

#pragma comment( lib, "opengl32.lib") // OpenGL32连接库
#pragma comment( lib, "glu32.lib")    // GLu32连接库
#pragma comment( lib, "glaux.lib")    // GLaux连接库

另外要运行该程序选择6张bmp格式的图片大小为:200px,分辨率最好为:72dpi。将该6张图片依次命名为:OpenGL01.bmp,OpenGL02.bmp,OpenGL03.bmp,OpenGL04.bmp,OpenGL05.bmp,OpenGL06.bmp,并将其放于你所创建的工程文件目录中(直接运行*.exe时,图片和可执行文件放在同一目录下)。

按照以上设置完成后即可将以下代码复制到相应的文件中并添加到(Project->Add To Project->Files)你所建立的工程文件。

头文件:stdafx.h的源代码

#define WIN32_LEAN_AND_MEAN      //从Windows中排除极少使用的资料
#include <windows.h>       //Windows头文件
#include <stdio.h>       //标准输入输出文件
#include <GL\gl.h>       //OpenGL32库的头文件
#include <GL\glu.h>       //glu32库的头文件
#include <GL\glaux.h>      //glaux库的头文件

#include "OpenGL.h"

头文件:OpenGL.h的源代码

class OpenGL
{
private:
GLuint Texture[6];    //纹理数据存储
public:
GLvoid ReSizeGLScene(GLsizei width,GLsizei height);   //重设并初始化窗口大小
int InitGL(GLvoid);           //对OpenGL进行所有设置
int DrawGLScene(GLvoid);         //进行所有绘制
AUX_RGBImageRec *LoadBMP(char *Filename);     //载入位图图象
bool LoadGLTextures(char *Filename,GLuint &texture); //载入位图并转换为纹理
};

cpp文件:WinMain.cpp的源代码

//包含头文件
#include "stdafx.h"        //包含全局头文件

//函数声明
bool CreateGLWindow(char,int,int,int,bool);   //创建窗口
GLvoid KillGLWindow(GLvoid);      //正常销毁窗口
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//接收消息

//全局变量
HGLRC   hRC    = NULL;     //永久着色描述表
HDC    hDC    = NULL;     //私有你GDI设备描述表
HWND   hWnd   = NULL;     //保存我们的窗口句柄
HINSTANCE hInstance;        //保存程序的实例

bool   keys[256] = {false};    //用于键盘例程的数组
bool   bActive   = true;     //窗口的活动标志
bool   bFullscreen = true;     //全屏标志,默认使用全屏
OpenGL   *myGL   = new OpenGL();   //类申请
char   *Title   = "OpenGL RGB Studio";//窗口标题

//函数
bool CreateGLWindow(char *title,int width,int height,int bits,bool bFullScreenFlag)
{
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为要求的高度

bFullscreen=bFullScreenFlag;     //设置全屏标志

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 = "OpenGL";    //设定类名字

if(!RegisterClass(&wc))       //注册窗口类
{
   MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
   return false;
}

if(bFullscreen)         //全屏
{
   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;
  
   if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
   {           //设置显示模式并返回结果
    if(MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By Your Video Card. Use Window Mode Instead?","OpenGL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
    {          //若设置失败则退出或者在窗口运行
     bFullscreen=false;     //选择窗口模式
    }
    else
    {
     MessageBox(NULL,"Program Will Close Now.","ERROR",MB_OK|MB_ICONSTOP);
     return false;
    }
   }
}

if(bFullscreen)         //是否全屏
{
   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);//调整窗口达到真正要求的大小

//以下用于计算初始时的窗口位置
int wid   = GetSystemMetrics(SM_CXSCREEN);   // 获取当前屏幕宽
int hei   = GetSystemMetrics(SM_CYSCREEN);   // 获取当前屏幕高
int Width = WindowRect.right-WindowRect.left; //窗口的宽度
int Height = WindowRect.bottom-WindowRect.top; //窗口的高度

if (!(hWnd=CreateWindowEx(dwExStyle,   //扩展窗体风格
   "OpenGL",         //类名字
   title,          //窗口标题
   WS_CLIPSIBLINGS|       //必须的窗体风格属性
   WS_CLIPCHILDREN|       //必须的窗体风格属性
   dwStyle,         //选择的窗体属性
   (wid-Width)/2,(hei-Height)/2,    //窗口位置居中
   WindowRect.right-WindowRect.left,   //计算调整好的窗口宽度
   WindowRect.bottom-WindowRect.top,   //计算调整好的窗口高度
   NULL,          //无父窗口
   NULL,          //无菜单
   hInstance,         //实例
   NULL)))          //不向WM_CREATE传递任何东东
{
   KillGLWindow();        //重置显示区
   MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
   return 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,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
   return false;
}

if(!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) //是否找到相应的象素格式
{
   KillGLWindow();        //重置显示区
   MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
   return false;
}

if(!SetPixelFormat(hDC,PixelFormat,&pfd)) //是否能够设置象素格式
{
   KillGLWindow();        //重置显示区
   MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
   return false;
}

if(!(hRC=wglCreateContext(hDC)))    //能否取得着色描述表?
{
   KillGLWindow();        //重置显示区
   MessageBox(NULL,"Can’t Create A GL Rendering Context.",
    "ERROR",MB_OK|MB_ICONEXCLAMATION);
   return false;        //返回 FALSE
}

if(!wglMakeCurrent(hDC,hRC))     //尝试激活着色描述表
{
   KillGLWindow();        //重置显示区
   MessageBox(NULL,"Can’t Activate The GL Rendering Context.",
    "ERROR",MB_OK|MB_ICONEXCLAMATION);
   return false;        //返回 FALSE
}

ShowWindow(hWnd,SW_SHOW);      //显示窗口
SetForegroundWindow(hWnd);      //略略提高优先级
SetFocus(hWnd);         //设置键盘的焦点至此窗口
myGL->ReSizeGLScene(width, height);    //设置透视GL屏幕

if(!myGL->InitGL())        //初始化新建的GL窗口
{
   KillGLWindow();        //重置显示区
   MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
   return false;        //返回 FALSE
}
return true;         //成功
}

GLvoid KillGLWindow(GLvoid)       //正常销毁窗口
{
if(bFullscreen)         //是否处于全屏状态
{
   ChangeDisplaySettings(NULL,0);    //换回桌面
   ShowCursor(true);       //显示鼠标指针
}
if(hRC!=NULL)         //是否拥有颜色着色表
{
   if(!wglMakeCurrent(NULL,NULL))    //能否释放DC和RC描述表
   {
    MessageBox(NULL,"Release DC And RC Failed.","ERROR",MB_OK|MB_ICONINFORMATION);
   }
  
   if(!wglDeleteContext(hRC))     //能否删除RC
   {
    MessageBox(NULL,"Release Rendering Context Failed.","ERROR",MB_OK|MB_ICONINFORMATION);
   }
   hRC=NULL;
}

if(hDC&&!ReleaseDC(hWnd,hDC))     //能否释放DC
{
   MessageBox(NULL,"Could not Release Device Context.","ERROR",MB_OK|MB_ICONINFORMATION);
   hDC=NULL;
}

if(hWnd&&!DestroyWindow(hWnd))     //能否销毁窗口
{
   MessageBox(NULL,"Could not Release hWnd.","ERROR",MB_OK|MB_ICONINFORMATION);
   hWnd=NULL;
}

if(!UnregisterClass("OpenGL",hInstance))
{            //能否注销类
   MessageBox(NULL,"Could Not Unregister Class.","ERROR",MB_OK|MB_ICONINFORMATION);
   hInstance=NULL;
}
}


LRESULT CALLBACK WndProc(HWND hWnd,     //窗口的句柄
       UINT uMsg,     //窗口的消息
       WPARAM wParam,    //附加的消息内容
       LPARAM lParam)    //附加的消息内容
{
switch(uMsg)         //检查Windows消息
{
case WM_ACTIVATE:        //监视窗口激活消息
   {
    if(!HIWORD(wParam))      //检查最小化状态
    {
     bActive=true;      //程序处于激活状态
    }
    else
    {
     bActive=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;
    return 0;
   }
case WM_KEYUP:         //有键放开
   {
    switch(wParam)
    {
    case VK_ESCAPE:
     PostQuitMessage(0);
     return 0;
    default:
     break;
    }
    keys[wParam]=false;
    return 0;
   }
case WM_SIZE:
   {
    myGL->ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
    return 0;
   }
}
return DefWindowProc(hWnd,uMsg,wParam,lParam); //向 DefWindowProc传递所有未处理的消息。
}

int WINAPI WinMain( HINSTANCE hInstance,   //实例
       HINSTANCE hPrevInstance,   //前一个实例
       LPSTR lpCmdLine,     //命令行参数
       int nCmdShow)     // 窗口显示状态
{
MSG msg;          //Windowsx消息结构
bool bExit=false;        //用来退出循环的Bool变量
myGL=new OpenGL();        //OpenGL类申请

if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?",
   "Start Fullscreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{            // 提示用户选择运行模式
   bFullscreen=false;       //窗口模式
}

if (!CreateGLWindow(Title,640,480,16,bFullscreen))
{            //创建OpenGL窗口
   return 0;         //失败退出
}

while(!bExit)         //保持循环直到bExit=true
{
   if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))//是否有消息在等待
   {
    if (msg.message==WM_QUIT)    //是否收到退出消息
    {
     bExit=true;       //bExit=true则退出
    }
    else         //不是,处理窗口消息
    {
     TranslateMessage(&msg);    //翻译消息
     DispatchMessage(&msg);    //发送消息
    }
   }
   else
   {
    if(bActive)        //窗口是否处于最小化状态
    {
     myGL->DrawGLScene();    //绘制场景
     SwapBuffers(hDC);     //交换缓存(双缓存)
    }
   }
}

KillGLWindow();         //销毁窗口
delete myGL;         //删除类指针
return (msg.wParam);       //退出程序
}

cpp文件:OpenGL.cpp的源代码

#include "stdafx.h"

AUX_RGBImageRec *OpenGL::LoadBMP(char *filename)   //载入位图图象
{
FILE *pFile=NULL;        //位图文件指针
if(!filename)
{
   return NULL;
}

pFile=fopen(filename,"r");
if(pFile!=NULL)
{
   fclose(pFile);
   return auxDIBImageLoad(filename);   //载入位图
}
return NULL;
}

bool OpenGL::LoadGLTextures(char *filename,GLuint &texture)   //载入位图并转换为纹理
{
bool bStatus=false;
AUX_RGBImageRec *TextureImage=new AUX_RGBImageRec;    //创建纹理的存储空间
memset(TextureImage,0,sizeof(void *)*1);

if(TextureImage=LoadBMP(filename))
{
   bStatus=true;

   glGenTextures(1,&texture);     //创建纹理
   glBindTexture(GL_TEXTURE_2D,texture); //使用来自位图的数据生成的典型纹理

   gluBuild2DMipmaps(GL_TEXTURE_2D,3, TextureImage->sizeX,
       TextureImage->sizeY,GL_RGB, GL_UNSIGNED_BYTE,TextureImage->data);

//   glTexImage2D(GL_TEXTURE_2D,0,3,
//    TextureImage->sizeX,TextureImage->sizeY,
//    0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage->data);

   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//线型滤波
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//线型滤波
}

if(TextureImage!=NULL)       //纹理是否存在
{
   if(TextureImage->data)      //纹理图像是否存在
   {
    delete TextureImage->data;    //释放纹理图像占用的内存
   }
   delete TextureImage;      //释放图像结构
}

return bStatus;
}

GLvoid OpenGL::ReSizeGLScene(GLsizei width,GLsizei height)
//重设并初始化窗口大小
{
if(height==0)         //防止被0除
{
   height=1;         //将height设为1
}
glViewport(0,0,width,height);     //重置当前的视口
glMatrixMode(GL_PROJECTION);     //选择投影矩阵
glLoadIdentity();        //重设投影矩阵

gluPerspective(45.0,(GLfloat)width/(GLfloat)height,0.01f,1000.0f); //计算窗口的外观比例

glMatrixMode(GL_MODELVIEW);      //选择模型观察矩阵
glLoadIdentity();        //重设模型观察矩阵
}

int OpenGL::InitGL(GLvoid)       //对OpenGL进行所有设置
{
LoadGLTextures("OpenGL01.bmp",Texture[0]); //载入纹理1
LoadGLTextures("OpenGL02.bmp",Texture[1]); //载入纹理2
LoadGLTextures("OpenGL03.bmp",Texture[2]); //载入纹理3
LoadGLTextures("OpenGL04.bmp",Texture[3]); //载入纹理4
LoadGLTextures("OpenGL05.bmp",Texture[4]); //载入纹理5
LoadGLTextures("OpenGL06.bmp",Texture[5]); //载入纹理6

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;
}

int OpenGL::DrawGLScene(GLvoid)        //从这里开始进行所有绘制
{
static float spin=0.0f;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
glLoadIdentity();        //重设投影矩阵

glTranslatef(0.0f,0.0f,-10.0f);     //向内平移10
glRotatef(spin+=0.05f,1.0f,1.0f,1.0f);   //自转转spin角度

glBindTexture(GL_TEXTURE_2D,Texture[0]); //选择纹理
glBegin(GL_QUADS);
   // 前面
   glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f); //纹理和四边形的左下
   glTexCoord2f(1.0f, 0.0f);glVertex3f( 1.0f,-1.0f, 1.0f); //纹理和四边形的右下
   glTexCoord2f(1.0f, 1.0f);glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的右上
   glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的左上
glEnd();

glBindTexture(GL_TEXTURE_2D,Texture[1]); //选择纹理
glBegin(GL_QUADS);  
   //后面
   glTexCoord2f(1.0f, 0.0f);glVertex3f(-1.0f,-1.0f,-1.0f); //纹理和四边形的右下
   glTexCoord2f(1.0f, 1.0f);glVertex3f(-1.0f, 1.0f,-1.0f); //纹理和四边形的右上
   glTexCoord2f(0.0f, 1.0f);glVertex3f( 1.0f, 1.0f,-1.0f); //纹理和四边形的左上
   glTexCoord2f(0.0f, 0.0f);glVertex3f( 1.0f,-1.0f,-1.0f); //纹理和四边形的左下
glEnd();
  
glBindTexture(GL_TEXTURE_2D,Texture[2]); //选择纹理
glBegin(GL_QUADS);
   // 顶面
   glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f,-1.0f); //纹理和四边形的左上
   glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的左下
   glTexCoord2f(1.0f, 0.0f);glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的右下
   glTexCoord2f(1.0f, 1.0f);glVertex3f( 1.0f, 1.0f,-1.0f); //纹理和四边形的右上
glEnd();
  
glBindTexture(GL_TEXTURE_2D,Texture[3]); //选择纹理
glBegin(GL_QUADS);
   //底面
   glTexCoord2f(1.0f, 1.0f);glVertex3f(-1.0f,-1.0f,-1.0f); //纹理和四边形的右上
   glTexCoord2f(0.0f, 1.0f);glVertex3f( 1.0f,-1.0f,-1.0f); //纹理和四边形的左上
   glTexCoord2f(0.0f, 0.0f);glVertex3f( 1.0f,-1.0f, 1.0f); //纹理和四边形的左下
   glTexCoord2f(1.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f); //纹理和四边形的右下
glEnd();
  
glBindTexture(GL_TEXTURE_2D,Texture[4]); //选择纹理
glBegin(GL_QUADS);
   // 右面
   glTexCoord2f(1.0f, 0.0f);glVertex3f( 1.0f,-1.0f,-1.0f); //纹理和四边形的右下
   glTexCoord2f(1.0f, 1.0f);glVertex3f( 1.0f, 1.0f,-1.0f); //纹理和四边形的右上
   glTexCoord2f(0.0f, 1.0f);glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的左上
   glTexCoord2f(0.0f, 0.0f);glVertex3f( 1.0f,-1.0f, 1.0f); //纹理和四边形的左下
glEnd();
  
glBindTexture(GL_TEXTURE_2D,Texture[5]); //选择纹理
glBegin(GL_QUADS);
   // 左面
   glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f,-1.0f,-1.0f); //纹理和四边形的左下
   glTexCoord2f(1.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f); //纹理和四边形的右下
   glTexCoord2f(1.0f, 1.0f);glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的右上
   glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f,-1.0f); //纹理和四边形的左上
glEnd();

return true;
}

posted @ 2010-07-13 18:47  香远益清  阅读(482)  评论(0编辑  收藏  举报