winapi - Win32 opengl 窗口创建

标签 winapi opengl window

在 win32 中设置一个集成了 OpenGl(如果需要额外的代码才能使用 glsl)的窗口的最佳方法是什么?

我做了一些研究,发现了许多完成这项任务的方法,我想知道最好的方法是什么,或者如果最好的方法没有答案,你最喜欢哪种方法。

我看过nehe的设计以及OpenGl super 圣经提供的设计,它们都有完全不同的实现方式( super 圣经也给了我错误:()。

任何帮助将不胜感激,包括教程等。

谢谢

最佳答案

你所有的“不同方式”并没有那么不同。你必须:

  • 创建您的窗口(以通常的 Win32 方式,使用 RegisterClass(Ex)CreateWindow(Ex) )
  • 创建对应于您的窗口的 GDI 设备上下文 ( GetDC )
  • 选择显示器支持的像素格式(可选 DescribePixelFormat ,然后是 ChoosePixelFormat )
  • 创建您的 OpenGL 上下文 ( wglCreateContext )
  • (可选,但需要使用 GLSL)链接 OpenGL 扩展函数(GLee 或 GLEW 助手,或 glGetString(GL_EXTENSIONS) 然后 wglGetProcAddress)
  • (可选)创建 OpenGL 3.x 上下文,释放兼容性上下文 ( wglCreateContextAttribs )
  • 使上下文处于事件状态 ( wglMakeCurrent )
  • 开始使用 OpenGL(设置着色器程序、加载纹理、绘制内容等)


  • 显示这些步骤的代码摘录(不适合复制+粘贴,使用了一堆 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/

    相关文章:

    c++ - 从 QGLPixelBuffer 获取深度缓冲区

    winapi - 调用返回 ERROR_MORE_DATA 或 ERROR_INSUFFICIENT_BUFFER 的 Win32 API 函数的模式?

    c++ - CreateProcessAsUser和createevent权限

    c# - DeviceIoControl 初始化并创建 NTFS 分区

    qt - 使用原始 OpenGL 调用绘制 Qml 项的问题

    jquery - 使用 jQuery 根据窗口宽度删除和添加元素不起作用

    c++ - 确定进程的输入线程 ID

    java - 为什么这个 SpriteBatch 在 C# 中工作而不在 Java 中工作?

    java - 防止调整窗口大小

    Javascript: window.onload问题