前言: 这个系列是我自己在看cocos2dx源码时记录的一些比较重要的数据结构跟方法中间可能穿插些opengl的知识. 每个介绍的类之间没有固定引用顺序,仅作为个人的记录,可能会有点乱(其实主要是为了怕记不住,这次看源码的目的是搞清楚 cocos的MVPMatrix的使用)
#1 CCGLProgram CCGLProgram 是 管理opengl 管线中 GLProgram 和其相关的 着色器, 顶点属性, 统一变量等等的类, 以下是其中几个比较关键的结构体
##1.1 VertextAttrib
VertexAtttrib结构体在数据存储上于 glGetActiveAttrib获取的结构时一致的 index : 指的是vertexShader顶点着色器中 attribute 属性 , 在shader中 可以用(layout=?)指定index size:属性对应类型存储的数量 例如color = {1.0, 1.0, 1.0}, size 为 3, type 为GL_FLOAT type: 指的是属性对应的存储类型 name: 在顶点着色器中属性的名字
/**VertexAttrib is a structure to encapsulate data got from glGetActiveAttrib.*/
struct VertexAttrib
{
/**Index of attribute, start from 0.*/
GLuint index;
/**Number of Data type in the attribute, could range from 0-4.*/
GLint size;
/**Data type of the attribute, could be GL_FLOAT, GL_UNSIGNED_BYTE etc.*/
GLenum type;
/**The string name in vertex shader.*/
std::string name;
};
这个结构体主要被应用于一下opengl函数的设置
void glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,const GLvoid * pointer);
//GLboolean normalized 属性主要用于标识传入的属性的各个分量是否需要归一化, stride是相同属性的两个数据间的偏移, pointer代表的是属性的首个在buffer里的偏移
##1.2 Uniform Uniform 主要用于存储 glGetActiveUnifom 和glGetUniformLocation 的数据
/**Uniform is a structure to encapsulate data got from glGetActiveUniform and glGetUniformLocation.*/
struct Uniform
{
/**The place where the uniform placed, starts from 0.*/
GLint location;
/**Number of data type in attribute.*/
GLint size;
/**Data type of the attribute.*/
GLenum type;
/**String of the uniform name.*/
std::string name;
};
uniform 统一变量是在一个glprogram 通用的 统一变量空间可以被顶点着色器个片段着色器同时引用 location : 统一变量在glprogram里的位置 ,这个可用的统一变量数是有上限的 size: 相应统一变量的分量数量 type:相应统一变量的数据类型 name:相应统一变量的名字 结构体内容可被用于一下opengl函数
void glUniform*(GLint location, GLsizei count, const GLfloat *value)
//count:指明要更改的元素个数。如果目标uniform变量不是一个数组,那么这个值应该设为1;如果是数组,则应该设置为>=1。
//value:指定一个具有count个数值的数组指针,用来更新指定的uniform变量。
##1.3 VertexIndex 预定义的顶点属性的对应的index, 占坑
/**Enum the preallocated vertex attribute. */
enum
{
/**Index 0 will be used as Position.*/
VERTEX_ATTRIB_POSITION,
/**Index 1 will be used as Color.*/
VERTEX_ATTRIB_COLOR,
/**Index 2 will be used as Tex coord unit 0.*/
VERTEX_ATTRIB_TEX_COORD,
/**Index 3 will be used as Tex coord unit 1.*/
VERTEX_ATTRIB_TEX_COORD1,
/**Index 4 will be used as Tex coord unit 2.*/
VERTEX_ATTRIB_TEX_COORD2,
/**Index 5 will be used as Tex coord unit 3.*/
VERTEX_ATTRIB_TEX_COORD3,
/**Index 6 will be used as Normal.*/
VERTEX_ATTRIB_NORMAL,
/**Index 7 will be used as Blend weight for hardware skin.*/
VERTEX_ATTRIB_BLEND_WEIGHT,
/**Index 8 will be used as Blend index.*/
VERTEX_ATTRIB_BLEND_INDEX,
/**Index 9 will be used as tangent.*/
VERTEX_ATTRIB_TANGENT,
/**Index 10 will be used as Binormal.*/
VERTEX_ATTRIB_BINORMAL,
VERTEX_ATTRIB_MAX,
// backward compatibility
VERTEX_ATTRIB_TEX_COORDS = VERTEX_ATTRIB_TEX_COORD,
};
##1.4 UniformIndex 预定义的统一变量的对应的index, 占坑. 这里代码用到的枚举名字大家如果有学过opengl的话应该会非常熟悉
enum
{
/**Ambient color.*/
UNIFORM_AMBIENT_COLOR,
/**Projection matrix.*/
UNIFORM_P_MATRIX,
/**Model view matrix.*/
UNIFORM_MV_MATRIX,
/**Model view projection matrix.*/
UNIFORM_MVP_MATRIX,
/**Normal matrix.*/
UNIFORM_NORMAL_MATRIX,
/**Time.*/
UNIFORM_TIME,
/**sin(Time).*/
UNIFORM_SIN_TIME,
/**cos(Time).*/
UNIFORM_COS_TIME,
/**Random number.*/
UNIFORM_RANDOM01,
/** @{
* Sampler 0-3, used for texture.
*/
UNIFORM_SAMPLER0,
UNIFORM_SAMPLER1,
UNIFORM_SAMPLER2,
UNIFORM_SAMPLER3,
/**@}*/
UNIFORM_MAX,
};
##1.4built in shader 内建的shader 字符串
/**
@name Built Shader types
@{
*/
/** ETC1 ALPHA supports for 2d */
static const char* SHADER_NAME_ETC1AS_POSITION_TEXTURE_COLOR;
static const char* SHADER_NAME_ETC1AS_POSITION_TEXTURE_COLOR_NO_MVP;
static const char* SHADER_NAME_ETC1AS_POSITION_TEXTURE_GRAY;
static const char* SHADER_NAME_ETC1AS_POSITION_TEXTURE_GRAY_NO_MVP;
/**Built in shader for 2d. Support Position, Texture and Color vertex attribute.*/
static const char* SHADER_NAME_POSITION_TEXTURE_COLOR;
/**Built in shader for 2d. Support Position, Texture and Color vertex attribute, but without multiply vertex by MVP matrix.*/
static const char* SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP;
/**Built in shader for 2d. Support Position, Texture vertex attribute, but include alpha test.*/
//省略一大堆
/**
Built in shader for camera clear
*/
static const char* SHADER_CAMERA_CLEAR;
/**
end of built shader types.
@}
*/
##1.5 built in uniform 内建的 uniform 默认名
/**
@name Built uniform names
@{
*/
/**Ambient Color uniform.*/
static const char* UNIFORM_NAME_AMBIENT_COLOR;
/**Projection Matrix uniform.*/
static const char* UNIFORM_NAME_P_MATRIX;
/**Model view matrix uniform.*/
static const char* UNIFORM_NAME_MV_MATRIX;
/**Model view projection uniform.*/
static const char* UNIFORM_NAME_MVP_MATRIX;
/**Normal matrix uniform.*/
static const char* UNIFORM_NAME_NORMAL_MATRIX;
/**Time uniform.*/
static const char* UNIFORM_NAME_TIME;
/**Sin time uniform.*/
static const char* UNIFORM_NAME_SIN_TIME;
/**Cos time uniform.*/
static const char* UNIFORM_NAME_COS_TIME;
/**Random number uniform.*/
static const char* UNIFORM_NAME_RANDOM01;
/**
@{ Sampler uniform 0-3, used for textures.
*/
static const char* UNIFORM_NAME_SAMPLER0;
static const char* UNIFORM_NAME_SAMPLER1;
static const char* UNIFORM_NAME_SAMPLER2;
static const char* UNIFORM_NAME_SAMPLER3;
/**
@}
*/
/**Alpha test value uniform.*/
static const char* UNIFORM_NAME_ALPHA_TEST_VALUE;
/**
end of Built uniform names
@}
*/
1.6 built in attribute names
默认的内建属性名字
/**
@name Built Attribute names
@{
*/
/**Attribute color.*/
static const char* ATTRIBUTE_NAME_COLOR;
/**Attribute position.*/
static const char* ATTRIBUTE_NAME_POSITION;
/**@{ Attribute Texcoord 0-3.*/
static const char* ATTRIBUTE_NAME_TEX_COORD;
static const char* ATTRIBUTE_NAME_TEX_COORD1;
static const char* ATTRIBUTE_NAME_TEX_COORD2;
static const char* ATTRIBUTE_NAME_TEX_COORD3;
/**@}*/
/**Attribute normal.*/
static const char* ATTRIBUTE_NAME_NORMAL;
/**Attribute blend weight.*/
static const char* ATTRIBUTE_NAME_BLEND_WEIGHT;
/**Attribute blend index.*/
static const char* ATTRIBUTE_NAME_BLEND_INDEX;
/**Attribute blend tangent.*/
static const char* ATTRIBUTE_NAME_TANGENT;
/**Attribute blend binormal.*/
static const char* ATTRIBUTE_NAME_BINORMAL;
/**
end of Built Attribute names
@}
*/
1.7 一些渲染流程管线方法的包装函数
挑选几个可以展示流程的 1.创建glprogram 省略了代码里如何使用内建shader名创建byteArray的过程
bool GLProgram::initWithByteArrays(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray, const std::string& compileTimeDefines)
{
_program = glCreateProgram();
CHECK_GL_ERROR_DEBUG();
// convert defines here. If we do it in "compileShader" we will do it twice.
// a cache for the defines could be useful, but seems like overkill at this point
std::string replacedDefines = "";
replaceDefines(compileTimeDefines, replacedDefines);
_vertShader = _fragShader = 0;
if (vShaderByteArray)
{
if (!compileShader(&_vertShader, GL_VERTEX_SHADER, vShaderByteArray, replacedDefines))
{
CCLOG("cocos2d: ERROR: Failed to compile vertex shader");
return false;
}
}
// Create and compile fragment shader
if (fShaderByteArray)
{
if (!compileShader(&_fragShader, GL_FRAGMENT_SHADER, fShaderByteArray, replacedDefines))
{
CCLOG("cocos2d: ERROR: Failed to compile fragment shader");
return false;
}
}
if (_vertShader)
{
glAttachShader(_program, _vertShader);
}
CHECK_GL_ERROR_DEBUG();
if (_fragShader)
{
glAttachShader(_program, _fragShader);
}
_hashForUniforms.clear();
CHECK_GL_ERROR_DEBUG();
return true;
}
2.链接
void GLProgram::link()
// 内部调用了
//void GLProgram::bindPredefinedVertexAttribs()
//绑定默认的顶点属性
//关键还是这个gl函数
//glBindAttribLocation(_program, attribute_locations[i].location, attribute_locations[i].attributeName);
3.使用
void GLProgram::use();
//内部实际调用 glUseProgram()
//很奇怪为什么没有dettachshader, 其实链接完就可以释放点shader在cpu端的内存了
4.更新 这里只找到对uniform统一变量的, MVPMatrix主要就是用uniform传入渲染管线的 网上的说法是cocos管理了一个变换矩阵的堆栈,用于管理和保存需要使用的矩阵数据
void GLProgram::updateUniforms()
5.其他类似删除释放glprogram , shader内存的包装方法都在源码中很容易找到
#3GLProgramCache 管理所有的GLProgram生死存亡的类
class CC_DLL GLProgramCache : public Ref
{
public:
/**
Constructor.
* @js ctor
*/
GLProgramCache();
/**
Destructor.
* @js NA
* @lua NA
*/
~GLProgramCache();
/** returns the shared instance */
/** 怀念的OC风格,现在都没人写OC了吗, 就想知道swift以后会直接兼容C++吗*/
static GLProgramCache* getInstance();
/** purges the cache. It releases the retained instance. */
static void destroyInstance();
/** @deprecated Use getInstance() instead */
CC_DEPRECATED_ATTRIBUTE static GLProgramCache* sharedShaderCache();
/** @deprecated Use destroyInstance() instead */
CC_DEPRECATED_ATTRIBUTE static void purgeSharedShaderCache();
/** loads the default shaders */
void loadDefaultGLPrograms();
CC_DEPRECATED_ATTRIBUTE void loadDefaultShaders() { loadDefaultGLPrograms(); }
/** reload the default shaders */
void reloadDefaultGLPrograms();
CC_DEPRECATED_ATTRIBUTE void reloadDefaultShaders() { reloadDefaultGLPrograms(); }
/** returns a GL program for a given key
*/
/*使用 对应的char* 变量作为索引 */
//例子:GLProgram *p = getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR);
GLProgram * getGLProgram(const std::string &key);
CC_DEPRECATED_ATTRIBUTE GLProgram * getProgram(const std::string &key) { return getGLProgram(key); }
CC_DEPRECATED_ATTRIBUTE GLProgram * programForKey(const std::string &key){ return getGLProgram(key); }
/** adds a GLProgram to the cache for a given name */
void addGLProgram(GLProgram* program, const std::string &key);
CC_DEPRECATED_ATTRIBUTE void addProgram(GLProgram* program, const std::string &key) { addGLProgram(program, key); }
/** reload default programs these are relative to light */
void reloadDefaultGLProgramsRelativeToLights();
private:
/**
@{
Init and load predefined shaders.
*/
bool init();
void loadDefaultGLProgram(GLProgram *program, int type);
/**
@}
*/
/**Get macro define for lights in current openGL driver.*/
/*获取宏定义的light GLSL方法*/
std::string getShaderMacrosForLight() const;
/**Predefined shaders.*/
std::unordered_map<std::string, GLProgram*> _programs;
};
PS:第一次写可能像是直接贴代码, 实际也的确如此, 对渲染管线的流程也只是只言片语,不成逻辑,是在抱歉....如果对opengl有兴趣的话可以点击https://learnopengl.com/这里有全套的教程,简单易学.ios 开发可以github上搜索GPUImage项目作为学习opengles2.0的参考