Сбой создания контекста OpenGL с ARB - PullRequest
1 голос
/ 03 апреля 2020

Я пытаюсь создать контекст OpenGL с расширением ARB. Я прочитал множество документов, постов и вики-хроники об этом . Но я не могу сделать последний контекст текущим, как вы видите в коде, второй вызов wglMakeCurrent () закомментирован, что означает, что контекст, который фактически используется, является первым созданным без расширения. Если я раскомментирую это, окно не будет отображаться.

Я провел некоторое тестирование на ошибки с функциями ARB, похоже, проблема в списке атрибутов или в вызове wglChoosePixelFormatARB ().

Код:

#include <stdio.h>

#define UNICODE
#include <windows.h>
#include <dwmapi.h>

#define GLEW_STATIC
#include <glew.h>

#include <GL\wglext.h>

LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp);
unsigned int CreateShaderProgram(char* VertexSource, char* FragmentSource);

int main(void){
    WNDCLASSEX wcx = {};
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.style = CS_OWNDC;
    wcx.lpfnWndProc = WindowProcedure;
    wcx.lpszClassName = L"Win32Class";
    RegisterClassEx(&wcx);

    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYERED, wcx.lpszClassName, L"Title",
        WS_POPUP, 400, 300, 800, 400, NULL, NULL, NULL, NULL);

    DWM_BLURBEHIND blur = {};
    blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
    blur.fEnable = 1;
    blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
    DwmEnableBlurBehindWindow(hWnd, &blur);

    SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 255, LWA_COLORKEY);

    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;
    pfd.iLayerType = PFD_MAIN_PLANE;

    HDC DeviceContext = GetDC(hWnd);
    int PixelFormat = ChoosePixelFormat(DeviceContext, &pfd);
    SetPixelFormat(DeviceContext, PixelFormat, &pfd);
    HGLRC RenderingContext = wglCreateContext(DeviceContext);
    wglMakeCurrent(DeviceContext, RenderingContext);

    glewInit();

    int Attributes[] = {
        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,
        WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
        WGL_CONTEXT_MINOR_VERSION_ARB, 4,
        WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        0,
    };

    PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
        wglGetProcAddress("wglChoosePixelFormatARB");
    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
        (PFNWGLCREATECONTEXTATTRIBSARBPROC)
        wglGetProcAddress("wglCreateContextAttribsARB");

    wglChoosePixelFormatARB(DeviceContext, Attributes, NULL, 1, &PixelFormat,
        NULL);
    SetPixelFormat(DeviceContext, PixelFormat, &pfd);
    RenderingContext = wglCreateContextAttribsARB(DeviceContext, NULL,
        Attributes);
    //wglMakeCurrent(DeviceContext, RenderingContext);

    char VertexShaderSource[] =
    "#version 440 core\n"
    "\n"
    "layout(location = 0) in vec4 position;\n"
    "\n"
    "void main(){\n"
    "   gl_Position = position;\n"
    "}";

    char FragmentShaderSource[] =
    "#version 440 core\n"
    "\n"
    "layout(location = 0) out vec4 colour;\n"
    "\n"
    "void main(){\n"
    "   colour = vec4(0.5, 0.5, 0.5, 1.0);\n"
    "}";

    float Verticies[] = {
         0.0f,  0.5f, // top    : 0
         0.5f,  0.0f, // right  : 1
         0.0f, -0.5f, // bottom : 2
        -0.5f,  0.0f  // left   : 3
    };

    unsigned int Indices[] = {
        3, 0, 1, // top
        3, 2, 1  // bottom
    };

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    unsigned int VertexArray;
    glGenVertexArrays(1, &VertexArray);
    glBindVertexArray(VertexArray);

    unsigned int VertexBuffer;
    glGenBuffers(1, &VertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), Verticies, GL_STATIC_DRAW);

    unsigned int IndexBuffer;
    glGenBuffers(1, &IndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), Indices,
        GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    unsigned int ShaderProgram = CreateShaderProgram(VertexShaderSource,
        FragmentShaderSource);
    glUseProgram(ShaderProgram);

    glViewport(0, 0, 800, 400);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    ShowWindow(hWnd, 1);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)){
        DispatchMessage(&msg);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
        wglSwapLayerBuffers(DeviceContext, WGL_SWAP_MAIN_PLANE);
    }
}

LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
    switch(uMsg){
        case WM_NCHITTEST: return HTCAPTION;
        case WM_DESTROY: PostQuitMessage(0); return 0;
        default: return DefWindowProc(hWnd, uMsg, wp, lp);
    }
}

unsigned int CreateShader(char* Source, unsigned int Type);

unsigned int CreateShaderProgram(char* VertexSource,
char* FragmentSource){
    unsigned int ShaderProgram = glCreateProgram(),
        VertexShader = CreateShader(VertexSource, GL_VERTEX_SHADER),
        FragmentShader = CreateShader(FragmentSource, GL_FRAGMENT_SHADER);
    glAttachShader(ShaderProgram, VertexShader);
    glAttachShader(ShaderProgram, FragmentShader);
    glLinkProgram(ShaderProgram);
    glValidateProgram(ShaderProgram);
    return ShaderProgram;
}

unsigned int CreateShader(char* Source, unsigned int Type){
    unsigned int Shader = glCreateShader(Type);
    glShaderSource(Shader, 1, (const char* const*)&Source, NULL);
    glCompileShader(Shader);
    return Shader;
}

Примечание. Приведение результата второго вызова wglGetProcAdress () выдает предупреждение, если установлен флаг -Wextra (для компилятора g cc). Я не знаю, как это исправить.

Обновление: это все еще не работает: «Не удалось выбрать последний формат окна в пикселях». и «Не удалось создать окончательный контекст рендеринга». напечатаны (см. код) ниже. И окно не отображается.

Новый код: (большой комментарий - старый код):

#include <stdio.h>

#define UNICODE
#include <windows.h>
#include <dwmapi.h>

#define GLEW_STATIC
#include <glew.h>

#include <GL\wglext.h>

LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
    LPARAM lp);
LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
    LPARAM lp);
unsigned int CreateShaderProgram(char* VertexSource, char* FragmentSource);

int main(void){
    WNDCLASSEX FirstWindowClass = {};
    FirstWindowClass.cbSize = sizeof(WNDCLASSEX);
    FirstWindowClass.style = CS_OWNDC;
    FirstWindowClass.lpfnWndProc = FirstWindowProcedure;
    FirstWindowClass.lpszClassName = L"FirstWindowClass";
    if(!RegisterClassEx(&FirstWindowClass))
        puts("Registration of the first window class failed.\n");

    HWND FirstWindow = CreateWindowEx(WS_EX_APPWINDOW,
        FirstWindowClass.lpszClassName, L"FirstWindow", WS_POPUP, 0, 0, 10, 10,
        NULL, NULL, NULL, NULL);
    if(FirstWindow == NULL)
        puts("Creation of the first window failed.\n");

    PIXELFORMATDESCRIPTOR FirstWindowPixelFormatDescriptor = {};
    FirstWindowPixelFormatDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    FirstWindowPixelFormatDescriptor.nVersion = 1;
    FirstWindowPixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    FirstWindowPixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
    FirstWindowPixelFormatDescriptor.cColorBits = 32;
    FirstWindowPixelFormatDescriptor.cDepthBits = 24;
    FirstWindowPixelFormatDescriptor.cStencilBits = 8;
    FirstWindowPixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;

    HDC FirstWindowDeviceContext = GetDC(FirstWindow);
    if(FirstWindowDeviceContext == NULL)
        puts("First window device context retrieving failed.\n");

    int FirstWindowPixelFormat = ChoosePixelFormat(FirstWindowDeviceContext,
        &FirstWindowPixelFormatDescriptor);
    if(FirstWindowPixelFormat == 0)
        puts("Choosing the first pixel format failed.\n");

    if(SetPixelFormat(FirstWindowDeviceContext, FirstWindowPixelFormat,
    &FirstWindowPixelFormatDescriptor) == FALSE)
        puts("Setting the first pixel format failed.\n");

    HGLRC FirstWindowRenderingContext =
        wglCreateContext(FirstWindowDeviceContext);
    if(FirstWindowRenderingContext == NULL)
        puts("Creating the first rendering context failed.\n");

    if(wglMakeCurrent(FirstWindowDeviceContext, FirstWindowRenderingContext) ==
    FALSE)
        puts("Making the first context current failed.\n");

    if(glewInit() != GLEW_OK)
        puts("Initialisation of GLEW failed.\n");

    WNDCLASSEX FinalWindowClass = {};
    FinalWindowClass.cbSize = sizeof(WNDCLASSEX);
    FinalWindowClass.style = CS_OWNDC;
    FinalWindowClass.lpfnWndProc = FinalWindowProcedure;
    FinalWindowClass.lpszClassName = L"FinalWindowClass";
    if(!RegisterClassEx(&FinalWindowClass))
        puts("Registration of the final window class failed\n");

    HWND FinalWindow = CreateWindowEx(WS_EX_APPWINDOW,
        FinalWindowClass.lpszClassName, L"FinalWindow", WS_POPUP, 0, 0, 10, 10,
        NULL, NULL, NULL, NULL);
    if(FinalWindow == NULL)
        puts("Creation of the final window failed.\n");

    PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
        wglGetProcAddress("wglChoosePixelFormatARB");
    if(wglChoosePixelFormatARB == NULL)
        puts("Getting the wglChoosePixelFormatARB function pointer failed.\n");

    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
        (PFNWGLCREATECONTEXTATTRIBSARBPROC)
        wglGetProcAddress("wglCreateContextAttribsARB");
    if(wglCreateContextAttribsARB == NULL)
        puts("Getting the wglCreateContextAttribsARB function pointer"
            "failed.\n");

    int FinalWindowContextAttributes[] = {
        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,
        WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
        WGL_CONTEXT_MINOR_VERSION_ARB, 4,
        WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        0,
    };

    HDC FinalWindowDeviceContext = GetDC(FinalWindow);
    if(FinalWindowDeviceContext == NULL)
        puts("Retrieving the final window device cotext failed.\n");

    int FinalWindowPixelFormat;
    if(FALSE == wglChoosePixelFormatARB(FinalWindowDeviceContext,
    FinalWindowContextAttributes, NULL, 1, &FinalWindowPixelFormat, NULL))
        puts("Choosing the final window pixel format failed.\n");

    HGLRC FinalWindowRenderingContext =
        wglCreateContextAttribsARB(FinalWindowDeviceContext, NULL,
        FinalWindowContextAttributes);
    if(FinalWindowRenderingContext == NULL)
        puts("Creating the final rendering context failed.\n");

    if(FALSE == wglMakeCurrent(FinalWindowDeviceContext,
    FinalWindowRenderingContext))
        puts("Making the final context current failed.\n");

    DWM_BLURBEHIND blur = {};
    blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
    blur.fEnable = 1;
    blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
    DwmEnableBlurBehindWindow(FinalWindow, &blur);

    SetLayeredWindowAttributes(FinalWindow, RGB(0, 0, 0), 255, LWA_COLORKEY);

    // -----   -----   ----- //

    /*WNDCLASSEX wcx = {};
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.style = CS_OWNDC;
    wcx.lpfnWndProc = WindowProcedure;
    wcx.lpszClassName = L"Win32Class";
    RegisterClassEx(&wcx);

    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYERED, wcx.lpszClassName, L"Title",
        WS_POPUP, 400, 300, 800, 400, NULL, NULL, NULL, NULL);

    DWM_BLURBEHIND blur = {};
    blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
    blur.fEnable = 1;
    blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
    DwmEnableBlurBehindWindow(hWnd, &blur);

    SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 255, LWA_COLORKEY);

    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;
    pfd.iLayerType = PFD_MAIN_PLANE;

    HDC DeviceContext = GetDC(hWnd);
    int PixelFormat = ChoosePixelFormat(DeviceContext, &pfd);
    SetPixelFormat(DeviceContext, PixelFormat, &pfd);
    HGLRC RenderingContext = wglCreateContext(DeviceContext);
    wglMakeCurrent(DeviceContext, RenderingContext);

    glewInit();

    int Attributes[] = {
        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,
        WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
        WGL_CONTEXT_MINOR_VERSION_ARB, 4,
        WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        0,
    };

    PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
        wglGetProcAddress("wglChoosePixelFormatARB");
    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
        (PFNWGLCREATECONTEXTATTRIBSARBPROC)
        wglGetProcAddress("wglCreateContextAttribsARB");

    wglChoosePixelFormatARB(DeviceContext, Attributes, NULL, 1, &PixelFormat,
        NULL);
    RenderingContext = wglCreateContextAttribsARB(DeviceContext, NULL,
        Attributes);
    wglMakeCurrent(DeviceContext, RenderingContext);*/

    char VertexShaderSource[] =
    "#version 440 core\n"
    "\n"
    "layout(location = 0) in vec4 position;\n"
    "\n"
    "void main(){\n"
    "   gl_Position = position;\n"
    "}";

    char FragmentShaderSource[] =
    "#version 440 core\n"
    "\n"
    "layout(location = 0) out vec4 colour;\n"
    "\n"
    "void main(){\n"
    "   colour = vec4(0.5, 0.5, 0.5, 1.0);\n"
    "}";

    float Verticies[] = {
         0.0f,  0.5f, // top    : 0
         0.5f,  0.0f, // right  : 1
         0.0f, -0.5f, // bottom : 2
        -0.5f,  0.0f  // left   : 3
    };

    unsigned int Indices[] = {
        3, 0, 1, // top
        3, 2, 1  // bottom
    };

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    unsigned int VertexArray;
    glGenVertexArrays(1, &VertexArray);
    glBindVertexArray(VertexArray);

    unsigned int VertexBuffer;
    glGenBuffers(1, &VertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), Verticies, GL_STATIC_DRAW);

    unsigned int IndexBuffer;
    glGenBuffers(1, &IndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), Indices,
        GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    unsigned int ShaderProgram = CreateShaderProgram(VertexShaderSource,
        FragmentShaderSource);
    glUseProgram(ShaderProgram);

    glViewport(0, 0, 800, 400);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    ShowWindow(FinalWindow, 1);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)){
        DispatchMessage(&msg);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
        wglSwapLayerBuffers(FinalWindowDeviceContext, WGL_SWAP_MAIN_PLANE);
    }
}

LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
    return DefWindowProc(hWnd, uMsg, wp, lp);
}

LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
    switch(uMsg){
        case WM_NCHITTEST: return HTCAPTION;
        case WM_DESTROY: PostQuitMessage(0); return 0;
        default: return DefWindowProc(hWnd, uMsg, wp, lp);
    }
}

unsigned int CreateShader(char* Source, unsigned int Type);

unsigned int CreateShaderProgram(char* VertexSource,
char* FragmentSource){
    unsigned int ShaderProgram = glCreateProgram(),
        VertexShader = CreateShader(VertexSource, GL_VERTEX_SHADER),
        FragmentShader = CreateShader(FragmentSource, GL_FRAGMENT_SHADER);
    glAttachShader(ShaderProgram, VertexShader);
    glAttachShader(ShaderProgram, FragmentShader);
    glLinkProgram(ShaderProgram);
    glValidateProgram(ShaderProgram);
    return ShaderProgram;
}

unsigned int CreateShader(char* Source, unsigned int Type){
    unsigned int Shader = glCreateShader(Type);
    glShaderSource(Shader, 1, (const char* const*)&Source, NULL);
    glCompileShader(Shader);
    return Shader;
}

1 Ответ

3 голосов
/ 03 апреля 2020

SetPixelFormat (DeviceContext, PixelFormat и & pfd);

Вы не можете выполнить SetPixelFormat() дважды для одного и того же окна - это описано в документации WinAPI и подробно описано в каждой статье, описывающей использование wglChoosePixelFormatARB / wglCreateContextAttribsARB на платформе Windows, которую я видел:

Как только формат пикселя окна установлен, его нельзя изменить.

Единственный способ - создать временный контекст OpenGL во временном окне, а затем создать контекст OpenGL для окончательного окна.

Добавить подробные проверки в ваш код, чтобы увидеть, где он не работает - не игнорируйте проверки NULL и BOOL результаты функций WinAPI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...