版权声明:本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名elloop(包含链接)
#前言
本文介绍了cocos2d-x中CCGLProgram这个类, 这篇文章假设读者已经了解OpenGL ES程序的基本渲染流程:顶点和片段着色器的源代码的编写、着色器的创建、program的创建、源代码绑定、编译、链接、OpenGL客户端-服务端传值等。CCGLProgram这个类正是对OpenGL ES渲染流程中涉及到着色器的编译、链接、传值等部分的抽象。
本文先总起介绍CCGLProgram所做的工作,然后分析其源代码中的关键实现,最后给出CCGLProgram的使用实例。
总体上认识CCGLProgram
CCGLProgram, 人如其名,它是一个OpenGL Program,通过一个顶点着色器和一个片段着色器代码(对于不支持shader即时编译功能的显卡,传入编译好的二进制着色器数据)来创建一个CCGLProgram.
CCGLProgram内部做下面这些工作:
-
compileShader方法,内部调用glCreateShader, glShaderSource, glCompileShader等OpenGL API创建建顶点和片段着色器, 并编译
-
调用glCreateProgram等OpenGL API完成program创建
-
link方法调用glLinkProgram完成program的链接
-
use方法调用glUseProgram以启用program
-
定义了8个预定义的uniform,
-
updateUniforms方法,完成预定义的8个uniform的绑定
-
setUniformsForBuiltins方法完成在绘制开始时,给预定义的uniform的传值工作
-
setUniformLocationWith_<n>_[fiv]
系列方法完成客户端数值上传到OpenGL服务器
-
使用一个哈希表m_pHashForUniforms
作为缓存,保存每一个uniform的值,如果不发生变化就不会重复上传该uniform的值到OpenGL服务器
CCGLProgram关键代码分析
成员变量
构造类方法
我还没搞过预编译的shader,主要来说说前两种初始化方法的实现:
辅助类方法
1. 着色器的编译
2. 链接程序
3. use.
在进行绘制之前进行调用
4. uniform缓存检查, 返回false代表不要更新uniform的值
5. log函数
绘制过程相关
**1. 预定义的8个uniform的赋值 **
2. 更新uniform的位置。在创建完program,并且在使用其进行绘制之前,调用此函数来绑定shader中预定义的8个uniform常量
3. 绑定属性变量
4. 上传uniform值
这类函数都是以 setUniformLocationWith开头,先检查uniform缓存,再决定是否需要上传新的uniform值。
CCGLProgram使用实例
在cocos引擎自身中,有一个类对CCGLProgram用的最多,它就是:CCShaderCache
从名字就能知道,这个类专门就是用来缓存shader的,这个shader就是CCGLProgram类型的对象实例。
在第一次获取CCShaderCache这个单例类的示例的时候,会调用下面这个方法:loadDefaultShader(), 它会往字典里存放一些预定以的shader program。
经过:initWithVertexShaderByteArray, link, updateUniforms这三个步骤,CCGLProgram就已经进入就绪状态,可以被用来进行绘制了。
下面来看CCGLProgram在绘制时候的使用,以CCSprite的绘制为例,因为它使用了刚才CCShaderCache中的第一个default shader: kCCShader_PositionTextureColor.
可以看到,在绘制的时候,调用了CCGLProgram的use()和setUniformsForBuiltins()这两个方法。
因此,对CCGLProgram的使用过程可以总结如下:
创建阶段
1. new CCGLProgram()
2. initWithVertexShaderByteArray 或者 initWithVertexShaderFilename 来完成顶点着色器和片段着色器的定义和编译
3. [可选]:如果有的话,绑定自定义的attribute **
**4. link() 链接program
5. updateUniforms 绑定预定义的8个uniform
6. [可选]:如果有的话,绑定自定义的uniform
绘制使用阶段
7. setShaderProgram(program) 设置为活动的program
开始绘制
8. use() 使用program
9. setUniformsForBuiltins() 设置预定义的8个uniform的值 8, 9两步可以用CC_NODE_DRAW_SETUP
这个宏来完成。
10. 其它的对shader中attribute和uniform的操作,这里已经跟CCGLProgram关系不大。
在这里也能看到这篇文章:github博客, CSDN博客, 欢迎访问