一、UniformValue

对一个uniform变量的状态(name、location、size、type)、值(union)的封装。

数据结构

  1. class CC_DLL UniformValue {
  2. protected:
  3. // uniform值类型的分类
  4. enum class Type {
  5. VALUE, // 基本类型:int、float、vec、mat
  6. POINTER, // 数值类型:float[1],float[2],float[3],float[4],
  7. CALLBACK_FN // 由外部回调设置值
  8. };
  9. Uniform* _uniform; // 一个uniform变量除值外的状态信息(location、size、type、name),weak reference
  10. GLProgram* _glprogram; // 这个uniform所属的GLProgram,weak reference
  11. Type _type; // the uniform's type
  12. union U { // 这个Uniform变量的值,用共同体结构。里面列出了所有可能的类型值,只能是其中一个
  13. float floatValue; // uniform float shit;
  14. int intValue; // uniform int shit;
  15. float v2Value[2]; // uniform vec2 shit;
  16. float v3Value[3]; // uniform vec3 shit;
  17. float v4Value[4]; // uniform vec4 shit;
  18. float matrixValue[16]; // uniform mat4 shit;
  19. struct {
  20. GLuint textureId;
  21. GLuint textureUnit;
  22. Texture2D* texture;
  23. } tex; // uniform sampler2D shit;
  24. struct {
  25. const float* pointer;
  26. GLsizei size;
  27. } floatv; // uniform float[] shit;
  28. struct {
  29. const float* pointer;
  30. GLsizei size;
  31. } v2f; // uniform float[2] shit;
  32. struct {
  33. const float* pointer;
  34. GLsizei size;
  35. } v3f; // uniform float[3] shit;
  36. struct {
  37. const float* pointer;
  38. GLsizei size;
  39. } v4f; // uniform float[4] shit;
  40. std::function<void(GLProgram*, Uniform*)> *callback; // 由于外部设置这个uniform的值
  41. } _value;
  42. };
  1. class CC_DLL UniformValue
  2. {
  3. public:
  4. // 设置uniform的值
  5. void setFloat(float value);
  6. void setInt(int value);
  7. void setFloatv(ssize_t size, const float* pointer);
  8. void setVec2(const Vec2& value);
  9. void setVec2v(ssize_t size, const Vec2* pointer);
  10. void setVec3(const Vec3& value);
  11. void setVec3v(ssize_t size, const Vec3* pointer);
  12. void setVec4(const Vec4& value);
  13. void setVec4v(ssize_t size, const Vec4* pointer);
  14. void setMat4(const Mat4& value);
  15. // 由外部的callback来设置uniform的值
  16. void setCallback(const std::function<void(GLProgram*, Uniform*)> &callback);
  17. // uniform sampler2D shit;
  18. void setTexture(Texture2D* texture, GLuint textureUnit);
  19. void apply(); // 设置uniform的值
  20. // 重载了赋值操作符
  21. UniformValue& operator=(const UniformValue& o);
  22. };

二、VertexAttribValue

VertexAttribValue是对GL函数glVertexAttribPointer及其参数的封装。相当于保存了一个通用顶点属性的状态,通过这个随时恢复这个状态。

  1. void glVertexAttribPointer( GLuint index, // attribute的location
  2. GLint size, // 分量数量
  3. GLenum type, // 分量数据类型
  4. GLboolean normalized, // 是否需要归一化
  5. GLsizei stride, // 步进长度
  6. const GLvoid* pointer); // 在VBO管理的数据中的偏移字节数

数据结构

  1. class CC_DLL VertexAttribValue {
  2. protected:
  3. VertexAttrib* _vertexAttrib; // active的顶点属性的相关信息(name、size、type、location),weak ref
  4. bool _enabled; // 可以执行glVertexAttribPointer了
  5. bool _useCallback; // 见下面的联合体,用callback还是pointer。
  6. // 方法一:要么通过pointer的数据作为参数,调用glVertexAttribPointer
  7. // 方法二:要么由外部传入的callback自己调用glVertexAttribPointer
  8. union U{ // 联合体
  9. struct {
  10. GLint size;
  11. GLenum type;
  12. GLboolean normalized;
  13. GLsizei stride;
  14. GLvoid *pointer;
  15. } pointer;
  16. std::function<void(VertexAttrib*)> *callback;
  17. } _value;
  18. };
  1. class CC_DLL VertexAttribValue {
  2. public:
  3. // 方法一,参数对照上面glVertexAttribPointer的参数
  4. void setPointer(GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid *pointer);
  5. // 方法二
  6. void setCallback(const std::function<void(VertexAttrib*)> &callback);
  7. void apply(); // 按两种方法中其中一种执行glVertexAttribPointer,恢复这个顶点属性状态。
  8. };

三、GLProgramState

为什么提出State的概念?请看下面着色器,这两个着色器是实现ETC1压缩纹理的alpha支持,做法就是每个ETC1都有一张像素宽高的alpha texture,将这两个texture混合,就达到了alpha效果。

  1. // *******************************************
  2. // ******* 顶 点 着 色 器
  3. // *******************************************
  4. # version 100
  5. uniform mat4 CC_MVPMatrix; // MVP矩阵
  6. attribute vec4 a_position; // 顶点坐标
  7. attribute vec4 a_color; // 顶点颜色
  8. attribute vec2 a_texCoord; // 该顶点对应的纹理坐标
  9. varying vec4 v_fragmentColor; // 顶点颜色传递给片段着色器
  10. varying vec2 v_texCoord; // 顶点纹理坐标传递给片段着色器
  11. void main()
  12. {
  13. gl_Position = CC_MVPMatrix;
  14. v_fragmentColor = a_color;
  15. v_texCoord = a_texCoord
  16. }
  17. // *******************************************
  18. // ******* 片 段 着 色 器
  19. // *******************************************
  20. uniform sampler2D CC_Texture0; // 纹理单元GL_TEXTURE0的纹理数据的采样器
  21. uniform sampler2D CC_Texture1; // 纹理单元GL_TEXTURE1的纹理数据的采样器
  22. varying vec4 v_fragmentColor; // 顶点颜色传递给片段着色器
  23. varying vec2 v_texCoord; // 顶点纹理坐标传递给片段着色器
  24. void main()
  25. {
  26. vec4 texColor = texture2D(CC_Texture0, v_texCoord); // 纹理颜色
  27. float alpha = texture2D(CC_Texture1, v_texCoord); // alpha texture的R值
  28. gl_FragColor = v_fragmentColor * vec4(texColor.rgb * alpha, alpha);
  29. }

实际场景中会有很多的不同的ETC1纹理需要alpha支持,对应在着色器上的区别就是uniform值、attribute值的区别,main函数主体还是一样的。我们完全可以只使用一个GLProgram,然后借助GL函数,动态的改变uniform值、attribute值,这样的话就无需创建多个GLProgram了,cocos就将动态改变的这个过程的信息封装成一个GLProgramState。
这里注意一点,GLProgramState封装的uniform中,只有user define的,并不包含cocos内置的。

1、数据结构

  1. class CC_DLL GLProgramState : public Ref
  2. {
  3. bool _uniformAttributeValueDirty; // dirty flag,是否需要重新获取
  4. // 这里缓存的都是user define uniform,并没有cocos内置的uniform
  5. unordered_map<std::string, GLint> _uniformsByName; // name -> location
  6. unordered_map<GLint, UniformValue> _uniforms; // location -> UniformValue
  7. unordered_map<std::string, VertexAttribValue> _attributes; // name -> VertexAttribValue
  8. unordered_map<std::string, int> _boundTextureUnits; // uniform name -> texture unit
  9. int _textureUnitIndex; // 对应纹理单元:GL_TEXTURE0 +_textureUnitIndex,1 <= _textureUnitIndex <= 4,
  10. // vertex attribute flag,每一位对应location的通用顶点属性的开关,例如:
  11. // _vertexAttribsFlags = 1001001(二进制),则
  12. // glEnableVertexAttribArray(location=0、3、6的attribute)
  13. // glEnableVertexAttribArray(其他location的attribute)
  14. uint32_t _vertexAttribsFlags;
  15. GLProgram* _glprogram; // 关联的gl program object
  16. Node* _nodeBinding; // render的node,weak ref
  17. // contains uniform name and variable
  18. // key: uniform name
  19. // value:
  20. std::unordered_map<std::string, std::string> _autoBindings;
  21. // Map of custom auto binding resolvers.
  22. static std::vector<AutoBindingResolver*> _customAutoBindingResolvers;
  23. };

2、创建

  1. class CC_DLL GLProgramState : public Ref
  2. {
  3. public:
  4. // **************************************************
  5. // !!!注意,只要缓存了GLProgramState,则GLProgram就在GLProgramStateCache中通过cocos2d::Map retain了
  6. // !!!注意,如果我们要操作GLProgramState对象,务必自己retain起来,因为是auto release对象。
  7. // **************************************************
  8. // 创建一个全新的独立的new instance,不会缓存到GLProgramState中。
  9. static GLProgramState* create(GLProgram* glprogram);
  10. // 1、从缓存中查找并返回。如果没有找到,则创建新的并缓存。
  11. static GLProgramState* getOrCreateWithGLProgram(GLProgram* glprogram);
  12. // 1、GLProgram必须在缓存中,否则直接返回nullptr
  13. // 2、从缓存中查找并返回。如果没有找到,则创建新的并缓存。
  14. static GLProgramState* getOrCreateWithGLProgramName(const std::string& glProgramName );
  15. // 这个版本慎用,你先看懂源码吧。
  16. // 1、GLProgram必须在缓存中。
  17. // 2、从缓存中查找并返回。如果没有找到,则创建新的并缓存。
  18. // 3、texture森
  19. static GLProgramState* getOrCreateWithGLProgramName(const std::string& glProgramName, Texture2D* texture);
  20. // 1、先确保缓存了GLProgram(vertexShader + "+" + fragShader + "+" + compileTimeDefines)
  21. // 2、然后返回一个全新独立的GLProgramState instance
  22. static GLProgramState* getOrCreateWithShaders(const std::string& vertexShader, const std::string& fragShader, const std::string& compileTimeDefines);
  23. // 返回一个全新独立的GLProgramState instance
  24. GLProgramState* clone() const;
  25. };

3、更新uniform值(状态)

注意,只能更新user define uniform。

  1. class CC_DLL GLProgramState : public Ref
  2. {
  3. // 修改uniformValue的值,注意并没有立即生效,仅仅是设置到uniformValue的状态中了。调用apply生效。
  4. void setUniformInt(const std::string& uniformName, int value);
  5. void setUniformFloat(const std::string& uniformName, float value);
  6. void setUniformFloatv(const std::string& uniformName, ssize_t size, const float* pointer);
  7. void setUniformVec2(const std::string& uniformName, const Vec2& value);
  8. void setUniformVec2v(const std::string& uniformName, ssize_t size, const Vec2* pointer);
  9. void setUniformVec3(const std::string& uniformName, const Vec3& value);
  10. void setUniformVec3v(const std::string& uniformName, ssize_t size, const Vec3* pointer);
  11. void setUniformVec4(const std::string& uniformName, const Vec4& value);
  12. void setUniformVec4v(const std::string& uniformName, ssize_t size, const Vec4* pointer);
  13. void setUniformMat4(const std::string& uniformName, const Mat4& value);
  14. void setUniformCallback(const std::string& uniformName, const std::function<void(GLProgram*, Uniform*)> &callback);
  15. void setUniformTexture(const std::string& uniformName, Texture2D *texture);
  16. void setUniformInt(GLint uniformLocation, int value);
  17. void setUniformFloat(GLint uniformLocation, float value);
  18. void setUniformFloatv(GLint uniformLocation, ssize_t size, const float* pointer);
  19. void setUniformVec2(GLint uniformLocation, const Vec2& value);
  20. void setUniformVec2v(GLint uniformLocation, ssize_t size, const Vec2* pointer);
  21. void setUniformVec3(GLint uniformLocation, const Vec3& value);
  22. void setUniformVec3v(GLint uniformLocation, ssize_t size, const Vec3* pointer);
  23. void setUniformVec4(GLint uniformLocation, const Vec4& value);
  24. void setUniformVec4v(GLint uniformLocation, ssize_t size, const Vec4* pointer);
  25. void setUniformMat4(GLint uniformLocation, const Mat4& value);
  26. void setUniformCallback(GLint uniformLocation, const std::function<void(GLProgram*, Uniform*)> &callback);
  27. void setUniformTexture(GLint uniformLocation, Texture2D *texture);
  28. }

4、更新attribute值(状态)

  1. class CC_DLL GLProgramState : public Ref
  2. {
  3. // 设置vertex attribute value,见VertexAttribValue
  4. // 注意,不会立即生效,而是设置到了状态中。
  5. void setVertexAttribCallback(const std::string& name, const std::function<void(VertexAttrib*)> &callback);
  6. void setVertexAttribPointer(const std::string& name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid *pointer);
  7. }

5、apply:值更改生效

  1. class CC_DLL GLProgramState : public Ref
  2. {
  3. // 调用下面的3个apply,modelView是MV
  4. void apply(const Mat4& modelView);
  5. // 1、glUseProgram();
  6. // 2、更新所有内置uniform的值,modelView为MV。
  7. // 注意哦,没有更新attribute
  8. void applyGLProgram(const Mat4& modelView);
  9. // 使所有attribute的通用顶点属性生效,调用glVertexAttribPointer
  10. // applyAttribFlags: 在这之前是否需要先调用glEnableVertexAttribArray/glDisableVertexAttribArray
  11. void applyAttributes(bool applyAttribFlags = true);
  12. // 使所有uniform值的更改生效,调用glUniform()
  13. void applyUniforms();
  14. }

四、AutoBindingResolver(待完成)