基础回顾:
cocos2d-x的底层渲染使用openGL ES 2.0,这是一个可编程的渲染管线,cocos已经封装了一套写渲染程序相关的类,这避免了我们在拓展开发时做一些重复的工作,简单介绍一下,这些类有:
1.CCGLProgram
该类封装了glsl program相关的内容,使一些gl变量或者状态值存储在该类中,并提供面向对象的接口操作这些gl变量。
2.CCShaderCache
该类缓存了cocos用到的各种上述program,使需要渲染的对象可以重复使用这些预先加载好的program,而不用重新创建。
3.ccGLStateCache
该文件提供封装了一些gl状态和操作,没有以面向对象的方式提供,但是这些gl操作指令集合的封装使一些操作可以简单调用执行,在这里维护的一些状态值也使得gl的状态机被正确设置,确保后续渲染的正确和有效进行。
流程指令的相关流程和涉及到的gl接口:
1.分别加载和编译vertex shader和fragment shader的源文件(glCreateShader, glShaserSource, glCompileShader)
2.绑定两个shader到同一个program上(glAttachShader)
3.为shader内的attribute绑定特定的index,此index作为handler用于后续gl客户端操作该attribute(glBindAttribLocation, glGetAttribLocation)
4.对program进行连接,正确连接之后原shader可被删除(glLinkProgram, glDeleteShader)
5.得到program连接时,gl为uniform分配的index,此index作为handler用于后续gl客户端操作该uniform(glGetUniformLocation)
6.使用该program做为gl当前的渲染程序(glUseProgram)
7.设置uniform和attribute,传给gl需要渲染的顶点数据(glUniform***, glVertexAttribPointer)
8.all done~执行渲染(glDrawArrays)
上述渲染流程中需要注意的一些地方是:
cocos使用glBindAttribLocation,而不是glGetAttribLocation,因为bind可以使不同program中的attribute拥有相同的index。而且uniform没有提供bind的方式,因为uniform通常作为一些通用的全局值而存在的,这些全局值在不同的渲染program都需要存在(例如MVP矩阵),甚至是保持相同(例如全局光源相关数据),而attribute作为每个program特有的一些数据,使用bind就可以避免需要为每个program里相同的attribute存储不同的index。所以这样做的最终好处是可以对不同program做统一处理。
需要说明的是,attribute使用bind方式,一定要在program绑定之后和连接之前,为这些attribute赋予相应的index。而uniform的get则一定要在连接之后,获取并存储这些index。
另外,使用CCGLProgram的接口编译shader program的时候,cocos会默认给vertex shader和fragment shader源文件前面加上每个cocos渲染程序都需要有的一些uniform变量:
precision highp float;(vertex shader中)/precision mediump float;(fragment shader中)
uniform mat4 CC_PMatrix;
uniform mat4 CC_MVMatrix;
uniform mat4 CC_MVPMatrix;
uniform vec4 CC_Time;
uniform vec4 CC_SinTime;
uniform vec4 CC_CosTime;
uniform vec4 CC_Random01;
这些变量为shader提供了变换矩阵、当前时间和当前时间的三角函数值,随机数。变换矩阵对于当前渲染对象一般是必须的,而后两者可以作为一些变量因子丰富shader的表现。
因为我们拓展的效果类是要用在cocos框架内的,所以也要尽可能的和cocos契合,这样,代码重用和维护都会方便很多。因为很多基本渲染的内容CCSprite都已经有了,所以就直接继承CCsprite吧~,因为要主要是要重写渲染的部分,所以我们重点要重写draw()函数。现在我们就用shader来实现一些游戏中常用到的效果吧~后续的内容都会以上述的作为基础。