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, которая позволит вам сделать это в переносимом режиме.