Обработка ошибок в OpenGL

Опубликовано: 4 Сентября, 2022

Многие функции OpenGL API очень полезны и эффективны. Но вполне возможно, что программы OpenGL могут содержать ошибки. Таким образом, становится важным изучить обработку ошибок в программах OpenGL. Библиотеки OpenGL и GLU имеют простой метод записи ошибок. Когда программа OpenGL обнаруживает ошибку при вызове подпрограммы базовой библиотеки или подпрограммы GLU, она записывает внутренний код ошибки, а подпрограмма, вызвавшая ошибку, игнорируется. Хотя OpenGL записывает только один код ошибки в любой момент времени. OpenGL использует собственные методы обнаружения ошибок. После возникновения ошибки никакой другой код ошибки не будет записан, пока программа явно не запросит состояние ошибки OpenGL.

Синтаксис:

GLenum code;
code = glGetError ();

Этот вызов функции возвращает текущий код ошибки и очищает внутренний флаг ошибки:

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

Базовая библиотека OpenGL предоставляет определения для ряда символических констант, которые представляют различные состояния ошибок. Библиотека GLU также определяет ряд кодов ошибок, но большинство из них имеют почти бессмысленные имена, такие как GLUNURBSERROR1 , GLUNURBSERROR2 и так далее.

Библиотека GLU содержит функцию, которая возвращает описательную строку для каждой из ошибок GLU и GL. Чтобы использовать его, сначала получите текущий код ошибки, а затем передайте его в качестве параметра этой функции. Возвращаемое значение может быть распечатано с помощью функций стандартной библиотеки C, таких как функция fprintf().

Ниже приведен фрагмент кода для реализации описанного выше подхода:

C




#include <stdio.h>
GLenum code;
  
const GLubyte* string;
code = glGetError();
string = gluErrorString(code);
fprintf(stderr, "OpenGL error: %s ", string);

Объяснение: Значение, возвращаемое gluErrorString , указывает на строку, расположенную внутри библиотеки GLU. Поскольку это не динамически выделяемая строка, программа не должна явно освобождать ее. Кроме того, он не должен изменяться программой (поэтому модификатор const в объявлении строки). Эти вызовы функций довольно легко инкапсулировать в общую функцию сообщения об ошибках в программе.

Приведенная ниже функция извлечет текущий код ошибки, напечатает описательную строку ошибки и вернет код в вызывающую процедуру:

Объяснение: По умолчанию glGetError печатает только номера ошибок, что нелегко понять, если коды ошибок уже не запомнены. Таким образом, часто имеет смысл написать небольшую вспомогательную функцию, чтобы легко распечатать строки ошибок вместе с тем, где была вызвана функция проверки ошибок:

GLenum glCheckError_(const char *file, int line)
{
    GLenum errorCode;
    while ((errorCode = glGetError()) != GL_NO_ERROR)
    {
        std::string error;
        switch (errorCode)
        {
            case GL_INVALID_ENUM:                  error = “INVALID_ENUM”; break;
            case GL_INVALID_VALUE:                 error = “INVALID_VALUE”; break;
            case GL_INVALID_OPERATION:             error = “INVALID_OPERATION”; break;
            case GL_STACK_OVERFLOW:                error = “STACK_OVERFLOW”; break;
            case GL_STACK_UNDERFLOW:               error = “STACK_UNDERFLOW”; break;
            case GL_OUT_OF_MEMORY:                 error = “OUT_OF_MEMORY”; break;
            case GL_INVALID_FRAMEBUFFER_OPERATION: error = “INVALID_FRAMEBUFFER_OPERATION”; break;
        }
        std::cout << error << ” | ” << file << ” (” << line << “)” << std::endl;
    }
    return errorCode;
}
#define glCheckError() glCheckError_(__FILE__, __LINE__) 

Полезно более точно знать, какой вызов glCheckError вернул ошибку, если любой из этих вызовов glCheckError сгруппирован в нашей базе данных.

glBindBuffer(GL_VERTEX_ARRAY, vbo);
glCheckError();

Пример вывода: