在 win32 中设置一个集成了 OpenGl(如果需要额外的代码才能使用 glsl)的窗口的最佳方法是什么?
我做了一些研究,发现了许多完成这项任务的方法,我想知道最好的方法是什么,或者如果最好的方法没有答案,你最喜欢哪种方法。
我看过nehe的设计以及OpenGl super 圣经提供的设计,它们都有完全不同的实现方式( super 圣经也给了我错误:()。
任何帮助将不胜感激,包括教程等。
谢谢
最佳答案
你所有的“不同方式”并没有那么不同。你必须:
RegisterClass(Ex)
和 CreateWindow(Ex)
)GetDC
) DescribePixelFormat
,然后是 ChoosePixelFormat
)wglCreateContext
) glGetString(GL_EXTENSIONS)
然后 wglGetProcAddress
)wglCreateContextAttribs
) wglMakeCurrent
) 显示这些步骤的代码摘录(不适合复制+粘贴,使用了一堆 RAII 包装器):
bool Context::attach( HWND hwnd )
{
PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1 };
if (!m_dc) {
scoped_window_hdc(hwnd).swap(m_dc);
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cAlphaBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
auto format_index = ::ChoosePixelFormat(m_dc.get(), &pfd);
if (!format_index)
return false;
if (!::SetPixelFormat(m_dc.get(), format_index, &pfd))
return false;
}
auto active_format_index = ::GetPixelFormat(m_dc.get());
if (!active_format_index)
return false;
if (!::DescribePixelFormat(m_dc.get(), active_format_index, sizeof pfd, &pfd))
return false;
if ((pfd.dwFlags & PFD_SUPPORT_OPENGL) != PFD_SUPPORT_OPENGL)
return false;
m_render_thread = ::CreateThread(NULL, 0, &RenderThreadProc, this, 0, NULL);
return m_render_thread != NULL;
}
DWORD WINAPI Context::RenderThreadProc( LPVOID param )
{
Context* const ctx = static_cast<Context*>(param);
HDC dc = ctx->m_dc.get();
SIZE canvas_size;
ctx->m_dc.check_resize(&canvas_size);
scoped_hglrc glrc(wglCreateContext(dc));
if (!glrc)
return EXIT_FAILURE;
if (!glrc.make_current(dc))
return EXIT_FAILURE;
if (ctx->m_major_version > 2 && GLEE_WGL_ARB_create_context) {
int const create_attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, ctx->m_major_version,
WGL_CONTEXT_MINOR_VERSION_ARB, ctx->m_minor_version,
0
};
scoped_hglrc advrc(wglCreateContextAttribsARB(dc, 0, create_attribs));
if (advrc) {
if (!advrc.make_current(dc))
return EXIT_FAILURE;
advrc.swap(glrc);
}
}
{
const char* ver = reinterpret_cast<const char*>(glGetString(GL_VERSION));
if (ver) {
OutputDebugStringA("GL_VERSION = \"");
OutputDebugStringA(ver);
OutputDebugStringA("\"\n");
}
}
glDisable(GL_DITHER);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.f, 0.f, 0.f, 1.f);
if (GLEE_WGL_EXT_swap_control)
wglSwapIntervalEXT(1);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
while (!::InterlockedExchange(&ctx->m_stop_render, 0)) {
ctx->process_queued_tasks();
if (ctx->m_dc.check_resize(&canvas_size)) {
glViewport(0, 0, canvas_size.cx, canvas_size.cy);
ctx->process_on_resize();
}
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
ctx->process_on_render();
BOOL swapped = ::SwapBuffers(dc);
if (!swapped)
std::cout << "::SwapBuffers failure, GetLastError() returns " << std::hex << ::GetLastError() << std::endl;
}
ctx->m_program_db.clear();
return EXIT_SUCCESS;
}
它也不包括窗口创建,它在现有窗口上启用 OpenGL。
关于winapi - Win32 opengl 窗口创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6287660/