Дебаггинг шейдеров — тяжелый труд. В шейдерах нет ничего подобного printf, и вряд ли будет, хотя инструменты разработчика с возможностями отладки уже появляются и будут совершенствоваться.
Действительно, сейчас вы можете использовать кое-какие трюки, но по некоторым причинам они не тривиальны. Но не всё потеряно, есть несколько функций для проверки, был ли код шейдера скомпилирован и прилинкован успешно.

Состояние шагов компилирования может быть запрошено в OpenGL 2.0 следующей функцией:

void glGetShaderiv(GLuint object, GLenum type, int *param);

// Параметры:

//    object — Дескриптор обьекта. Либо шейдера, либо программы.
//    type — GL_COMPILE_STATUS.
//    param — возвращаемое значение, GL_TRUE если всё ОК, иначе GL_FALSE.

 

Состояние шагов линковки может быть запрошено в OpenGL 2.0 следующей функцией:

void glGetProgramiv(GLuint object, GLenum type, int *param);

// Параметры:

//    object — Дескриптор обьекта. Либо шейдера, либо программы.
//    type — GL_LINK_STATUS.
//    param — возвращаемое значение, GL_TRUE если всё ОК, иначе GL_FALSE.

 

С расширениями шейдеров ARB одна и та же функция может быть использована для получения статуса обоих шагов, и линковки, и компилирования, в зависимости от параметров.

void glGetObjectParameterivARB(GLhandleARB object, GLenum type, int *param);

// Параметры:

//    object — Дескриптор обьекта. Либо шейдера, либо программы.
//    type — GL_OBJECT_LINK_STATUS_ARB или GL_OBJECT_COMPILE_STATUS_ARB.
//    param — возвращаемое значение, 1 если всё ОК, иначе 0.

 

Существует много опций для второго параметра «type», однако здесь я их не буду объяснять.
Посетите сайт 3Dlabs для полной спецификации.

Если возвращена ошибка, существует возможность получить больше информации с помощью infoLog.
Этот лог хранит информацию о последней произведённой операции, такую как варнинги и ошибки при компиляции, или проблемы на этапе линковки. Этот лог может даже показать, были ли ваши шейдеры обработаны софтварно, что значит, что ваше железо не поддерживает что-то, что вы напрограммировали, или хардварно — идеальная ситуация. К сожалению, для сообщений InfoLog нет никакой спецификации, так что разные драйвера и железо могут выдавать разный текст.

Чтобы получить InfoLog для специфического шейдера или программы в OpenGL используйте следующие функции:

void glGetShaderInfoLog(GLuint object, int maxLen, int *len, char *log);
void glGetProgramInfoLog(GLuint object, int maxLen, int *len, char *log);// Параметры://    object — Дескриптор обьекта. Либо шейдера, либо программы.
//    maxLen — макс. число получаемых символов от InfoLog.
//    len — реальная длинна полученного InfoLog.
//    log — Сам лог.

 

Опять же, в расширениях шейдеров ARB одна и та же функция используется для получения логов и шейдера, и программы:

void glGetInfoLogARB(GLhandleARB object, int maxLen, int *len, char *log);

// Параметры:

//    object — Дескриптор обьекта. Либо шейдера, либо программы.
//    maxLen — макс. число получаемых символов от InfoLog.
//    len — реальная длинна полученного InfoLog.
//    log — Сам лог.

 

В этом отношении спецификация GLSL могла бы быть и лучше… Чтобы получить лог, вы должны знать его длину.
Чтобы получить этот драгоценный бит информации, используйте следующие функции (OpenGL 2.0):

void glGetShaderiv(GLuint object, GLenum type, int *param);
void glGetProgramiv(GLuint object, GLenum type, int *param);// Параметры://    object — Дескриптор обьекта. Либо шейдера, либо программы.
//    type — GL_INFO_LOG_LENGTH.
//    param — возвращаемое значение, длинна лога

 

Синтаксис расширений ARB в очередной раз проще — хватает одной функции:

void glGetObjectParameterivARB(GLhandleARB object, GLenum type, int *param);

// Параметры:

//    object — Дескриптор обьекта. Либо шейдера, либо программы.
//    type — GL_OBJECT_INFO_LOG_LENGTH_ARB.
//    param — возвращаемое значение, длинна лога

 

Следующие функции могут быть использованы для вывода информации InfoLog В OpenGL 2.0:

    void printShaderInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten  = 0;
char *infoLog;glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
printf(«%s
«
,infoLog);
free(infoLog);
}
}

void printProgramInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten  = 0;
char *infoLog;

glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
printf(«%s
«
,infoLog);
free(infoLog);
}
}

 

Использование шейдерных расширений ARB делает процесс проще:

    void printInfoLog(GLhandleARB obj)
{
int infologLength = 0;
int charsWritten  = 0;
char *infoLog;glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
&infologLength);if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
printf(«%s
«
,infoLog);
free(infoLog);
}
}