本文为xiedantibu在学习opengles的笔记
,转载请注明作者及出处!
###目录
—-
创建着色器
加载着色器源码
编译着色器
获取编译状态
调用info日志
获取着色器源码
cocos2d-x编译着色器示例
Reference
####创建着色器
—
GLuint glCreateShader(GLenum type)
type:着色器的类型 GL_VERTEX_SHADER或者GL_FRAGMENT_SHADER.
使用glCreateShader
你能依据输入参数创建一个顶点着色器或片段着色器,返回值是个新着色器的句柄,是一个非零的整数值,如果为0则说明发生了错误。不使用了,用glDeleteShader
删除它。
void glDeleteShader(GLuint shader)
shader:要删除的着色器句柄.
如果着色器正连接着一个项目对象,glDeleteShader
不会立刻删除着色器,而是设置删除标记,一旦着色器不再连接项目对象,才删除着色器使用的内存。
####加载着色器源码 —
void glShaderSource(GLuint shader, GLsizei count,const char** string,const GLint* length)
shader :着色器对象句柄
count :着色器源码的字符数,着色器由字符串组成,每个着色器仅有一个主函数main
string :一个由count行GLchar类型的字符串组成的数组,用来表示着色器的源代码数据,string中的字符串可以是NULL结尾的,也可以不是
length :可以是以下三种值的一种。如果length是NULL,那么我们假设string给出的每行字符串都是NULL结尾的。否则,length中必须有count个元素,它们分别表示string中对应行的长度。如果length数组中的某个值是一个整数,那么它表示对应的字符串中的字符数。如果某个值是负数,那么string中的对应行假设为NULL结尾
####编译着色器 —
void glCompileShader(GLuint shader)
shader :着色器对象句柄
####获取编译状态 —
void glGetShaderiv(GLuint shader, GLenum pname,GLint *params)
shader :着色器句柄
pname :需要查询的信息.GL_COMPILE_STATUS|GL_DELETE_STATUS|GL_INFO_LOG_LENGTH|GL_SHADER_SOURCE_LENGTH|GL_SHADER_TYPE
Params :返回查询结果的整型指针
使用GL_COMPILE_STATUS
参数查询编译是否成功,成功返回GL_TRUE
,失败返回GL_FALSE
。如失败,编译错误被写入 info日志。info日志记录了编译器的任何错误和警告。 即使编译成功,同样也有info日志,可以使用GL_INFO_LOG_LENGTH
查询 info日志长度。 可以调用glGetShaderInfoLog
调用info日志。使用GL_SHADER_TYPE
查询着色器类型是GL_VERTEX_SHADER
或者GL_FRAGMENT_SHADER
.使用GL_SHADER_SOURCE_LENGTH
查询着色器源码长度,即使着色器为空。使用GL_DELETE_STATUS
查询着色器是否被glDeleteShader
标记删除。
####调用info日志 —
void glGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog)
shader :handle to the shader object to get the info log for
maxLength :the size of the buffer to store the info log in
length :the length of the info log written (minus the null terminator). If the length does not need to be known, this parameter can be NULL
infoLog :pointer to the character buffer to store the info log in
要使用glGetShaderInfoLog
调用info日志,首先要通过glGetShaderiv
查询GL_INFO_LOG_LENGTH
,因为只有分配足够的字符串才能存储info log。
####获取着色器源码
—
void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
shader :指定查询的着色器
bufsize :the number of bytes available in the array source for returning the shader’s source
length :the length of the returned shader string
source :指定存储着着色器源码的GLchar类型数组 --- --- <a id='cocobuildshader' name='cocobuildshader'> </a> ####[cocos2d-x编译着色器示例](#top) --- cocos2d-x编译着色器的代码主要封装在GLProgram类中,下面就来看看GLProgram中的compileShader方法。
bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source)
{
GLint status;
if (!source)
{
return false;
}
const GLchar *sources[] = {
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform mat3 CC_NormalMatrix;\n"
"uniform vec4 CC_Time;\n"
"uniform vec4 CC_SinTime;\n"
"uniform vec4 CC_CosTime;\n"
"uniform vec4 CC_Random01;\n"
"uniform sampler2D CC_Texture0;\n"
"uniform sampler2D CC_Texture1;\n"
"uniform sampler2D CC_Texture2;\n"
"uniform sampler2D CC_Texture3;\n"
"//CC INCLUDES END\n\n",
source,
};
*shader = glCreateShader(type);//创建着色器
glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, nullptr);//加载着色器源码
glCompileShader(*shader);//编译着色器源码
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);//获取编译状态
if (! status)//如果编译失败
{
GLsizei length;
glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length);//获取着色器源码长度
GLchar* src = (GLchar *)malloc(sizeof(GLchar) * length);//创建保存源码空间
glGetShaderSource(*shader, length, nullptr, src);//获取着色器源码
CCLOG("cocos2d: ERROR: Failed to compile shader:\n%s", src);//打印出错的编译源码
if (type == GL_VERTEX_SHADER)//顶点着色器
{
CCLOG("cocos2d: %s", getVertexShaderLog().c_str());//打印顶点着色器出错log
}
else//片元着色器
{
CCLOG("cocos2d: %s", getFragmentShaderLog().c_str());//打印片元着色器出错log
}
free(src);//回收保存源码空间
return false;;
}
return (status == GL_TRUE);
} 关于打印顶点或者片元着色器出错log的方法,其实就是上文提到的事先得先通过`glGetShaderiv`查询`GL_INFO_LOG_LENGTH`,获取log的长度,再通过`glGetShaderInfoLog`获取info日志,只不过cocos封装了下,方便调用。
//获取顶点着色器log
std::string GLProgram::getVertexShaderLog() const
{
return this->logForOpenGLObject(_vertShader, (GLInfoFunction)&glGetShaderiv, (GLLogFunction)&glGetShaderInfoLog);//传入的是指向glGetShaderiv方法的指针以及指向glGetShaderInfoLog方法的指针
}
//获取片元着色器log
std::string GLProgram::getFragmentShaderLog() const
{
return this->logForOpenGLObject(_fragShader, (GLInfoFunction)&glGetShaderiv, (GLLogFunction)&glGetShaderInfoLog);
}
//上诉两个方法其实调用的都是同一个方法`logForOpenGLObject`,只不过传入的参数不同,分别是顶点着色器的句柄以及片元着色器的句柄,至于其他两个参数,传的是一样的。
std::string GLProgram::logForOpenGLObject(GLuint object, GLInfoFunction infoFunc, GLLogFunction logFunc) const
{
std::string ret;
GLint logLength = 0, charsWritten = 0;
infoFunc(object, GL_INFO_LOG_LENGTH, &logLength);//回调glGetShaderiv方法,获取log长度
if (logLength < 1)
return "";
char *logBytes = (char*)malloc(logLength);//根据logLength长度开辟一片空间保存log
logFunc(object, logLength, &charsWritten, logBytes);//回调glGetShaderInfoLog获取log内容,保存在logBytes中
ret = logBytes;//将logBytes赋值给ret
free(logBytes);//回收保存log的空间
return ret;
}
####在本文中主要是结合cocos2d-x,回顾下着色器的创建和编译,以及在编译出错的情况下,查询编译状态以及出错信息的处理。。。
####Reference —
青春是一场大雨,即使感冒了,还盼回头再淋一次......微笑永远是一个人身上最好看的东西...