OpenGL.h:
#pragma once
#include "resource.h"
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
OpenGL.cpp:
// OpenGL.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
#include <gl\glut.h>
#include "OpenGL.h"
#include "GfxOpenGL.h"
bool exiting = false; //程序是否退出.
long windowWidth = 800; //窗口宽度.
long windowHeight = 600; //窗口高度.
long windowBits = 32; //每个相素的字节位.
bool fullscreen = false; //是否全屏模式.
HDC hDC; //窗口设备环境.
CGfxOpenGL *g_glRender = NULL; //OpenGL渲染类的全局指针.
void SetupPixelFormat(HDC hDC) {
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // 大小,
1, // 版本都写1
PFD_SUPPORT_OPENGL | // OpenGL窗口
PFD_DRAW_TO_WINDOW | // 渲染窗口
PFD_DOUBLEBUFFER, // 支持双缓冲区.
PFD_TYPE_RGBA, // 颜色类型.
32, // 颜色深度.
0, 0, 0, 0, 0, 0, // 颜色位数(忽略)
0, // 没有alpha缓冲区.
0, // alpha缓冲区字节位
0, // 没有聚集缓冲区.
0, 0, 0, 0, // 聚集字节位.
16, // 深度缓冲区
0, // 没有模板缓冲区
0, // 没有辅助缓冲区.
PFD_MAIN_PLANE, // 主层冲
0, // 保留
0, 0, 0, // 没有层次, 可见性, 破损遮罩.
};
pixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pixelFormat, &pfd);
}
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static HDC hDC;
static HGLRC hRC; //渲染环境.
int height, width;
// 发送信息.
switch (uMsg) {
case WM_CREATE: // 创建窗口.
hDC = GetDC(hWnd); //获取窗口的设备环境.
SetupPixelFormat(hDC); //
hRC = wglCreateContext(hDC); //创建渲染环境.
wglMakeCurrent(hDC, hRC); //使当前环境生效.
break;
case WM_DESTROY: // 销毁窗口.
case WM_QUIT: //退出窗口.
case WM_CLOSE: // 关闭窗口.
wglMakeCurrent(hDC, NULL); //取消渲染环境
wglDeleteContext(hRC); //删除渲染环境.
PostQuitMessage(0); //将WM_QUIT发送到消息队列.
break;
case WM_SIZE: //大小改变时.
height = HIWORD(lParam); // 获取宽度和高度.
width = LOWORD(lParam);
g_glRender->SetupProjection(width, height);
break;
case WM_ACTIVATEAPP: // activate app
break;
case WM_PAINT: // paint
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN: // left mouse button
break;
case WM_RBUTTONDOWN: // right mouse button
break;
case WM_MOUSEMOVE: // mouse movement
break;
case WM_LBUTTONUP: // 左键弹起.
break;
case WM_RBUTTONUP: // 右键弹起.
break;
case WM_KEYUP:
break;
case WM_KEYDOWN:
int fwKeys;
LPARAM keyData;
fwKeys = (int)wParam; // 虚键码.
keyData = lParam; // 按键数据.
switch(fwKeys) {
case VK_ESCAPE:
PostQuitMessage(0);
break;
default:
break;
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
/**VS2010 应用程序入口**/
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX windowClass; //窗口类.
HWND hwnd; //窗口句柄.
MSG msg; //消息.
DWORD dwExStyle; //窗口的扩展样式.
DWORD dwStyle; //窗口样式.
RECT windowRect; //窗口矩形.
g_glRender = new CGfxOpenGL();
windowRect.left = (long)0;
windowRect.right = (long)windowWidth;
windowRect.top = (long)0;
windowRect.bottom = (long)windowHeight;
//填写窗口类的结构.
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = MainWindowProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 定义图标
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 默认箭头
windowClass.hbrBackground = NULL; // 不要背景
windowClass.lpszMenuName = NULL; // 没有菜单
windowClass.lpszClassName = _T("GLClass");
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // windows的小标记.
// 注册windows 类
if (!RegisterClassEx(&windowClass)) {
return 0;
}
if (fullscreen) { // 是否全屏.
DEVMODE dmScreenSettings; // 设备模式.
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = windowWidth; // 屏幕宽度.
dmScreenSettings.dmPelsHeight = windowHeight; // 屏幕高度.
dmScreenSettings.dmBitsPerPel = windowBits; // 每个象素字节位.
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
// 设置显示模式失败, 切换为窗口模式.
MessageBox(NULL, _T("Display mode failed"), NULL, MB_OK);
fullscreen = 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); // 将窗口调整为所需大小.
//类被注册.
hwnd = CreateWindowEx(NULL,
_T("GLClass"), // 类名
_T("BOGLGP - Chapter 2 - OpenGL Application"), // 应用程序的名称.
dwStyle | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0, // X和Y座标.
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top, // 宽度和高度.
NULL, // 父句柄.
NULL, // 菜单句柄.
hInstance, // 应用程序实例.
NULL); // 没有额外参数.
hDC = GetDC(hwnd);
// 查看窗口创建是否失败.(hwnd = NULL)
if(!hwnd) return 0;
ShowCursor(TRUE); //显示鼠标.
ShowWindow(hwnd, SW_SHOW); //显示窗口.
UpdateWindow(hwnd); //更新窗口.
g_glRender->Init(); //初始化PoenGL.
while (!exiting) {
g_glRender->Prepare(0.0f); //
g_glRender->Render(); //
SwapBuffers(hDC);
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {
if(!GetMessage (&msg, NULL, 0, 0)) {
exiting = true;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
delete g_glRender; //清除OpenGL
if (fullscreen) { //如果是全屏.
ChangeDisplaySettings(NULL,0); //切换到桌面.
ShowCursor(TRUE); //显示鼠标.
}
return (int)msg.wParam;
}
GfxOpenGL.h
#pragma once
class CGfxOpenGL {
private:
private:
int m_windowWidth;
int m_windowHeight;
float m_angle;
public:
CGfxOpenGL(void);
~CGfxOpenGL(void);
void CGfxOpenGL::Prepare(float ft);
void CGfxOpenGL::SetupProjection(int width, int height);
bool CGfxOpenGL::Init();
void CGfxOpenGL::Render();
};
GfxOpenGL.cpp:
#include "StdAfx.h"
#include "GfxOpenGL.h"
#include <windows.h>
#include <gl/glut.h>
CGfxOpenGL::CGfxOpenGL(void) { }
CGfxOpenGL::~CGfxOpenGL(void) { }
//禁用隐式的浮点数值到双精度数值的转换.
#pragma warning(disable:4305);
//设置窗口的投影矩阵.
void CGfxOpenGL::SetupProjection(int width, int height) {
if (height == 0) { // 不能除以0;
height = 1;
}
glViewport(0, 0, width, height); // 将窗口重设为新的尺寸.
glMatrixMode(GL_PROJECTION); // 将投影矩阵作为当前矩阵.
glLoadIdentity(); // 设置投影矩阵.
// 计算窗口的长宽比.
gluPerspective(52.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);
glMatrixMode(GL_MODELVIEW); // 设置模型观察矩阵.
glLoadIdentity(); // 重置模型观察矩阵.
m_windowWidth = width;
m_windowHeight = height;
}
//更新数据操作.
void CGfxOpenGL::Prepare(float ft){
m_angle += 0.1f;
}
//初始化方法.
bool CGfxOpenGL::Init(){
glClearColor(0.0, 0.0, 0.0, 0.0); //将背景清除为黑色.
m_angle = 0.1f; //初始化浮点全局变量.
return true;
}
//渲染场景.
void CGfxOpenGL::Render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓冲区.
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0f);
glRotatef(m_angle, 1.0f, 0.0f, 0.0f);
glRotatef(m_angle, 0.0f, 1.0f, 0.0f);
glRotatef(m_angle, 0.0f, 0.0f, 1.0f);
glColor3f(0.7f, 1.0f, 0.3f); //灰绿色.
//在中间绘制旋转的三角型.
glBegin(GL_TRIANGLES);
glVertex3f(1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glEnd();
}
获取当前环境: HGLRC wglGetCurrentContext(); .不存在返回NULL.
获取当前设备环境: HDC wglGetCurrentDC();
PIXELFORMATDESCRIPTOR结构的属必和行为:
typeof struct tagPIXELFORMATDESCRIPTOR{
WORD nSize; //结构大小. sizeof(PIXELFORMATDESCRIPTOR);
WORD nVersion //版本, 总被设置为1.
DWORD dwFlags; //像素缓冲区的属性标记.
BYTE iPixelType; //像素数据的类型.
BYTE cColorBits; //每个像素的字节位数.
BYTE cRedBits; //红色的字节位数.
BYTE cRedShift; //红色的移位计数.
BYTE cGreenBits; //绿色的字节位数.
BYTE cGreenShift; //绿色的移位计数.
BYTE cBlueBits; //蓝色的字节位数.
BYTE cBlueShift; //蓝色的移位计数.
BYTE cAlphaBits; //alpha的字节位数.
BYTE cAlphaShift; //alpha的移位计数.
BYTE cAccumBits; //累加缓冲区的字节位数.
BYTE cAccumRedBits; //红色累加的字节位数.
BYTE cAccumGreenBits;//绿色累加的字节位数.
BYTE cAccumBlueBits; //蓝色累加的字节位数.
BYTE cAccumAlphaBits;//alpha累加的字节位数.
BYYE cDepthBits; //深度缓冲区的字节位数.
BYTE cStencliBits; //特征缓冲区的字节位数.
BYTE cAuxBuffers; //辅助缓冲区的字节位数.
BYTE iLayerType; //不再使用.
BYTE bReserved; //覆盖面和底层面的数量.
DWORD dwLayerMask; //不再使用.
DWORD dwVisibleMask; //平面色彩下的透明.
DWORD dwDamageMask; //不再使用.
} PIXELFORMATDESCRIPTOR;