步骤:
1、创建windows窗口,得到窗口句柄hwnd
2、获取该窗口的设备环境hDC(当然也可以获取其他的设备环境,但我们一般是在创建的窗口上绘制)
3、创建OpenGL绘制环境RC,这个只能从hDC创建
4、将hDC和RC绑定到当前的线程
注:RC表示OpenGL的绘制环境,所有的OpenGL命令都会在RC这个绘制环境中作用,所以必须在RC绑定到当前线程之后才能调用OpenGL命令,否则运行出错,内存访问错误。
一般的笔刷绘制,在hDC下即可。
封装的窗口类如下:
GLWindow.h
#pragma once
#include <windows.h>
#include <GL/glew.h>
#include <iostream>
class GLContext
{
public:
GLContext();
~GLContext();
void Setup(HWND,HDC);
void SetupPixelFormat(HDC);
private:
HWND hWnd;
HDC hDC;
HGLRC hRC;
int format;
};
GLContext::GLContext()
{
this->hWnd = 0;
this->hDC = 0;
this->hRC = 0;
this->format = 0;
}
GLContext::~GLContext()
{
}
void GLContext::SetupPixelFormat(HDC hDC) {
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size
1, // version
PFD_SUPPORT_OPENGL | // OpenGL window
PFD_DRAW_TO_WINDOW | // render to window
PFD_DOUBLEBUFFER, // support double-buffering
PFD_TYPE_RGBA, // color type
32, // prefered color depth
0, 0, 0, 0, 0, 0, // color bits (ignored)
0, // no alpha buffer
0, // alpha bits (ignored)
0, // no accumulation buffer
0, 0, 0, 0, // accum bits (ignored)
16, // depth buffer
0, // no stencil buffer
0, // no auxiliary buffers
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0, // no layer, visible, damage masks
};
pixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pixelFormat, &pfd);
}
void GLContext::Setup(HWND hwnd, HDC hdc) {
this->hWnd = hwnd;
this->hDC = hdc;
SetupPixelFormat(hDC);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
//initialize glew
glewExperimental = GL_TRUE;
glewInit();
if (AllocConsole())
{
freopen("CONOUT$", "w+t", stdout);
freopen("CONOUT$", "w+t", stderr);
const GLubyte* Devise = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬件平台
const GLubyte* str = glGetString(GL_VERSION);
printf("OpenGL实现的版本号:%s\n", str);
printf("硬件平台:%s\n", Devise);
}
}
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
class GLWindow
{
public:
GLWindow();
~GLWindow();
void Setup(HINSTANCE, HINSTANCE, LPSTR, int);
//LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void RegisterDisplayFunc(void (*display)()) {
this->Display = display;
}
void Run();
private:
void(*Display)();
private:
bool exiting = false;
long windowWidth = 800;
long windowHeight = 600;
long windowBits = 64;
bool fullscreen = false;
WNDCLASSEX windowClass; // window class
HWND hwnd; // window handle
HDC hDC;
MSG msg; // message
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT windowRect;
GLContext glContext;
};
GLWindow::GLWindow() {}
GLWindow::~GLWindow() {}
void GLWindow::Setup(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
windowRect.left = (long)0; // Set Left Value To 0
windowRect.right = (long)windowWidth; // Set Right Value To Requested Width
windowRect.top = (long)0; // Set Top Value To 0
windowRect.bottom = (long)windowHeight; // Set Bottom Value To Requested Height
// fill out the window class structure
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); // default icon
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // default arrow
windowClass.hbrBackground = NULL; // don't need background
windowClass.lpszMenuName = NULL; // no menu
windowClass.lpszClassName = L"Windows API";
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // windows logo small icon
// register the windows class
if (!RegisterClassEx(&windowClass)) {
puts("Register Class Failed");
}
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle = WS_OVERLAPPEDWINDOW; // Windows Style
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
// class registered, so now create our window
hwnd = CreateWindowEx(NULL, // extended style
L"Windows API", // class name
L"OpenGL", // app name
dwStyle | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0, // x,y coordinate
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top, // width, height
NULL, // handle to parent
NULL, // handle to menu
hInstance, // application instance
NULL); // no extra params
ShowWindow(hwnd, SW_SHOW); // display the window
UpdateWindow(hwnd); // update the window
hDC = GetDC(hwnd);
glContext.Setup(hwnd,hDC);
}
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int height, width;
// dispatch messages
switch (uMsg)
{
case WM_CREATE: // window creation
break;
case WM_DESTROY: // window destroy
case WM_QUIT:
CloseWindow(hWnd);
break;
case WM_CLOSE: // windows is closing
// deselect rendering context and delete it
//wglMakeCurrent(hDC, NULL);
//wglDeleteContext(hRC);
// send WM_QUIT to message queue
PostQuitMessage(0);
break;
case WM_SIZE:
height = HIWORD(lParam); // retrieve width and height
width = LOWORD(lParam);
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: // left button release
break;
case WM_RBUTTONUP: // right button release
break;
case WM_KEYUP:
break;
case WM_KEYDOWN:
int fwKeys;
LPARAM keyData;
fwKeys = (int)wParam; // virtual-key code
keyData = lParam; // key data
switch (fwKeys)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
default:
break;
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void GLWindow::Run() {
while (true)
{
(*Display)();
SwapBuffers(hDC);
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage(&msg, NULL, 0, 0))
{
exiting = true;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
主函数调用代码示例:
#include <Windows.h>
#include <cameras/phc.h>
#include "shader.h"
#include "Cube.h"
#include "GLWindow.h"
redips::PhC phc;
GLWindow window;
Shader* shader;
Cube* cube;
void Display() {
cube->Draw(*shader, phc);
}
void Initialize(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
phc.lookAt(redips::float3(0, 0, 200), redips::float3(0, 0, 0), redips::float3(0, 1, 0));
window.Setup(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
window.RegisterDisplayFunc(Display);
shader = new Shader("./joint.vert", "./joint.frag");
cube = new Cube();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
Initialize(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
window.Run();
return 1;
}
运行:
来源:oschina
链接:https://my.oschina.net/u/4411233/blog/3524165