一、GLProgram Shader

下面是是最简单着色器。

  1. #version 200 // 版本声明
  2. uniform vec4 color; // uniform 声明
  3. #define MOTHER_FUCKER 1 // 宏定义
  4. attribute vec4 a_position; // 顶点属性声明
  5. void main()
  6. {
  7. ...... // 函数体
  8. }

cocos自己封装了一个GLProgram类,用于构建shader Program。它将一个着色器的代码划分成以下几个部分:

  • header(自定义)
    • 版本声明,如#version 100
    • 精度声明,如precision mediump float
  • 内置uniforms变量
    • 指的cocos预定义的,并不是glsl内置的
  • 宏定义(自定义)
  • source
    • uniforms(**自定义**)
      • 注意不要和内置重叠
    • 顶点属性
      • 包含内置、自定义,注意不要重叠
    • 其他全局定义(自定义)
    • main

详情见以下:

  1. // ****************************************************
  2. // ************ 一、shader header
  3. // ****************************************************
  4. if 自定义header:
  5. ......; // 使用自定义的header
  6. else: // 没有自定义,则默认采用以下规则:
  7. if CC_PLATFORM_WINRT
  8. if vertex_shader
  9. precision mediump float;
  10. precision mediump int;
  11. else
  12. precision mediump float;
  13. precision mediump int;
  14. if CC_PLATFORM_ANDROID
  15. #version 100
  16. precision highp float;
  17. precision highp int;
  18. if not CC_PLATFORM_WIN32 and not CC_PLATFORM_LINUX and not CC_PLATFORM_MAC
  19. if vertex_shader:
  20. precision highp float;
  21. precision highp int;
  22. else
  23. precision mediump float;
  24. precision mediump int;
  25. // ****************************************************
  26. // ************ 二、内置uniforms,
  27. // ****************************************************
  28. // 这些是会自动添加的,没有使用到的在link阶段将被优化掉
  29. uniform vec4 CC_AmbientColor; //
  30. uniform mat4 CC_PMatrix; // 投影矩阵,如果顶点坐标已经是世界坐标了就用这个。
  31. uniform mat4 CC_MultiViewPMatrix[4]; // 多视图的投影矩阵
  32. uniform mat4 CC_MVMatrix; // ModelView矩阵,简称MV矩阵
  33. uniform mat4 CC_MVPMatrix; // ModelViewProjection矩阵,简称MVP矩阵
  34. uniform mat4 CC_MultiViewMVPMatrix[4]; // 多视图的MVP矩阵
  35. uniform mat3 CC_NormalMatrix; // 法线矩阵:https://www.yuque.com/tvvhealth/cs/yavt4r#wl0P2
  36. // time = 总运行时间 = totalFrames x interval
  37. uniform vec4 CC_Time; // [0]:time/10; [1]:time; [2]:time*2; [3]:time*4
  38. uniform vec4 CC_SinTime; // [0]:time/8; [1]:time/4; [2]:time/2; [3]:sin(time)
  39. uniform vec4 CC_CosTime; // [0]:time/8; [1]:time/4; [2]:time/2; [3]:cos(time)
  40. uniform vec4 CC_Random01; // [0]:0~1; [1]:0~1; [2]:0~1; [3]:0~1;
  41. uniform sampler2D CC_Texture0; //
  42. uniform sampler2D CC_Texture1; //
  43. uniform sampler2D CC_Texture2; //
  44. uniform sampler2D CC_Texture3; //
  45. // ****************************************************
  46. // ************ 三、宏定义
  47. // ****************************************************
  48. // 自定义的,将字符串按一下规则解析:
  49. // 将字符串:FUCK;SHIT 1;MOTHER 1;,转换成下面的宏定义
  50. // #define FUCK
  51. // #define SHIT 1
  52. // #define MOTHER 1
  53. // ****************************************************
  54. // ************ 四、source
  55. // ****************************************************
  56. // 这部分都要自定义,但是有一些规则,不能随便写。
  57. //********************* 自定义uniforms
  58. uniform vec3 motherfucker; //自定义uniforms,注意不要和上面内置的重叠,没有使用到的在link阶段将被优化掉
  59. ......
  60. //********************* 顶点属性attributes,没有使用到的在link阶段将被优化掉
  61. // 以下是cocos固定的内置顶点属性,不会自定添加要我们自己写
  62. attribute vec4 a_position; // location=0,对应枚举值:VERTEX_ATTRIB_POSITION=0
  63. attribute vec4 a_color; // location=1,对应枚举值:VERTEX_ATTRIB_COLOR=1
  64. attribute vec2 a_texCoord; // location=2,对应枚举值:VERTEX_ATTRIB_TEX_COORD=2
  65. attribute vec2 a_texCoord1; // location=3,对应枚举值:VERTEX_ATTRIB_TEX_COORD1=3
  66. attribute vec2 a_texCoord2; // location=4,对应枚举值:VERTEX_ATTRIB_TEX_COORD2=4
  67. attribute vec2 a_texCoord3; // location=5,对应枚举值:VERTEX_ATTRIB_TEX_COORD3=5
  68. attribute vec3 a_normal; // location=6,对应枚举值:VERTEX_ATTRIB_NORMAL=6
  69. attribute vec4 a_blendWeight; // location=7,对应枚举值:VERTEX_ATTRIB_BLEND_WEIGHT=7
  70. attribute vec4 a_blendIndex; // location=8,对应枚举值:VERTEX_ATTRIB_BLEND_INDEX=8
  71. attribute vec3 a_tangent; // location=9,对应枚举值:VERTEX_ATTRIB_TANGENT=9
  72. attribute vec3 a_binormal; // location=10,对应枚举值:VERTEX_ATTRIB_BINORMAL=10
  73. attribute in vec3 shit; // 这里是我们自定义的顶点属性
  74. ......;
  75. ......; // 这里是我们自定义的其他一些全局定义
  76. void main() { // main函数体。
  77. ......
  78. }

二、数据结构

  1. struct Uniform // 保存uniform变量除值以外的信息
  2. {
  3. GLint location; // 位置值,glGetUniformLocation得到
  4. GLenum type; // 分量的数据类型,GL_FLOAT、GL_UNSIGNED_BYTE等。
  5. GLint size; // 分量数量,0~4,size * type = 数据类型大小
  6. string name; // 变量名称
  7. };
  8. struct VertexAttrib // 保存顶点属性除值以外的信息
  9. {
  10. GLuint index; // location,glGetAttribLocation的返回值
  11. GLenum type; // 分量数据类型,GL_FLOAT、GL_UNSIGNED_BYTE等。
  12. GLint size; // 分量数量,0~4,size * type = 数据类型大小
  13. string name; // 变量名称
  14. };
  15. class CC_DLL GLProgram : public Ref
  16. {
  17. GLuint _program; // GL program对象句柄。
  18. GLuint _vertShader; // 顶点着色器句柄
  19. GLuint _fragShader; // 片段着色器句柄
  20. GLint _builtInUniforms[UNIFORM_MAX]; // cocos内置的uniform全局变量的location,并不是glsl内置的
  21. // key: index,枚举实现,唯一识别该变量
  22. // value: location,该变量的位置值。
  23. unordered_map<std::string, Uniform> _userUniforms;
  24. // link之后,也就是active的非cocos内置的uniform变量,link会把代码中只定义但没有被使用的部分优化掉
  25. // cocos内置的都是CC_开头的。
  26. // key: uniform name
  27. // value: uniform除了值的所有信息,如name,location,type,size
  28. unordered_map<std::string, VertexAttrib> _vertexAttribs;
  29. // link之后,也就是active的attribute变量
  30. // key: attribute name
  31. // value: attribute除了值的所有信息,如index, name,type,size
  32. unordered_map<GLint, std::pair<GLvoid*, unsigned int>> _hashForUniforms;
  33. // 在C++端缓存了一份所有uniform变量的值,目的是在更新uniform时可以先和缓存比较,看值是否有改变,如果没有则不执行gl call更新
  34. // key: uniform location
  35. // value: 是一个pair,
  36. // frist: 存储uniform value的内存,动态分配,用于保存可能频繁更新的uniform值。
  37. // second: 内存大小,也是uniform数据类型大小。
  38. Director* _director; // cached director pointer for calling
  39. UniformFlags _flags; // 标识用到了哪些内置的uniforms,下面的位域bitfield实现。
  40. struct UniformFlags {
  41. unsigned int usesTime:1; // 占1it,以下相同,总共1byte = 8bit
  42. unsigned int usesNormal:1;
  43. unsigned int usesMVP:1;
  44. unsigned int usesMultiViewMVP:1;
  45. unsigned int usesMV:1;
  46. unsigned int usesP:1;
  47. unsigned int usesMultiViewP:1;
  48. unsigned int usesRandom:1;
  49. UniformFlags() { memset(this, 0, sizeof(*this)); } // 初始都为0
  50. };
  51. };

三、创建

  1. class CC_DLL GLProgram : public Ref
  2. {
  3. // ****************************************
  4. // !!!注意,所有的create方法创建的实例都不会自动缓存到GLProgramCache中。需要手动调用。
  5. // 内置的Shader,则会在初始化的时候就缓存起来了。
  6. // !!!注意,如果我们要直接操作GLProgram对象,务必自己retain起来维护,因为它是一个autorelease对象。
  7. // ****************************************
  8. // 生成一个编译、链接好的GL program,着色器代码内容如下:
  9. // header:默认
  10. // uniforms:内置
  11. // 宏定义:空
  12. // source: vShaderByteArray、fShaderByteArray
  13. static GLProgram* createWithByteArrays(
  14. const GLchar* vShaderByteArray, // 顶点着色器代码
  15. const GLchar* fShaderByteArray); // 片段着色器代码
  16. static GLProgram* createWithFilenames(......); // 文件路径版本,参数相同
  17. // header:默认
  18. // uniforms:内置
  19. // 宏定义:compileTimeDefines
  20. // source: vShaderByteArray、fShaderByteArray
  21. static GLProgram* createWithByteArrays(
  22. const GLchar* vShaderByteArray, // 顶点着色器代码
  23. const GLchar* fShaderByteArray, // 片段着色器代码
  24. const std::string& compileTimeDefines); // 宏定义,格式见上面
  25. static GLProgram* createWithFilenames(......); // 文件路径版本,参数相同
  26. // header:compileTimeHeaders
  27. // uniforms:内置
  28. // 宏定义:compileTimeDefines
  29. // source: vShaderByteArray、fShaderByteArray
  30. static GLProgram* createWithByteArrays(
  31. const GLchar* vShaderByteArray, // 顶点着色器代码
  32. const GLchar* fShaderByteArray, // 片段着色器代码
  33. const std::string& compileTimeHeaders, // 自定义header,见上面
  34. const std::string& compileTimeDefines); // 宏定义,格式见上面
  35. static GLProgram* createWithFilenames(......); // 文件路径版本,参数相同
  36. }

创建过程如下:

  1. GLProgram* GLProgram::createWithByteArrays(
  2. const GLchar* vShaderByteArray, // 顶点着色器代码,source部分,见上面
  3. const GLchar* fShaderByteArray, // 片段着色器代码,source部分,见上面
  4. const std::string& compileTimeHeaders, // header部分,见上面
  5. const std::string& compileTimeDefines) // 宏定义
  6. {
  7. auto ret = new (std::nothrow) GLProgram();
  8. if(ret && ret->initWithByteArrays(vShaderByteArray, // 拼好shader代码,然后编译shader并attch to program
  9. fShaderByteArray,
  10. compileTimeHeaders,
  11. compileTimeDefines))
  12. {
  13. // 1、将source定义的内置attribute,按上面的内置attribute规则build好,name对应的location
  14. // 2、链接gl program
  15. // 3、获取所有active的attributes
  16. // 4、获取所有active的uniforms
  17. ret->link(); // do jobs above。
  18. ret->updateUniforms(); // 获得内置的uniforms,没有active的uniform则更新相应flag
  19. ret->autorelease();
  20. return ret;
  21. }
  22. CC_SAFE_DELETE(ret);
  23. return nullptr;
  24. }

1、initWithByteArrays

  1. // 相关函数源码如下:
  2. bool GLProgram::initWithByteArrays(
  3. const GLchar* vShaderByteArray,
  4. const GLchar* fShaderByteArray,
  5. const std::string& compileTimeHeaders,
  6. const std::string& compileTimeDefines)
  7. {
  8. _program = glCreateProgram(); // create program object
  9. CHECK_GL_ERROR_DEBUG(); // 检查上一次glGetError到现在之间gl调用的log
  10. // 将字符串:FUCK;SHIT 1;MOTHER 1;,转换成下面的宏定义
  11. // #define FUCK
  12. // #define SHIT 1
  13. // #define MOTHER 1
  14. std::string replacedDefines = "";
  15. replaceDefines(compileTimeDefines, replacedDefines); // 插入宏定义,详细见上面。
  16. _vertShader = _fragShader = 0; // shader object id
  17. if (vShaderByteArray) {
  18. if (!compileShader( // 编译并生成一个vertex shader object
  19. &_vertShader, // 保存生成的vertex shader object id
  20. GL_VERTEX_SHADER, // 要生成的是vertex shader object
  21. vShaderByteArray, // source部分:顶点着色器代码
  22. compileTimeHeaders, // header部分
  23. replacedDefines)) { // 宏定义
  24. CCLOG("cocos2d: ERROR: Failed to compile vertex shader");
  25. return false;
  26. }
  27. }
  28. //
  29. ......; // 片段着色器的创建同上,只是source部分不同。
  30. if (_vertShader) {
  31. glAttachShader(_program, _vertShader);
  32. }
  33. CHECK_GL_ERROR_DEBUG();
  34. if (_fragShader) {
  35. glAttachShader(_program, _fragShader);
  36. }
  37. clearHashUniforms(); // 回收之前的uniform变量的值的存储区。
  38. CHECK_GL_ERROR_DEBUG();
  39. return true;
  40. }

2、compileShader

在initWithByteArrays中调用。

  1. // 生成并编译好一个shader
  2. bool GLProgram::compileShader(
  3. GLuint* shader, // 保存shader object id
  4. GLenum type, // GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
  5. const GLchar* source, // source部分
  6. const std::string& compileTimeHeaders, // header部分
  7. const std::string& convertedDefines) // 宏定义部分
  8. {
  9. GLint status;
  10. if (!source)
  11. {
  12. return false;
  13. }
  14. // 实现上面的shader header部分逻辑
  15. std::string headersDef;
  16. if (compileTimeHeaders.empty()) {
  17. #if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
  18. headersDef = (type == GL_VERTEX_SHADER ? "precision mediump float;\n precision mediump int;\n" : "precision mediump float;\n precision mediump int;\n");
  19. // Bugfix to make shader variables types constant to be understood by the current Android Virtual Devices or Emulators. This will also eliminate the 0x501 and 0x502 OpenGL Errors during emulation.
  20. // Changed shader data types mediump to highp to remove possible sprite joggling on some Android phones.
  21. #elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  22. headersDef = "#version 100\n precision highp float;\n precision highp int;\n";
  23. #elif (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_LINUX && CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
  24. headersDef = (type == GL_VERTEX_SHADER ? "precision highp float;\n precision highp int;\n" : "precision mediump float;\n precision mediump int;\n");
  25. #endif
  26. }else{
  27. headersDef = compileTimeHeaders;
  28. }
  29. // shader代码的合成
  30. const GLchar *sources[] = {
  31. headersDef.c_str(), // 1、header部分
  32. COCOS2D_SHADER_UNIFORMS, // 2、内置uniforms,在代码中没有使用的,在link时会被优化掉。
  33. convertedDefines.c_str(), // 3、宏定义
  34. source}; // 4、source部分,attribute变量在这里。
  35. *shader = glCreateShader(type); // 创建一个shader object
  36. glShaderSource( // 写入shader code
  37. *shader, // shader object
  38. sizeof(sources)/sizeof(*sources), // sources的元素个数
  39. sources, // sources
  40. nullptr);
  41. glCompileShader(*shader); // 编译
  42. glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); // 检查编译结果
  43. if (! status) { // 编译出错,获取日志
  44. GLsizei length;
  45. glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length);
  46. GLchar* src = (GLchar *)malloc(sizeof(GLchar) * length);
  47. glGetShaderSource(*shader, length, nullptr, src);
  48. CCLOG("cocos2d: ERROR: Failed to compile shader:\n%s", src);
  49. if (type == GL_VERTEX_SHADER)
  50. {
  51. CCLOG("cocos2d: %s", getVertexShaderLog().c_str());
  52. }
  53. else
  54. {
  55. CCLOG("cocos2d: %s", getFragmentShaderLog().c_str());
  56. }
  57. free(src);
  58. return false;
  59. }
  60. return (status == GL_TRUE);
  61. }

3、link

在createWithByteArrays中调用。

  1. bool GLProgram::link() {
  2. CCASSERT(_program != 0, "Cannot link invalid program");
  3. GLint status = GL_TRUE;
  4. bindPredefinedVertexAttribs(); // 将source中定义的内置attribute,按规则设置好location,见下面源码
  5. glLinkProgram(_program);
  6. // Calling glGetProgramiv(...GL_LINK_STATUS...) will force linking of the program at this moment.
  7. // Otherwise, they might be linked when they are used for the first time. (I guess this depends on the driver implementation)
  8. // So it might slow down the "booting" process on certain devices. But, on the other hand it is important to know if the shader
  9. // linked successfully. Some shaders might be downloaded in runtime so, release version should have this check.
  10. // For more info, see Github issue #16231
  11. glGetProgramiv(_program, GL_LINK_STATUS, &status);
  12. if (status == GL_FALSE)
  13. {
  14. CCLOG("cocos2d: ERROR: Failed to link program: %i", _program);
  15. GL::deleteProgram(_program);
  16. _program = 0;
  17. }
  18. else
  19. {
  20. parseVertexAttribs(); // 见下面源码,获得所有的active的attribute
  21. parseUniforms(); // 见下面源码,获得所有的active的uniform
  22. clearShader();
  23. }
  24. return (status == GL_TRUE);
  25. }
  26. // 将source中定义的内置attribute,按规则设置好location
  27. void GLProgram::bindPredefinedVertexAttribs()
  28. {
  29. static const struct {
  30. const char *attributeName;
  31. int location;
  32. } attribute_locations[] =
  33. {
  34. {GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION},
  35. {GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR},
  36. {GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD},
  37. {GLProgram::ATTRIBUTE_NAME_TEX_COORD1, GLProgram::VERTEX_ATTRIB_TEX_COORD1},
  38. {GLProgram::ATTRIBUTE_NAME_TEX_COORD2, GLProgram::VERTEX_ATTRIB_TEX_COORD2},
  39. {GLProgram::ATTRIBUTE_NAME_TEX_COORD3, GLProgram::VERTEX_ATTRIB_TEX_COORD3},
  40. {GLProgram::ATTRIBUTE_NAME_NORMAL, GLProgram::VERTEX_ATTRIB_NORMAL},
  41. };
  42. // layout(location=0) in vec4 a_position; // location=0,对应枚举值:VERTEX_ATTRIB_POSITION=0
  43. // layout(location=1) in vec4 a_color; // location=1,对应枚举值:VERTEX_ATTRIB_COLOR=1
  44. // layout(location=2) in vec2 a_texCoord; // location=2,对应枚举值:VERTEX_ATTRIB_TEX_COORD=2
  45. // layout(location=3) in vec2 a_texCoord1; // location=3,对应枚举值:VERTEX_ATTRIB_TEX_COORD1=3
  46. // layout(location=4) in vec2 a_texCoord2; // location=4,对应枚举值:VERTEX_ATTRIB_TEX_COORD2=4
  47. // layout(location=5) in vec2 a_texCoord3; // location=5,对应枚举值:VERTEX_ATTRIB_TEX_COORD3=5
  48. // layout(location=6) in vec3 a_normal; // location=6,对应枚举值:VERTEX_ATTRIB_NORMAL=6
  49. const int size = sizeof(attribute_locations) / sizeof(attribute_locations[0]);
  50. for(int i=0; i<size;i++) {
  51. // 指定_program的attribute的location
  52. glBindAttribLocation(_program, attribute_locations[i].location, attribute_locations[i].attributeName);
  53. }
  54. }
  55. void GLProgram::parseVertexAttribs() // 获得所有active的attribute
  56. {
  57. //_vertexAttribs.clear();
  58. // Query and store vertex attribute meta-data from the program.
  59. GLint activeAttributes;
  60. GLint length;
  61. glGetProgramiv(_program, GL_ACTIVE_ATTRIBUTES, &activeAttributes); // the number of active attribute variables for program.
  62. if(activeAttributes > 0)
  63. {
  64. VertexAttrib attribute;
  65. // returns the length of the longest active attribute name for program,
  66. // including the null termination character
  67. glGetProgramiv(_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &length);
  68. if(length > 0) {
  69. GLchar* attribName = (GLchar*) alloca(length + 1);
  70. for(int i = 0; i < activeAttributes; ++i) {
  71. // Query attribute info.
  72. glGetActiveAttrib(_program, i, length, nullptr, &attribute.size, &attribute.type, attribName);
  73. attribName[length] = '\0';
  74. attribute.name = std::string(attribName);
  75. // Query the pre-assigned attribute location
  76. attribute.index = glGetAttribLocation(_program, attribName);
  77. _vertexAttribs[attribute.name] = attribute;
  78. }
  79. }
  80. }
  81. else
  82. {
  83. GLchar ErrorLog[1024];
  84. glGetProgramInfoLog(_program, sizeof(ErrorLog), nullptr, ErrorLog);
  85. CCLOG("Error linking shader program: '%s'\n", ErrorLog);
  86. }
  87. }
  88. void GLProgram::parseUniforms() // 获得所有active的uniforms,和上面同理。
  89. {
  90. //_userUniforms.clear();
  91. // Query and store uniforms from the program.
  92. GLint activeUniforms;
  93. glGetProgramiv(_program, GL_ACTIVE_UNIFORMS, &activeUniforms);
  94. if(activeUniforms > 0)
  95. {
  96. GLint length;
  97. glGetProgramiv(_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &length);
  98. if(length > 0)
  99. {
  100. Uniform uniform;
  101. GLchar* uniformName = (GLchar*)alloca(length + 1);
  102. for(int i = 0; i < activeUniforms; ++i)
  103. {
  104. // Query uniform info.
  105. glGetActiveUniform(_program, i, length, nullptr, &uniform.size, &uniform.type, uniformName);
  106. uniformName[length] = '\0';
  107. // Only add uniforms that are not built-in.
  108. // The ones that start with 'CC_' are built-ins
  109. if(strncmp("CC_", uniformName, 3) != 0) {
  110. // remove possible array '[]' from uniform name
  111. if(length > 3)
  112. {
  113. char* c = strrchr(uniformName, '[');
  114. if(c)
  115. {
  116. *c = '\0';
  117. }
  118. }
  119. uniform.name = std::string(uniformName);
  120. uniform.location = glGetUniformLocation(_program, uniformName);
  121. GLenum __gl_error_code = glGetError();
  122. if (__gl_error_code != GL_NO_ERROR)
  123. {
  124. CCLOG("error: 0x%x uniformName: %s", (int)__gl_error_code, uniformName);
  125. }
  126. assert(__gl_error_code == GL_NO_ERROR);
  127. _userUniforms[uniform.name] = uniform;
  128. }
  129. }
  130. }
  131. }
  132. else
  133. {
  134. GLchar ErrorLog[1024];
  135. glGetProgramInfoLog(_program, sizeof(ErrorLog), nullptr, ErrorLog);
  136. CCLOG("Error linking shader program: '%s'\n", ErrorLog);
  137. }
  138. }

4、updateUniforms

在createWithByteArrays中调用。

  1. // 获得gl program link成功后,active的uniforms
  2. // active的意思就是在代码使用到的uniform变量。
  3. void GLProgram::updateUniforms()
  4. {
  5. // _userUniforms里面其实已经有了,不知道为什么这里还要再gl call,难道这个方法还会被外调?
  6. _builtInUniforms[UNIFORM_AMBIENT_COLOR] = glGetUniformLocation(_program, UNIFORM_NAME_AMBIENT_COLOR);
  7. _builtInUniforms[UNIFORM_P_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_P_MATRIX);
  8. _builtInUniforms[UNIFORM_MULTIVIEW_P_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MULTIVIEW_P_MATRIX);
  9. _builtInUniforms[UNIFORM_MV_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MV_MATRIX);
  10. _builtInUniforms[UNIFORM_MVP_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MVP_MATRIX);
  11. _builtInUniforms[UNIFORM_MULTIVIEW_MVP_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MULTIVIEW_MVP_MATRIX);
  12. _builtInUniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_NORMAL_MATRIX);
  13. _builtInUniforms[UNIFORM_TIME] = glGetUniformLocation(_program, UNIFORM_NAME_TIME);
  14. _builtInUniforms[UNIFORM_SIN_TIME] = glGetUniformLocation(_program, UNIFORM_NAME_SIN_TIME);
  15. _builtInUniforms[UNIFORM_COS_TIME] = glGetUniformLocation(_program, UNIFORM_NAME_COS_TIME);
  16. _builtInUniforms[UNIFORM_RANDOM01] = glGetUniformLocation(_program, UNIFORM_NAME_RANDOM01);
  17. _builtInUniforms[UNIFORM_SAMPLER0] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER0);
  18. _builtInUniforms[UNIFORM_SAMPLER1] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER1);
  19. _builtInUniforms[UNIFORM_SAMPLER2] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER2);
  20. _builtInUniforms[UNIFORM_SAMPLER3] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER3);
  21. // 更新bitfiled,哪些内置uniforms在被使用。
  22. _flags.usesP = _builtInUniforms[UNIFORM_P_MATRIX] != -1;
  23. _flags.usesMultiViewP = _builtInUniforms[UNIFORM_MULTIVIEW_P_MATRIX] != -1;
  24. _flags.usesMV = _builtInUniforms[UNIFORM_MV_MATRIX] != -1;
  25. _flags.usesMVP = _builtInUniforms[UNIFORM_MVP_MATRIX] != -1;
  26. _flags.usesMultiViewMVP = _builtInUniforms[UNIFORM_MULTIVIEW_MVP_MATRIX] != -1;
  27. _flags.usesNormal = _builtInUniforms[UNIFORM_NORMAL_MATRIX] != -1;
  28. _flags.usesTime = (
  29. _builtInUniforms[UNIFORM_TIME] != -1 ||
  30. _builtInUniforms[UNIFORM_SIN_TIME] != -1 ||
  31. _builtInUniforms[UNIFORM_COS_TIME] != -1
  32. );
  33. _flags.usesRandom = _builtInUniforms[UNIFORM_RANDOM01] != -1;
  34. this->use(); // glUseProgram()
  35. // Since sampler most probably won't change, set it to 0,1,2,3 now.
  36. if(_builtInUniforms[UNIFORM_SAMPLER0] != -1)
  37. setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER0], 0); // 更准确的写法应该是GL_TEXTURE0 - GL_TEXTURE0
  38. if(_builtInUniforms[UNIFORM_SAMPLER1] != -1)
  39. setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER1], 1); // 更准确的写法应该是GL_TEXTURE1 - GL_TEXTURE0
  40. if(_builtInUniforms[UNIFORM_SAMPLER2] != -1)
  41. setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER2], 2); // 更准确的写法应该是GL_TEXTURE2 - GL_TEXTURE0
  42. if(_builtInUniforms[UNIFORM_SAMPLER3] != -1)
  43. setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER3], 3); // 更准确的写法应该是GL_TEXTURE3 - GL_TEXTURE0
  44. glGetError(); // 这里为什么又不用宏CHECK_GL_ERROR_DEBUG了,太不专业了。
  45. }

四、获取attribute

  1. class CC_DLL GLProgram : public Ref
  2. {
  3. // 从_vertexAttribs缓存中获取变量名称为name的顶点属性的信息。
  4. // 这个缓存是在link之后建立的。并没有发生GL call
  5. VertexAttrib* getVertexAttrib(const std::string &name);
  6. // 通过GL call 获取变量名称为attributeName的顶点属性的location
  7. GLint getAttribLocation(const std::string &attributeName) const;
  8. }
  9. // *************************** 下面是获取cocos内置attribute的例子
  10. auto program = GLProgram::createWithFilenames(......);
  11. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_COLOR); // attribute vec4 a_color
  12. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_POSITION); // attribute vec4 a_position
  13. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_TEX_COORD); // attribute vec2 a_texCoord
  14. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_TEX_COORD1); // attribute vec2 a_texCoord1
  15. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_TEX_COORD2); // attribute vec2 a_texCoord2
  16. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_TEX_COORD3); // attribute vec2 a_texCoord3
  17. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_NORMAL); // attribute vec3 a_normal
  18. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_BLEND_WEIGHT); // attribute vec4 a_blendWeight
  19. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_BLEND_INDEX); // attribute vec4 a_blendIndex
  20. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_TANGENT); // attribute vec3 a_tangent
  21. program->getVertexAttrib(GLProgram::ATTRIBUTE_NAME_BINORMAL); // attribute vec3 a_binormal

五、获得uniform

  1. class CC_DLL GLProgram : public Ref
  2. {
  3. // 从_userUniforms获取user define的uniform的信息,也即不是cocos 内置的CC_开头的uniform,
  4. // _userUniforms缓存是在link的时候建立的
  5. Uniform* getUniform(const std::string& name);
  6. // 下面这两个是一样的效果,通过GL call获得变量名称为name的uniform的location
  7. // 这源码写的有够随便的。
  8. GLint getUniformLocation(const std::string& name) const;
  9. GLint getUniformLocationForName(const char* name) const;
  10. }
  11. // *************************** 下面是获取cocos内置uniform的例子
  12. auto program = GLProgram::createWithFilenames(......);
  13. // 注意getUniform无法获得cocos内置uniform
  14. program->getUniformLocation(GLProgram::UNIFORM_NAME_AMBIENT_COLOR); // uniform vec4 CC_AmbientColor
  15. program->getUniformLocation(GLProgram::UNIFORM_NAME_P_MATRIX); // uniform mat4 CC_PMatrix
  16. program->getUniformLocation(GLProgram::UNIFORM_NAME_MULTIVIEW_P_MATRIX); // uniform mat4 CC_MultiViewPMatrix[4]
  17. program->getUniformLocation(GLProgram::UNIFORM_NAME_MV_MATRIX); // uniform mat4 CC_MVMatrix
  18. program->getUniformLocation(GLProgram::UNIFORM_NAME_MVP_MATRIX); // uniform mat4 CC_MVPMatrix
  19. program->getUniformLocation(GLProgram::UNIFORM_NAME_MULTIVIEW_MVP_MATRIX); // uniform mat4 CC_MultiViewMVPMatrix[4]
  20. program->getUniformLocation(GLProgram::UNIFORM_NAME_NORMAL_MATRIX); // uniform mat3 CC_NormalMatrix
  21. program->getUniformLocation(GLProgram::UNIFORM_NAME_TIME); // uniform vec4 CC_Time
  22. program->getUniformLocation(GLProgram::UNIFORM_NAME_SIN_TIME); // uniform vec4 CC_SinTime
  23. program->getUniformLocation(GLProgram::UNIFORM_NAME_COS_TIME); // uniform vec4 CC_CosTime
  24. program->getUniformLocation(GLProgram::UNIFORM_NAME_RANDOM01); // uniform vec4 CC_Random01
  25. program->getUniformLocation(GLProgram::UNIFORM_NAME_SAMPLER0); // uniform sampler2D CC_Texture0
  26. program->getUniformLocation(GLProgram::UNIFORM_NAME_SAMPLER1); // uniform sampler2D CC_Texture1
  27. program->getUniformLocation(GLProgram::UNIFORM_NAME_SAMPLER2); // uniform sampler2D CC_Texture2
  28. program->getUniformLocation(GLProgram::UNIFORM_NAME_SAMPLER3); // uniform sampler2D CC_Texture3
  29. program->getUniformLocation(GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE); // uniform vec4 CC_AmbientColor

六、更新uniform

以下是更新program中uniform值的接口,注意这些更新操作都会先和本地缓存的uniform值检查,如果没有改变则不执行glUniform的更新操作。
注意,最好要使用这些方法进行更新,不要自私调用GL CALL,否则会导致uniform值缓存的不同步。

  1. class CC_DLL GLProgram : public Ref
  2. {
  3. // uniform int shit = i1
  4. void setUniformLocationWith1i(GLint location, GLint i1);
  5. // uniform ivec2 shit = ivec2(i1, i2)
  6. void setUniformLocationWith2i(GLint location, GLint i1, GLint i2);
  7. // uniform ivec3 shit = ivec2(i1, i2, i3)
  8. void setUniformLocationWith3i(GLint location, GLint i1, GLint i2, GLint i3);
  9. // uniform ivec4 shit = ivec2(i1, i2, i3, i4)
  10. void setUniformLocationWith4i(GLint location, GLint i1, GLint i2, GLint i3, GLint i4);
  11. // uniform ivec2[] shit
  12. void setUniformLocationWith2iv( GLint location, GLint* ints, unsigned int numberOfArrays);
  13. // uniform ivec3[] shit
  14. void setUniformLocationWith3iv(GLint location, GLint* ints, unsigned int numberOfArrays);
  15. // uniform ivec4[] shit
  16. void setUniformLocationWith4iv(GLint location, GLint* ints, unsigned int numberOfArrays);
  17. // uniform float shit
  18. void setUniformLocationWith1f(GLint location, GLfloat f1);
  19. // uniform vec2 shit
  20. void setUniformLocationWith2f(GLint location, GLfloat f1, GLfloat f2);
  21. // uniform vec3 shit
  22. void setUniformLocationWith3f(GLint location, GLfloat f1, GLfloat f2, GLfloat f3);
  23. // uniform vec4 shit
  24. void setUniformLocationWith4f(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4);
  25. // uniform float[] shit
  26. void setUniformLocationWith1fv(GLint location, const GLfloat* floats, unsigned int numberOfArrays);
  27. // uniform vec2[] shit
  28. void setUniformLocationWith2fv(GLint location, const GLfloat* floats, unsigned int numberOfArrays);
  29. // uniform vec3[] shit
  30. void setUniformLocationWith3fv(GLint location, const GLfloat* floats, unsigned int numberOfArrays);
  31. // uniform vec4[] shit
  32. void setUniformLocationWith4fv(GLint location, const GLfloat* floats, unsigned int numberOfArrays);
  33. // uniform mat2[] shit
  34. void setUniformLocationWithMatrix2fv(GLint location, const GLfloat* matrixArray, unsigned int numberOfMatrices);
  35. // uniform mat3[] shit
  36. void setUniformLocationWithMatrix3fv(GLint location, const GLfloat* matrixArray, unsigned int numberOfMatrices);
  37. // uniform mat4[] shit
  38. void setUniformLocationWithMatrix4fv(GLint location, const GLfloat* matrixArray, unsigned int numberOfMatrices);
  39. void setUniformsForBuiltins(const Mat4 &modelView); // 更新内置uniforms的值
  40. void setUniformsForBuiltins(); // modelView是当前栈顶的MV
  41. }