我写了一个< code>OpenGL代码用于在屏幕上渲染图像。我使用< code>GLUT来创建一个窗口和回调,但是我想在< code>win32窗口中而不是在< code>GLUT中呈现图像,基本上我们有一个< code > CreateWindowEx() API来在< code>win32中创建窗口,并且我们有一个< code>HWND(句柄),以便我们可以将此句柄传递给< code>HDC,但是我在< code>GLUT中没有找到任何类似的内容,是吗还是其他途径?。
下面是我的代码,它成功地在屏幕上渲染图像。
int main()
{
__try{
int argc = 1;
char *argv[1] = { (char*)"GLUTwindow" };
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(0, 0);
glutCreateWindow("GLUTwindow");
GLenum err = glewInit(); if (GLEW_OK != err) __debugbreak();
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMotionFunc(motion);
glutMainLoop();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
return 0;
}
void init()
{
// compile and link the shaders into a program, make it active
vShader = compileShader(vertexShader, GL_VERTEX_SHADER);
fShader = compileShader(fragmentShader, GL_FRAGMENT_SHADER);
std::list<GLuint> tempList;
tempList.clear();
tempList.insert(tempList.end(), (GLuint)vShader);
tempList.insert(tempList.end(), (GLuint)fShader);
program = createProgram(tempList);
offset = glGetUniformLocation(program, "offset"); GLCHK;
texUnit = glGetUniformLocation(program, "texUnit"); GLCHK;
glUseProgram(program); GLCHK;
// configure texture unit
glActiveTexture(GL_TEXTURE0); GLCHK;
glUniform1i(texUnit, 0); GLCHK;
// create and configure the textures
glGenTextures(1, &texture); GLCHK;
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, texture); GLCHK;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); GLCHK;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); GLCHK;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLCHK;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GLCHK;
}
void display()
{
GLuint w, h; std::vector<GLubyte> img; if (lodepng::decode(img, w, h, "test2.png")) __debugbreak();
glBindTexture(GL_TEXTURE_2D, texture); GLCHK;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,w,h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &img[0]); GLCHK;
glClear(GL_COLOR_BUFFER_BIT); GLCHK;
glBindTexture(GL_TEXTURE_2D, texture); GLCHK;
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); GLCHK;
glutSwapBuffers();
glutPostRedisplay();
}
如果要创建一个没有任何窗口库的 win32 OpenGL 窗口,则必须执行以下操作:
#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;
}
对于窗口,需要一个处理窗口消息的过程:
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
读取纹理。
我有一个常规的Win32窗口,我想使用OpenGL渲染该窗口的一部分,我发现了这个问题: 在常规窗口中使用打开GL (Win32) 但我真的不知道他们是如何在一个窗口内创建一个面板,并获得了它的DC。。 基本上,我想要一个使用win32绘制按钮、列表等的窗口,并在同一窗口的某个指定部分渲染opengl内容。 我试着使用glScissor和清除缓冲区,但这只是用黑色填充整个屏幕,而我指定的部分是透明
我正在通过glfw3库学习OpenGL,我正在使用imgui制作一个有趣的应用程序。 我想做一个小引擎或CAD工具。 问题是我不能在imgui窗口中呈现我想要的。 我搜索了谷歌,找到了以下链接: https://gamedev.stackexchange.com/questions/150214/render-in-a-imgui-window https://gamedev.stackexcha
我正在寻找一些关于渲染子窗口的信息,特别是关于OpenGL如何与GDI互操作的信息。我的问题是,我基本上有两个窗口,首先,主窗口是在qt中创建的,而在qt内部,子窗口是利用OpenGL渲染器托管的。 现在我想做的是在我的OpenGL窗口顶部托管一个覆盖,所以我用它来覆盖OpenGL窗口。我遇到的问题是,当我使用OpenGL渲染时,OpenGL生成的图形似乎模糊了图形区域,包括并有效地撤消了由qt合
我正在尝试学习windows上的opengl编程,虽然我最初是从SDL开始的,但我已经决定放弃它,以便学习如何使用WGL自己启动OpenGL上下文。 我使用nanovg作为一个快速的图形绘制库,用SDL渲染一切都很好,但是,现在我已经移除了SDL,创建了我自己的窗口和OpenGL上下文,我发现窗口的标题栏与渲染区域重叠了。好像渲染区域的原点(0,0)在整个窗口的左上方,而不是标题栏的正下方,如果这
我已经阅读了关于这个棘手(利基)主题的所有现有问题,但我被卡住了。我有一个带有OpenGL上下文的Win32窗口。我希望我的窗口是部分透明的。 到目前为止,我的结果是整个窗口都是透明的。我只希望黑色区域是透明的,这样我可以绘制一些3D对象,它们看起来就像是从窗口出来的。 首先,在我的窗口类中,我将hbrbackground设置为黑色。 我已经使用WS_EX_LAYERED标志创建了我的窗口。 在我
我用C语言制作了一个简单的OpenGL程序,在盒子内绘制一个旋转的三角形。三角形应该是等边的,但即使窗口宽度和高度相同,当它们沿着窗口的宽度和长度移动时,三角形的顶点也会收缩和拉伸。我能分辨出来,因为我做了一个静态的等角盒,三角形的顶点在它外面。以下是它正在做的事情的简短片段:https://edwardseverinsen1717-gmail.tinytake.com/sf/NDg5NjQ0Xz