我在屏幕上为渲染图像编写了OpenGL
代码。我使用GLUT
创建了一个窗口和回调,但我希望在win32
窗口中呈现的图像不在GLUT
中,基本上我们有一个CreateWindowEx()
API来创建{ {1}}我们有一个win32
(句柄),以便我们可以将此句柄传递给HWND
,但我在HDC
中找不到这样的内容,是否有可能发送句柄到GLUT
?或其他方法?
下面是我的代码,它在屏幕上成功渲染图像。
GLUT
答案 0 :(得分:2)
如果你想创建一个没有任何窗口库的win32 OpenGL窗口,你必须执行以下操作:
RegisterClassEx
CreateWindow
wglCreateContext
wglMakeCurrent
ShowWindow
#include <GL/gl.h>
#include <windows.h>
const std::wstring wnd_class( L"my_wnd_class" );
HWND hOGLWnd = NULL;
HGLRC hOGLRenderContext = NULL;
HWND createWindow( int width, int height )
{
// Get module handle
HMODULE hModule = ::GetModuleHandle( 0 );
if (!hModule)
return NULL;
// Create window calss
WNDCLASSEX wndClassData;
memset( &wndClassData, 0, sizeof( WNDCLASSEX ) );
wndClassData.cbSize = sizeof( WNDCLASSEX );
wndClassData.style = CS_DBLCLKS;
wndClassData.lpfnWndProc = WindowProcedure;
wndClassData.cbClsExtra = 0;
wndClassData.cbWndExtra = 0;
wndClassData.hInstance = hModule;
wndClassData.hIcon = ::LoadIcon(0,IDI_APPLICATION);
wndClassData.hCursor = ::LoadCursor(0,IDC_ARROW);
wndClassData.hbrBackground = ::CreateSolidBrush(COLOR_WINDOW+1);
wndClassData.lpszMenuName = 0;
wndClassData.lpszClassName = wnd_class.c_str();
wndClassData.hIconSm = 0;
if ( !::RegisterClassEx( &wndClassData ) )
return false;
// Creaate Window
hOGLWnd = ::CreateWindow( wnd_class.c_str(), NULL, WS_OVERLAPPEDWINDOW, 0, 0, width, height, NULL, NULL, hModule, NULL);
if ( hOGLWnd == NULL )
return NULL;
// Get device context
HDC hDC = ::GetDC( hOGLWnd );
// Create OpenGL context
DWORD pixelFormatFlags = PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION | PFD_GENERIC_ACCELERATED | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
pixelFormatFlags, //Flags
PFD_TYPE_RGBA, //The kind of framebuffer. RGBA or palette.
32, //Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24, //Number of bits for the depthbuffer
8, //Number of bits for the stencilbuffer
0, //Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0, 0, 0, 0
};
int pixelFormat = ::ChoosePixelFormat( hDC, &pfd );
::SetPixelFormat( hDC, pixelFormat, &pfd );
hOGLRenderContext = ::wglCreateContext( hDC );
// make OpenGL context the current context
::wglMakeCurrent( hDC, hOGLRenderContext );
// release device context
::ReleaseDC( hOGLWnd, hDC );
// show the window
::ShowWindow( hOGLWnd, SW_SHOWDEFAULT );
return hOGLWnd;
}
对于窗口,过程是neede,它处理窗口消息:
LRESULT CALLBACK WindowProcedure( HWND hWnd, unsigned int msg, WPARAM wparam, LPARAM lparam )
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_ERASEBKGND:
display();
break;
}
return DefWindowProc( hWnd, msg, wparam, lparam );
}
主循环必须调度窗口消息(消息循环):
void mainloop( void )
{
MSG msg;
while( ::GetMessage( &msg, 0, 0, 0 ) )
::DispatchMessage( &msg );
}
窗口可以像这样被破坏:
void destroyWindow(void)
{
if ( HDC currentDC = ::wglGetCurrentDC() )
::wglMakeCurrent( currentDC , NULL );
::DestroyWindow( hOGLWnd );
::wglDeleteContext( hOGLRenderContext );
HMODULE hModule = ::GetModuleHandle( 0 );
if (!hModule)
return;
::UnregisterClass( wnd_class.c_str(), hModule );
}
为了完整性的一个简单的演示程序:
#include <GL/glew.h>
#include <vector>
#include <stdexcept>
int main()
{
int w = 800;
int h = 600;
HWND hWnd = createWindow( w, h );
if ( hWnd == 0 )
throw std::runtime_error( "error initializing window" );
if ( glewInit() != GLEW_OK )
throw std::runtime_error( "error initializing glew" );
static const std::vector<float> varray
{
-0.707f, -0.75f, 1.0f, 0.0f, 0.0f, 1.0f,
0.707f, -0.75f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.75f, 0.0f, 0.0f, 1.0f, 1.0f
};
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, varray.size()*sizeof(*varray.data()), varray.data(), GL_STATIC_DRAW );
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glVertexPointer( 2, GL_FLOAT, 6*sizeof(*varray.data()), 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glColorPointer( 4, GL_FLOAT, 6*sizeof(*varray.data()), (void*)(2*sizeof(*varray.data())) );
glEnableClientState( GL_COLOR_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
mainloop();
destroyWindow();
return 0;
}
void display( void )
{
RECT clientRect;
::GetClientRect( hOGLWnd, &clientRect );
glViewport( 0, 0, clientRect.right-clientRect.left, clientRect.bottom-clientRect.top );
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glDrawArrays( GL_TRIANGLES, 0, 3 );
// swap buffers
HDC hDC = ::GetDC( hOGLWnd );
::SwapBuffers( hDC );
::ReleaseDC( hOGLWnd, hDC );
// create message WM_ERASEBKGND
::InvalidateRect( hOGLWnd, NULL, TRUE);
}
请注意,如果您不显示窗口(跳过ShowWindow
),则您有一个隐藏窗口,您可以在其中进行图像渲染。您可以通过glReadPixels
从GPU读取渲染图像,或者您可以创建带有附加纹理的帧缓冲区,并按glGetTexImage
读取纹理。