OpenGL程序框架

http://hi.baidu.com/shirdrn/blog/item/1467311997a65d4343a9adf8.html

 

OpenGL程序框架在很多教程中都有人介绍过了,作为我个人学习,我还是写一下。

在实现OpenGL的框架之前,必须保证你已经正确配置好了OpenGL,才能通过建立OpenGL框架来测试。

启动VC 6,新建一个名称为OpenGL的Win32 Console Application,新建一些头文件和CPP文件,工程结果如图所示:

下面对工程中的文件简单介绍:

第一个:StdAfx.h头文件

StdAfx.h是与VC的框架相关,生成程序框架的。该文件内容如下所示:

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(AFX_STDAFX_H__78441E1B_7353_4082_9B09_20806569F5EA__INCLUDED_)
#define AFX_STDAFX_H__78441E1B_7353_4082_9B09_20806569F5EA__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define WIN32_LEAN_AND_MEAN   // Exclude rarely-used stuff from Windows headers

#include <windows.h> // Windows的头文件

#include <mmsystem.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <gl/gl.h>   // OpenGL32库的头文件
#include <gl/glu.h>   // GLu32库的头文件
#include <gl/glaux.h> // GLaux库的头文件
#pragma comment( lib, "winmm.lib")
#pragma comment( lib, "opengl32.lib") // OpenGL32连接库
#pragma comment( lib, "glu32.lib")   // GLu32连接库
#pragma comment( lib, "glaux.lib")   // GLaux连接库

// TODO: reference additional headers your program requires here

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__78441E1B_7353_4082_9B09_20806569F5EA__INCLUDED_)

 

这里默认主要生成工程的程序框架,而且,我们已经将OpenGL库配置到VC里面,现在它已经作为工程框架的一部分,在StdAfx.h文件中引入。

第二个:StdAfx.cpp头文件

这是个C++源文件,并没有做什么事情,只是引用了StdAfx.h头文件,代码如下所示:

// stdafx.cpp : source file that includes just the standard includes
// OpenGL.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

只是包含StdAfx.h头文件。

第三个:OpenGL.h头文件

这里,声明了一个OpenGL类,定义中声明了安装、初始化、渲染、清除OpenGL的方法,实现是在OpenGL.cpp文件中。OpenGL.h头文件的源代码如下所示:

// OpenGL.h: interface for the OpenGL class.
//
//

#if !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_)
#define AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class OpenGL 
{ public: OpenGL();
virtual ~OpenGL();
public:

HDC   hDC;    // GDI设备描述表
HGLRC hRC;   // 永久着色描述表
BOOL SetupPixelFormat(HDC hDC); // 检测安装OpenGL
void init(int Width, int Height);
void Render(); // OpenGL图形处理,是一个渲染的过程
void CleanUp(); // 清除OpenGL
};

#endif // !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_)

各个方法的功能可以参考注释。

第四个:OpenGL.cpp类文件

该类中真正实现了头文件OpenGL.h中声明的方法。源代码如下所示:

// OpenGL.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "OpenGL.h"
//
extern HWND hWnd;

//
OpenGL::OpenGL()
{
}
OpenGL::~OpenGL()
{ CleanUp();
}
BOOL OpenGL::SetupPixelFormat(HDC hDC0) // 检测安装OpenGL
{ int nPixelFormat;       // 象素点格式
hDC=hDC0;
PIXELFORMATDESCRIPTOR pfd = { 
     sizeof(PIXELFORMATDESCRIPTOR),    // pfd结构的大小 
     1,                                // 版本号 
     PFD_DRAW_TO_WINDOW |              // 支持在窗口中绘图 
     PFD_SUPPORT_OPENGL |              // 支持 OpenGL 
     PFD_DOUBLEBUFFER,                 // 双缓存模式 
     PFD_TYPE_RGBA,                    // RGBA 颜色模式 
     16,                               // 24 位颜色深度 
     0, 0, 0, 0, 0, 0,                 // 忽略颜色位 
     0,                                // 没有非透明度缓存 
     0,                                // 忽略移位位 
     0,                                // 无累加缓存 
     0, 0, 0, 0,                       // 忽略累加位 
     16,                               // 32 位深度缓存     
     0,                                // 无模板缓存 
     0,                                // 无辅助缓存 
     PFD_MAIN_PLANE,                   // 主层 
     0,                                // 保留 
     0, 0, 0                           // 忽略层,可见性和损毁掩模 
}; 
if (!(nPixelFormat = ChoosePixelFormat(hDC, &pfd)))
   { MessageBox(NULL,"没找到合适的显示模式","Error",MB_OK|MB_ICONEXCLAMATION);
       return FALSE;
   }
SetPixelFormat(hDC,nPixelFormat,&pfd);//设置当前设备的像素点格式
hRC = wglCreateContext(hDC);          // 获取渲染描述句柄
wglMakeCurrent(hDC, hRC);             // 激活渲染描述句柄
return TRUE;
}
void OpenGL::init(int Width, int Height)
{ glViewport(0,0,Width,Height);    // 设置OpenGL视口大小。 
glMatrixMode(GL_PROJECTION);    // 设置当前矩阵为投影矩阵。
glLoadIdentity();       // 重置当前指定的矩阵为单位矩阵
gluPerspective        // 设置透视图
   ( 54.0f,        // 透视角设置为 45 度
    (GLfloat)Width/(GLfloat)Height, // 窗口的宽与高比
    0.1f,         // 视野透视深度:近点1.0f
    3000.0f        // 视野透视深度:始点0.1f远点1000.0f
   );
// 这和照象机很类似,第一个参数设置镜头广角度,第二个参数是长宽比,后面是远近剪切。
glMatrixMode(GL_MODELVIEW);     // 设置当前矩阵为模型视图矩阵
glLoadIdentity();       // 重置当前指定的矩阵为单位矩阵
//====================================================
}
void OpenGL::Render() // OpenGL图形处理
{ glClearColor(0.0f, 0.0f, 0.3f, 1.0f);    // 设置刷新背景色
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);// 刷新背景
glLoadIdentity();         // 重置当前的模型观察矩阵

glFlush();           // 更新窗口
SwapBuffers(hDC);         // 切换缓冲区
}
void OpenGL::CleanUp() // 清除OpenGL
{
wglMakeCurrent(hDC, NULL);                       // 清除OpenGL
wglDeleteContext(hRC);                           // 清除OpenGL

}

注释已经非常清晰地解释了各个方法功能的实现及其原理。

第五个:OpenGLFramework.cpp源文件

该文件中,涉及到了VC的实现机制,即基于消息机制,可以通过参考其他更多的关于VC的内容,来了解VC。

源代码如下所示:

// OpenGLFramework.cpp : Defines the entry point for the application.
#include "stdafx.h"
#include "OpenGL.h"
//
OpenGL* m_OpenGL;
HDC   hDC;   // GDI设备句柄,将窗口连接到 GDI( 图形设备接口)
HGLRC hRC=NULL; // 渲染描述句柄,将OpenGL调用连接到设备描述表 
HWND hWnd=NULL; // 保存 Windows 分配给程序的窗口句柄
int   Width = 400;// 窗口宽
int   Height= 300;// 窗口高
int   bits = 16; // 颜色深度
void GameLoop()
{   MSG msg; 
    BOOL fMessage;
    PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
    while(msg.message != WM_QUIT) // 消息循环
    {   fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
        if(fMessage)     //有消息
    { TranslateMessage(&msg);
              DispatchMessage(&msg);
    }
        else m_OpenGL->Render(); //无消息
    }
}
LRESULT WINAPI MsgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam )// 消息处理
{ switch(message)
{ case WM_CREATE:       // 建立窗口
    hDC = GetDC(hWnd);     // 获取当前窗口的设备句柄
    m_OpenGL->SetupPixelFormat(hDC);// 调用显示模式安装功能
    return 0;   break;
   case WM_CLOSE:       // 关闭窗口
    m_OpenGL->CleanUp();    // 结束处理
    PostQuitMessage(0);
    return 0;   break;
   case WM_SIZE:       // 窗口尺寸变化
    Height = HIWORD(lParam);   // 窗口的高
    Width = LOWORD(lParam);   // 窗口的宽
    if (Height==0) Height=1;   // 防止被0 除
    m_OpenGL->init(Width,Height);
    return 0;   break;
   case WM_DESTROY:      // 退出消息
            PostQuitMessage(0);
            return 0;   break;
        case WM_KEYUP:       // 按ESC退出,全屏模式必需要加入的退出方式。
            switch (wParam)
            { case VK_ESCAPE:
      m_OpenGL->CleanUp(); // 结束处理
        PostQuitMessage(0);
        return 0;break;
            } 
   default:    break;
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,INT )// WinMain程序入口
{   // 注册窗口类
bool fullScreen =TRUE;
DWORD dwExStyle;   // Window 扩展风格
DWORD dwStyle;   // Window 窗口风格
RECT windowRect;   // 窗口尺寸
int   nX=0,nY=0;
// 判断是否进入全屏模式
/* if (MessageBox(NULL,"使用全屏模式吗?", "将进入OpenGL,选择显示模式",
             MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL)==IDNO)
   {fullScreen =false;}    // 选择窗口模式
if (fullScreen)       // 选择全屏模式
{ DEVMODE dmScr;      // 设备模式
   memset(&dmScr,0,sizeof(dmScr)); // 确保内存分配
   dmScr.dmSize=sizeof(dmScr);   // Devmode 结构的大小
   dmScr.dmPelsWidth = Width;   // 屏幕宽
   dmScr.dmPelsHeight= Height;   // 屏幕高
   dmScr.dmBitsPerPel= 16;    // 色彩深度
   dmScr.dmDisplayFrequency=75; // 刷屏速度
   dmScr.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
   if (ChangeDisplaySettings(&dmScr, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
    {fullScreen=FALSE;}
   dwExStyle=WS_EX_APPWINDOW;   // Window 扩展风格
   dwStyle=WS_POPUP;     // Window 窗口风格
   ShowCursor(FALSE);     // 隐藏鼠标
}
else*/

{ dwExStyle=WS_EX_AWS_OVERLAPPEDWINDOWPPWINDOW|WS_EX_WINDOWEDGE; // 使窗口具有3D外观
   dwStyle= WS_OVERLAPPEDWINDOW;     // 使用标准窗口
   //WS_OVERLAPPEDWINDOW是有标题栏,窗口菜单,最大、小化按钮和可调整尺寸的窗口
   int wid=GetSystemMetrics(SM_CXSCREEN);   // 获取当前屏幕宽
   int hei=GetSystemMetrics(SM_CYSCREEN);   // 获取当前屏幕高
   nX=(wid-Width)/2;nY=(hei-Height)/2;    // 计算窗口居中用
}
//-------------------------------------------------------------------
AdjustWindowRectEx(&windowRect,dwStyle,FALSE,dwExStyle);
          //根据窗口风格来调整窗口尺寸达到要求的大小
char cc[]="tml";
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      cc, NULL };
    RegisterClassEx( &wc );
m_OpenGL=new OpenGL();//
hWnd = CreateWindowEx(NULL,cc,"OpenGL的程序框架",
        dwStyle|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
        nX, nY,Width, Height,
        NULL,NULL,hInst,NULL); // 创建窗口
ShowWindow( hWnd, SW_SHOWDEFAULT );     // 显示窗口
UpdateWindow( hWnd );        // 刷新窗口
GameLoop();           // 进入消息循环
    return 0;
}

可以参考注释来简单了解一下。

测试OpenGL程序框架

现在可以测试,显示OpenGL程序框架了。而且,在以后的所有OpenGL应用,都可以基于该程序框架来开发。

测试如图所示:

实际上,这个框架就是一个自定义的窗口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值