本篇文章旨在记录cocos2dx中的shader文件是如何组织和编译的,理清脉络后,更容易对shader进行扩展和自定义。
shader使用的文件包括GLProgram 、GLProgramState、GLProgramCache、GLProgramStateCache
GLProgramCache文件中的reloadDefaultGLPrograms()函数会编译所有的cocos内置的shader
cocos的shader文件定义在cocos/renderer下面,是用const char定义的全局变量,ccShader.cpp include “xxx.frag” 就可以在cpp文件展开。 调用initWithByteArrays()函数 编译shader
在shader中使用了一个STRINGIFY的宏 STRINGIFY(A)=#(A) "#"的意思是把()内的内容用字符串替代
ccShaders.h 定义全局的shader脚本字符串
CCGLProgram.h 定义shader的宏
MVP_MATRIX Model view projection matrix 模型视图投影矩阵
模型视图投影矩阵=投影矩阵×视图矩阵×模型矩阵
ShaderPositionTextureColor_noMVP 这些string类型定义在CCGLProgram.cpp中在reloadDefaultGLPrograms()函数中 作为 std::unordered_map<std::string, GLProgram> _programs;的key 保存对应的program
调用node的setGLProgram()可以直接设置shader但是这样做不高效,每次都会编译和链接,需要用GLProgramCache来提高效率。GLProgramCache 中是一个map,字符串作为key,glProgram是value,先在GLProgramCache中查找,没有的话再创建,并且把它加到GLProgramCache中。 createWithFilenames()不如createWithByteArrays()高效。原因是使用file存储shader会查找磁盘,使用array不需要查找磁盘。
static const char * COCOS2D_SHADER_UNIFORMS =
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MultiViewPMatrix[4];\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform mat4 CC_MultiViewMVPMatrix[4];\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";
在这文件中的 bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source, const std::string& compileTimeHeaders, const std::string& convertedDefines) 这个函数中
有这样一行代码
const GLchar *sources[] = {
headersDef.c_str(),
COCOS2D_SHADER_UNIFORMS,
convertedDefines.c_str(),
source};
cocos会对传进来的shader添加一个头部 headersDef ,加一堆的uniform变量 ,uniform就是数组里的东西