glGenBuffers - GL_INVALID_OPERATION

У меня возникает проблема всякий раз, когда я вызываю glGenBuffers на окнах. Всякий раз, когда я вызываю glGenBuffers или любые другие функции версии 3.2 или выше, OpenGL возвращает ошибку INVALID_OPERATION. После прочтения в Интернете это, вероятно, вызвано отсутствием обновленного указателя функции для 3.2 на окнах. Из всего, что я прочитал, вы должны получить указатели функций во время выполнения, задав Windows API wglGetProcAddress вернуть указатель на функцию для использования в вашей программе и вашем текущем драйвере. Само по себе это не сложно, но зачем изобретать велосипед. Вместо этого я предпочитаю включить GLEW для обработки указателей функций для меня.

Вот небольшая программа, чтобы продемонстрировать мою проблему.

#define GLEW_STATIC
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <iostream>


void PrintError(void)
{
    // Print glGetError()
}

int main()
{


    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,GL_TRUE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    PrintError();

    // Initalize GLEW
    glewExperimental = GL_TRUE;
    GLenum error = glewInit();
    if(error!= GLEW_OK)
        std::cerr << glewGetErrorString(error) << std::endl;


    // Glew information
    if(GLEW_VERSION_3_2)
        std::cout << "Supports 3.2.." << std::endl;

    // Try buffer
    GLuint buffer;
    glGenBuffers(1,&buffer); // INVALID_OPERATION
    PrintError(); // Error shows up


    // This is our main loop
    while(!glfwWindowShouldClose(window))
    {
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;
}

Когда я запускаю следующий код, я получаю окна OpenGL. Однако в моей консоли я вижу, что первый вызов PrintError возвратил NO_ERROR, а второй вызов вернул INVALID_OPERATION. У меня такое ощущение, что я упускаю из виду какой-то небольшой факт, но я просто не могу найти его на веб-странице glfw или GLEW.

Сейчас я работаю: glfw-3.0.4 (32 бита), glew-1.10.0 (32 бита)

**** Обновить ****

В ответ на сообщение гламперта я добавил следующий код после метода glewInit().

GLenum loop_error = glGetError();
while (loop_error != GL_NO_ERROR)
{
    switch (loop_error)
    {
    case GL_NO_ERROR: std::cout << "GL_NO_ERROR" << std::endl; break;
    case GL_INVALID_ENUM: std::cout << "GL_INVALID_ENUM" << std::endl; break;
    case GL_INVALID_VALUE: std::cout << "GL_INVALID_VALUE" << std::endl; break;
    case GL_INVALID_OPERATION: std::cout << "GL_INVALID_OPERATION" << std::endl; break;
    case GL_INVALID_FRAMEBUFFER_OPERATION: std::cout << "GL_INVALID_FRAMEBUFFER_OPERATION" << std::endl; break;
    case GL_OUT_OF_MEMORY: std::cout << "GL_OUT_OF_MEMORY" << std::endl; break;
    }
    loop_error = glGetError();
}

Что подтверждает его предположение, что неправильная операция вызвана кодом glewinit.

* Обновить *

Похоже, что это известная проблема с контекстом GLEW & 3.2. http://www.opengl.org/wiki/OpenGL_Loading_Library

После определения GLEW в качестве источника проблем я обнаружил следующие два поста. OpenGL: glGetError () возвращает недействительное перечисление после вызова glewInit()

Похоже, предлагаемое решение состоит в том, чтобы установить экспериментальный флаг, который я уже делаю. Тем не менее, веб-сайт упоминает, что даже после этого все еще существует вероятность того, что это вызовет недопустимую операцию и не сможет получить указатели на функции.

Я думаю, что на данный момент мое лучшее решение - просто взять мои собственные указатели функций.

1 ответ

Решение

Вполне возможно, что ошибка, которую вы получаете, является остаточной ошибкой от GLFW или GLEW.

Попробуйте добавить это после кода инициализации библиотеки:

GLenum error;
while ((error = glGetError()) != GL_NO_ERROR) 
{
    // print(error), etc...
}

и прежде чем пытаться вызвать какую-либо функцию OpenGL, очистите кеш ошибок.

Если ошибка действительно вызвана GLEW, она не обязательно может быть опасной и не позволяет библиотеке работать. Так что я бы не отказался от библиотеки только из-за этой проблемы, которая в итоге будет исправлена. Однако, если вы решите извлечь указатели на функции самостоятельно, GLFW предоставит функцию glfwGetProcAddress, которая позволит вам сделать это в переносимом режиме.

Другие вопросы по тегам