在这部分,与NeHe不同的是,OpenGL框架被定义为类,与windows框架分开,其内容与NeHe教程第一章大同小异。
错误记录:
1、WinMain只能在windows桌面应用中使用,main在控制台程序中使用,网上有教程说在控制台应用中,将属性->编译器->系统->subsystem中_CONSOLE改为_WINDOWS,实测并不可行,需要重新新建一个工程;
2、搭建框架时,OpenGL框架被定义为类保存于opengl.cpp中,我犯了一个很大的错误,未将类实例化(m_opengl = new opengl),花了一上午找问题,c++基础较为薄弱,及时看书时知道,写程序又忘了,还需要多加实践。
资源:
效果:
代码:
#include "stdafx.h"
#include "windows.h"
#include "opengl.h"
opengl* m_opengl;
HDC hDC;
HGLRC hRC = NULL;
HWND hWnd = NULL;
int Width = 800;
int Height = 600;
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;
m_opengl->init(Width, Height);
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYUP:
switch (wParam)
{
case VK_ESCAPE:
m_opengl->CleanUp();
PostQuitMessage(0);
return 0;
break;
default:
break;
}
default:
break;
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, INT)
{
bool fullScreen = TRUE;
DWORD dwExStyle;
DWORD dwStyle;
RECT windowRect;
int nX = 0, nY = 0;
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;//使窗口具有3D外观
dwStyle = 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,
(LPCWSTR)cc,NULL
};
RegisterClassEx(&wc);
m_opengl = new opengl;
HWND hWnd = CreateWindowEx(NULL,
(LPCWSTR)cc,
L"OpenGL Game",
dwStyle | WS_CLIPCHILDREN,
nX, nY,
Width, Height,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
GameLoop();
return 0;
}
#include "stdafx.h"
#include "opengl.h"
#include "OPENGLSB.H"
extern HWND hWnd;
opengl::opengl()
{
}
opengl::~opengl()
{
CleanUp();
}
BOOL opengl::SetupPixelFormat(HDC hDC)
{
int nPixelFormat;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
16,
0,0,0,0,0,0,
0,
0,
0,
0,0,0,0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0
};
if (!(nPixelFormat = ChoosePixelFormat(hDC, &pfd)))
{
MessageBox(NULL, (LPCWSTR)"cannot find", (LPCWSTR)"Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
SetPixelFormat(hDC, nPixelFormat, &pfd);
hRC = wglCreateContext(hDC);//获取渲染描述句柄
wglMakeCurrent(hDC, hRC);//激活渲染描述句柄
return TRUE;
}
void opengl::init(float Width, float Height)
{
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective
(45.0f,//透视角设置为45度
Width / Height,
1.0f,//近点
1000.0f//远点
);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void opengl::Render()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glFlush();
SwapBuffers(hDC);
}
void opengl::CleanUp()
{
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
}
#pragma once
class opengl
{
public:
opengl();
~opengl();
public:
HDC hDC;
HGLRC hRC;
BOOL SetupPixelFormat(HDC hDC);
void init(float Width, float Height);
void Render();
void CleanUp();
};