调试着色器是很困难的。至今还没有printf,可能永远不会有,但是今后可能会出现具有调试能力的开发工具。目前你可以使用一些技巧来调试着色器。OpenGL还提供了更多的函数用于检验你的代码是否编译、链接成功。
在OpenGL2.0中,使用如下函数可以查询编译步骤的状态:
void
glGetShaderiv(GLuint object
, GLenum type, int
*param);
Parameters:
object
- 指向对象的句柄. 着色器或者程序
type - GL_COMPILE_STATUS.
param - 返回值, 如果成功为GL_TRUE, 否则为GL_FALSE.
在OpenGL2.0中,使用如下函数可以查询链接步骤的状态:
void
glGetProgramiv(GLuint object
, GLenum type, int
*param);
Parameters:
object
- the handler to the object
. Either a shader or a program
type - GL_LINK_STATUS.
param - the return
value
, GL_TRUE if
OK, GL_FALSE otherwise.
ARB扩展使用单个函数检测编译状态和连接状态(根据参数的不同):
void
glGetObjectParameterivARB(GLhandleARB object
, GLenum type, int
*param);
Parameters:
object
- 指向对象的句柄. 着色器或者程序
type - GL_OBJECT_LINK_STATUS_ARB或GL_OBJECT_COMPILE_STATUS_ARB.
param - 返回值, 如果成功为1, 否则为0.
第二个参数type,有更多的可选项,在此就不加讨论了。你可以访问3Dlabs
站点获取更多的信息。
当OpenGL向你报告错误时,你可以通过InfoLog获取更详细的错误信息。InfoLog存储了关于最后一个操作的信息,例如编译过程中的错误和警告,链接过程中的问题等。InfoLog甚至会告诉你你的着色器能否在软件中运行,即你的硬件是否支持你现在使用的某些特性,或者你硬件的理想环境。遗憾的是关于InfoLog并没有一个规范,因此不同的驱动和硬件会产生不同的日志。
在OpenGL2.0中,使用如下函数得到某个着色器或者程序的InfoLog:
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 - InfoLog内容.
ARG扩展使用单个函数达到相同的目的:
void
glGetInfoLogARB(GLhandleARB object
, int
maxLen, int
*len, char
*log);
参数:
object
- 指向对象的句柄. 着色器或者程序
maxLen – InfoLog的最大字符长度.
len - 返回InfoLog的实际长度.
log – InfoLog的内容.
GLSL 本可以做到更好的。你必须知道你要查询的InfoLog的精确字节数。在OpenGL2.0中,使用如下函数获取该信息:
void
glGetShaderiv(GLuint object
, GLenum type, int
*param);
void
glGetProgramiv(GLuint object
, GLenum type, int
*param);
参数:
object
- 指向对象的句柄. 着色器或者程序
type - GL_INFO_LOG_LENGTH.
param - 返回值, InfoLog的长度.
ARG扩展使用单个函数达到这个目的:
void
glGetObjectParameterivARB(GLhandleARB object
, GLenum type, int
*param);
参数:
object
- 指向对象的句柄. 着色器或者程序
type - GL_OBJECT_INFO_LOG_LENGTH_ARB.
param - 返回值, InfoLog的长度.
在OpenGL2.0中,如下的函数用于打印InfoLog的内容:
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/n"
,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/n"
,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/n"
,infoLog);
free(infoLog);
}
}