我想使用OpenGL库GLFW来渲染窗口,但也希望使用WinAPi来创建控件和处理事件。有没有办法做到这一点? 我尝试搜索(谷歌搜索)“使用glfw和winapi”,但没有产生任何结果。 我找到的唯一一个我想要的页面是this,但由于GLFW_WINPAR不存在,页面似乎已经过时了。有没有办法做我想要的,或者我必须使用“Vanilla”OpenGL。
答案 0 :(得分:5)
如果您打算使用本机Win32 API,那么使用GLFW并没有多大好处。 GLFW的重点是隐藏下面的系统API。
单独使用Win32创建一个OpenGL窗口并不那么难:
#include <windows.h>
#include <GL/gl.h>
namespace viewwnd
{
HWND hWnd;
HDC hDC;
HGLRC hRC;
};
namespace render
{
int win_width;
int win_height;
}
typedef HGLRC (*wglprocCreateContextAttribsARB)(HDC, HGLRC, const int *);
typedef BOOL (*wglprocChoosePixelFormatARB)(HDC, const int *, const FLOAT *, UINT,int *,UINT *);
#define VIEWCLASS "ViewWnd"
#define VIEWSTYLE WS_VISIBLE|WS_POPUP|WS_MAXIMIZE
BOOL OpenGLWindowCreate()
{
srand((unsigned)time(NULL));
using namespace viewwnd;
{
WNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
wc.lpfnWndProc = ViewProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = VIEWCLASS;
RegisterClass(&wc);
}
/* Create a temporaray context to get address of wgl extensions. */
HWND hTmpWnd= CreateWindowEx( WS_EX_APPWINDOW,
VIEWCLASS,
"Simple",
VIEWSTYLE,
0,0,0,0,
NULL,NULL,
hInstance,
NULL);
if(!hTmpWnd)
return FALSE;
HDC hTempDC = GetDC(hTempWnd);
if(!hTempDC) {
DestroyWindow(hTempWnd);
return FALSE;
}
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd,0,sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
pfd.cColorBits = 24;
pfd.cDepthBits = 24;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
int iPF;
if( (!(iPF = ChoosePixelFormat(hTempDC, &pfd)) || !SetPixelFormat(hTempDC, iPF, &pfd)) ||
(!(hTempRC = wglCreateContext(hTempDC)) || !wglMakeCurrent(hTempDC,hTempRC)) ) {
ReleaseDC(hTempDC);
DestroyWindow(hTempWnd);
return FALSE;
}
/* Like all extensions in Win32, the function pointers returned by wglGetProcAddress are tied
* to the render context they were obtained with. Since this is a temporary context, we
* place those function pointers in automatic storage of the window and context creation function. */
wglprocCreateContextAttribsARB wglCreateContextAttribsARB = (wglprocCreateContextAttribsARB) wglGetProcAddress("wglCreateContextAttribsARB");
wglprocChoosePixelFormatARB wglChoosePixelFormatARB = (wglprocChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB");
if( wglChoosePixelFormatARB && wglCreateContextAttribsARB ) {
/* good we have access to extended pixelformat and context attributes */
hWnd = CreateWindowEx( WS_EX_APPWINDOW,
VIEWCLASS,
"Simple",
VIEWSTYLE,
0,0,0,0,
NULL,NULL,
hInstance,
NULL);
if(!hWnd) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hTempRC);
ReleaseDC(hTempDC);
DestroyWindow(hTempWnd);
return FALSE;
}
hDC = GetDC(hWnd);
if(!hDC) {
DestroyWindow(hWnd);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hTempRC);
ReleaseDC(hTempDC);
DestroyWindow(hTempWnd);
return FALSE;
}
int attribs[] = {
WGL_DRAW_TO_WINDOW_ARB, TRUE,
WGL_DOUBLE_BUFFER_ARB, TRUE,
WGL_SUPPORT_OPENGL_ARB, TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 24,
WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0, 0
};
UINT num_formats_choosen;
BOOL choose_pf_success = wglChoosePixelFormatARB(
hDC,
attribs,
NULL,
1,
&iPF,
&num_formats_choosen);
/* now this is a kludge; we need to pass something in the PIXELFORMATDESCRIPTOR
* to SetPixelFormat; it will be ignored, mostly. OTOH we want to send something
* sane, we're nice people after all - it doesn't hurt if this fails. */
DescribePixelFormat(hDC, iPF, sizeof(pfd), &pfd);
if(!( choose_pf_success &&
num_formats_choosen >= 1 &&
SetPixelFormat(hDC, iPF, &pfd) )) {
ReleaseDC(hDC);
DestroyWindow(hWnd);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hTempRC);
ReleaseDC(hTempDC);
DestroyWindow(hTempWnd);
return FALSE;
}
/* we request a OpenGL-3 compatibility profile */
int context_attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB | WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0, 0
};
hRC = wglCreateContextAttribARB(hDC, NULL, context_attribs);
if(!hRC) {
ReleaseDC(hDC);
DestroyWindow(hWnd);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hTempRC);
ReleaseDC(hTempDC);
DestroyWindow(hTempWnd);
return FALSE;
}
wglMakeCurrent(hDC, hRC);
/* now that we've created the proper window, DC and RC
* we can delete the temporaries */
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hTempRC);
ReleaseDC(hTempDC);
DestroyWindow(hTempWnd);
} else {
/* extended pixelformats and context attributes not supported
* => use temporary window and context as the proper ones */
hWnd = hTempWnd;
hDC = hTempDC;
hRC = hTempRC;
}
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
return TRUE;
}
void OnOpenGLWindowDestroy()
{
using namespace viewwnd;
wglMakeCurrent(NULL,NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd,hDC);
UnregisterClass(VIEWCLASS, GetModuleHandle(NULL));
PostQuitMessage(0);
}
LRESULT CALLBACK ViewProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
using namespace viewwnd;
switch(uMsg)
{
case WM_DESTROY:
OnOpenGLWindowDestroy();
break;
case WM_PAINT:
display();
break;
case WM_SIZE:
reshape(LOWORD(lParam),HIWORD(lParam));
break;
default:
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
void reshape(int w,int h)
{
win_width = w;
win_height = h;
}
void display()
{
using namespace viewwnd;
using namespace render;
glViewport(0, 0, win_width, win_heighth);
glClearColor(0., 0., 0., 1.);
glClearDepth(1.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,ratio,0.1,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
SwapBuffers(hDC);
}