使用WGL创建现代OpenGL上下文?

3
我正在尝试使用Windows函数创建一个OpenGL上下文(现代版本)。
基本上代码如下:
1. 创建窗口类 2. 注册类 3. 创建窗口 4. 选择PIXELFORMATDESCRIPTOR并设置它 5. 创建传统的OpenGL上下文 6. 将上下文设为当前 7. glewInit() 8. 创建新窗口 9. 创建现代像素格式属性数组 10. 设置格式 11. 创建现代OpenGL上下文 12. 将上下文设为当前
之后,我尝试绘制一个正方形(使用VAO和VBO)。
结果是:Windows窗口工作正常,glClear(GL_COLOR_BUFFER_BIT)也能正常工作,但是无法绘制正方形(display()函数)。
如果我使用OpenGL 2.0上下文,它可以绘制正方形(与以前一样使用VAO和VBO),因此问题必须在初始化OpenGL 3.2时出现了错误。
我错在哪里了?
以下是代码:
#include <iostream>
#include <GL/glew.h>
#include <GL/wglew.h>
#include <windows.h>
#include <string>
using namespace std;

bool progRun = false;

void display(){
   glUseProgram(shaderProg);
   glBindVertexArray(vao[0]);
   glDrawArrays(GL_QUADS, 0,4);
}

string errorStr = "none";

PIXELFORMATDESCRIPTOR pfd;

HGLRC hrc; // vars to init glew
HDC hdc;
HWND hwnd;

HGLRC hrc1; //vars for the real window
HDC hdc1;
HWND hwnd1;

LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); // window event hadler prototype

//-------------------- INIT OPENGL
int initOpengl(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow
)
{
    //---- fake Window
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof( WNDCLASSEX );
    wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
    wcex.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = "coco";
    wcex.hIconSm = NULL;

    if( !RegisterClassEx( &wcex ) )
    {
        errorStr = "RegisterClassEx";
        return 0;
    }
    hwnd = CreateWindow(
        "coco",
        "dddd",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        500, 500,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    hdc = GetDC( hwnd );

    memset( &pfd, 0, sizeof( PIXELFORMATDESCRIPTOR ) );
    pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
    pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int nPixelFormat = ChoosePixelFormat( hdc, &pfd );

    SetPixelFormat( hdc, nPixelFormat, &pfd );

    hrc = wglCreateContext( hdc );

    wglMakeCurrent( hdc, hrc );

    glewExperimental = true;
    glewInit();

    //---------------For the real window
    if( wglewIsSupported( "WGL_ARB_create_context" ) == 1 )
    {
        wglMakeCurrent( NULL, NULL );
        wglDeleteContext( hrc );
        ReleaseDC( hwnd, hdc );
        DestroyWindow( hwnd );

        hwnd1 = CreateWindow(
            "coco",
            "ddddd",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT,
            500, 500,
            NULL,
            NULL,
            hInstance,
            NULL
        );

        hdc1 = GetDC( hwnd1 );

        const int iPixelFormatAttribList[] = {
            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
            WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
            WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
            WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
            WGL_COLOR_BITS_ARB, 32,
            WGL_DEPTH_BITS_ARB, 24,
            WGL_STENCIL_BITS_ARB, 8,
            0 // End of attributes list
        };
        int attributes[] = {
            WGL_CONTEXT_MAJOR_VERSION_ARB, 3
            , WGL_CONTEXT_MINOR_VERSION_ARB, 2
            , WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
            , 0
        };

        int nPixelFormat = 0;
        UINT iNumFormats = 0;

        wglChoosePixelFormatARB( hdc1, iPixelFormatAttribList, NULL, 1, &nPixelFormat, (UINT*)&iNumFormats );

        SetPixelFormat( hdc1, nPixelFormat, &pfd );

        hrc1 = wglCreateContextAttribsARB( hdc1, 0, attributes );

        wglMakeCurrent( NULL, NULL );
        wglMakeCurrent( hdc1, hrc1 );
    }
    else
    {
        errorStr = "WGL_ARB_create_context";
        return 0;
    }
    return true;
}


// MAIN -----

int CALLBACK WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow
)
{
    initOpengl( hInstance, hPrevInstance, lpCmdLine, nCmdShow );

    ShowWindow( hwnd1, SW_SHOW );

    glClearColor( 1, 0, 0, 1 );

    MSG msg;
    progRun = true;

    while( progRun )
    {
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }

        glClear( GL_COLOR_BUFFER_BIT );
        glViewport( 0, 0, 500, 500 );
        display();

        SwapBuffers( hdc1 );
    }

    return 0;
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    return DefWindowProc( hWnd, message, wParam, lParam );
}

4
如果您想要OpenGL 3.2,请不要要求3.1。此外,建议设置核心配置文件标志以用作上下文属性(不使用旧的固定管线指令)。在核心配置文件中,GL_QUADS无效。另外,在WM_PAINT处理程序中进行渲染(显示+交换缓冲区)。如果不使用glViewPort,则当窗口更改大小时,您的渲染不会适应窗口大小。还应为背景设置一个glClearColor,最好不是黑色,以便判断GL是否正常工作。 - Ripi2
2
我建议将操作系统功能与GL相关的内容分开。编写专门的函数用于窗口创建、大小更改、绘制、上下文创建、着色器、数据、相机、渲染、用户操作等。 - Ripi2
1个回答

2
问题不仅出现在上下文创建代码中,还在于所使用的OpenGL版本和绘图代码的组合。
当像问题中那样请求OpenGL上下文时,有几个属性可以设置。这里相关的属性是未设置的WGL_CONTEXT_PROFILE_MASK_ARB。相关的扩展说明中指出:
默认值为 WGL_CONTEXT_CORE_PROFILE_BIT_ARB。如果请求的OpenGL版本低于3.2,则忽略WGL_CONTEXT_PROFILE_MASK_ARB,并且上下文的功能仅由请求的版本确定。
这意味着问题中的代码请求了一个OpenGL 3.2核心配置文件,在不起作用的版本中请求了一个3.1(兼容性)配置文件。
在核心配置文件中,使用GL_QUADS作为glDrawArrays模式已被弃用,不能使用。因此,矩形没有渲染。请注意,如果您在代码中检查OpenGL错误(glGetError),您将更快地发现问题,因为它会报告绘制命令的无效枚举(GL_INVALID_ENUM)。
解决问题的方法有两种:
停止绘制矩形,改为绘制三角形(GL_TRIANGLES)。这是推荐的方法。
通过添加值为WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARBWGL_CONTEXT_PROFILE_MASK_ARB来明确请求OpenGL 3.2兼容性配置文件。但是请注意,这可能会在将来引起问题,因为将旧的OpenGL代码与现代OpenGL混合可能会导致问题。

嗯,它起作用了,那就是问题所在...终于解决了,非常感谢! - Popo Heche

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接