glGetString(GL_VERSION) 在 OpenGL 初始化时返回 NULL

Posted

技术标签:

【中文标题】glGetString(GL_VERSION) 在 OpenGL 初始化时返回 NULL【英文标题】:glGetString(GL_VERSION) returns NULL while OpenGL was initialized 【发布时间】:2016-05-24 18:21:40 【问题描述】:

我正在尝试制作 *.obj 加载器。当我认为一切都已解决时,我无法启动 GLEW 来使用我的装载机。

问题是我的应用程序初始化如下所示:

int WINAPI WinMain( HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int nCmdShow)

    WNDCLASSEX wc;
    MSG msg;
    HWND hWnd;

    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WndProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = L"Projekt";

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(  NULL,
                            L"Projekt",
                            L"Symulator lodzi",
                            WS_OVERLAPPEDWINDOW,
                            100, 50,
                            SCREEN_WIDTH, SCREEN_HEIGHT,
                            NULL, NULL, hInstance, NULL);

    if (!hWnd)
        return 0;

    ShowWindow(hWnd, nCmdShow); //wyswietlanie okna

    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (err != GLEW_OK)
    
        const GLubyte* error = glGetString(GL_VERSION);
        const GLubyte* error2 = glewGetErrorString(err);
        exit(1);
    

    while (TRUE)
    
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        

        if (msg.message == WM_QUIT)
            break;
    

    return msg.wParam;

在 CreateWindowEx 被调用后,它全部转到 WndProc 函数中的 WM_CREATE 消息,如下所示:

case WM_CREATE:
        
            SetTimer(hWnd, 1, 1000, (TIMERPROC)NULL);
            if (oGL == NULL)
                oGL = new OpenGL(hWnd);

            hDC = GetDC(hWnd);
         break;

oGL 构造函数代码在这里:

OpenGL::OpenGL(HWND hWnd)

    static PIXELFORMATDESCRIPTOR pfd = 
                                        sizeof(PIXELFORMATDESCRIPTOR),
                                        1,
                                        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
                                        PFD_TYPE_RGBA,              
                                        32,                           
                                        0, 0, 0,
                                        0, 0, 0,                      
                                        0, 0,                         
                                        0, 0, 0, 0, 0,                
                                        32,                           
                                        0,                             
                                        0,                             
                                        PFD_MAIN_PLANE,                 
                                        0,                             
                                        0,                             
                                        0,                              
                                        0                               
                                        ;

    int pixelFormatID;
    HDC hDC;

    hDC = GetDC(hWnd);

    pixelFormatID = ChoosePixelFormat(hDC, &pfd);
    SetPixelFormat(hDC, pixelFormatID, &pfd);

    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);
    ReleaseDC(hWnd, hDC);

所以我认为 OpenGL 已正确初始化,但随后我收到了这些错误:

我不明白为什么应用程序认为 OpenGL 尚未初始化(我一直在逐步调试它,并且肯定首先创建了窗口,然后创建了 oGL 对象)。

【问题讨论】:

是什么让您认为您的消息处理程序在您的代码到达消息泵之前已被调用? 我一直在调试模式下跟踪代码,在到达 CreateWindowsEx 后,调用的下一行在 WM_CREATE 消息中。即使我在 WM_CREATE 中放置断点并在第一个错误行中设置断点时,该代码也停止了。是 WM_CREATE 【参考方案1】:

在尝试初始化 GLEW 时,您没有 OpenGL 上下文。 WM_CREATE 消息只有在进入消息循环后才会通过 DispatchMessage 进行处理。在处理 WM_CREATE 之前,您的程序没有上下文。

只在创建窗口后创建 OpenGL 上下文,而不是在 WM_CREATE 中。更容易并避免了订购问题。

【讨论】:

好的,我会检查的。我 100% 确定 WM_CREATE 是在 CreateWindowsEx 之后调用的,因为 VS studio 就是这样显示的。 当我从 WM_CREATE 删除创建上下文时,我收到一些变量未初始化的错误(它们来自 CreateWindowsEx 调用后的 WndProc 函数)。所以我必须在 WM_CREATE 中创建我的 OpenGL 上下文,当我试图在 glewInit() 之前再次创建它时,它已经创建了。 @KamilPrzybyo:未初始化的变量不是错误,只要您不尝试读取它们。无论哪种方式,在 WM_CREATE 中创建 OpenGL 上下文的普通 Win32 API 程序都有点不寻常。不过,这对于基于 MFC 的程序来说很常见。无论哪种方式,您都应该在创建上下文的同时进行 GLEW 初始化。或者更确切地说,您实际上必须在每次 wglMakeCurrent 调用之后创建 glewInit;这是因为在 Windows 扩展入口点实际上可能因上下文而异。您似乎尝试将 GL 包装在类中(很难!);然后你可以包装函数指针。 那个答案对我很有帮助!我刚刚将初始化 glew 移动到我的 OpenGL 类构造函数,就在 wglMakeCurrent 之后,现在一切正常。我一直在尝试在创建 OpenGL 类对象后立即调用 glewInit,但它没有用。它必须在 wglMakeCurrent 之后。感谢您的帮助

以上是关于glGetString(GL_VERSION) 在 OpenGL 初始化时返回 NULL的主要内容,如果未能解决你的问题,请参考以下文章

glGetString(GL_VERSION) returns “OpenGL ES-CM 1.1” but my phone supports OpenGL 2

NVIDIA Optimus 卡在 OpenGL 下不切换

C ++ OpenGL fstream问题[关闭]

如何获取当前应用程序所用的OpenGL ES的版本

GLEW _First 是 nullptr

查询自己OpenGL的版本信息