//OpenGL.h
class OpenGL
{
public:
OpenGL();
virtual ~OpenGL();
BOOL SetupPixelFormat(HDC hDc); //检测安装OpenGL
void init(int Width, int Height); //初始化
void Render(); //OpenGL图像处理
void CleanUp(); //清除OpenGL
private:
HDC hDC; //GDI设备描述表
HGLRC hRc; //永久着色描述表
};
//OpenGL.cpp
#include "OpenGL.h"
extern HWND hWnd;
OpenGL::OpenGL()
{
}
OpenGL::~OpenGL()
{
}
//检测安装OpenGL
BOOL OpenGL::SetupPixelFormat(HDC hDC0)
{
int nPixelFormat; //像素点格式
hDC = hDC0;
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), //pfd结构的大小
1, //版本号
PFD_DRAW_TO_BITMAP | //支持在窗口中绘图
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, L"没找到合适的显示模式", L"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(); //重置当前指定的矩阵为单位矩阵
}
//OpenGL图像处理
void OpenGL::Render()
{
glClearColor(0.0f, 0.0f, 0.3f, 1.0f); //设置刷新背景色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //刷新背景
glLoadIdentity(); //重置当前的模型观察矩阵
glFlush(); //更新窗口
SwapBuffers(hDC); //切换缓冲区
}
//清除OpenGL
void OpenGL::CleanUp()
{
wglMakeCurrent(hDC, NULL); //清除OpenGL
wglDeleteContext(hRc); //清除OpenGL
}
//main.cpp
#include "OpenGL.h"
//////////////////////////////////////////////////////////////
int Width = 800; //窗口宽
int Height = 800; //窗口高
int bits = 16; //颜色深度
OpenGL *m_OpenGL;
HDC hDC; //GDI设备句柄,将窗口连接到GDI(图形设备接口)
HGLRC hRc = NULL; //渲染描述句柄,将OpenGL调用连接到设备描述表
HWND hWnd = NULL; //保存windwos 分配给程序的窗口句柄
////////////////////////////////////////////////////////////////
LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //窗口回调函数
void GameLoop(); //游戏的消息循环
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, INT)
{
//注册窗口类
bool fullScreen = TRUE;
DWORD dwExStyle; //Window 扩展风格
DWORD dwStyle; //Window 窗口风格
RECT windwoRect; //窗口尺寸
int nX = 0, nY = 0;
if (IDNO == MessageBox(NULL, L"使用全屏模式吗?", L"将进入OpenGL选择显示模式",
MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL))
{
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; //windwo 扩展风格
dwStyle = WS_POPUP; //window 窗口风格
ShowCursor(FALSE); //隐藏鼠标
}
else
{
dwExStyle = WS_EX_APPWINDOW | 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(&windwoRect, dwStyle, FALSE, dwExStyle);
LPCWSTR cc = L"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, L"OpenGL程序框架",
dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
nX, nY, Width, Height,
NULL, NULL, hInstance, NULL
); //创建窗口
ShowWindow(hWnd, SW_SHOWDEFAULT); //显示窗口
UpdateWindow(hWnd); //更新窗口
GameLoop(); //进入消息循环
return 0;
}
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 CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd); //获取当前窗口的设备句柄
m_OpenGL->SetupPixelFormat(hDC); //调用显示模式安装功能
break;
case WM_CLOSE:
m_OpenGL->CleanUp();
PostQuitMessage(0);
break;
case WM_SIZE:
Height = HIWORD(lParam); //窗口的高
Width = LOWORD(lParam); //窗口的宽
if (Height == 0)
Height = 1;
m_OpenGL->init(Width, Height);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYUP:
switch (wParam)
{
case VK_ESCAPE:
m_OpenGL->CleanUp();
PostQuitMessage(0);
break;
default:
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}