cocos2d的Shader也就是差不多直接跟GPU打交道了,跟Flash的Stage3D(AGAL)类似,不过没有AGAL这么恶心,不需要直接编写汇编语言。而Fragment Shader又跟Flash的pixelbender类似。
本文以cocos2d-js为例,但cocos2dx其他版本也是同理的,只是函数名略有不同而已。
当然还是得先复习或者学习一下GPU的原理,至少得知道vertex shader和fragment shader的作用和区别。
详细可以看看大神的说明:
http://www.opengpu.org/bbs/forum.php?mod=viewthread&tid=7550&extra=page=1
http://www.opengpu.org/bbs/forum.php?mod=viewthread&tid=7376&extra=page=1
cocos2d的Shader步骤还是类似的:
1、编写vertex shader和fragment shader
2、定义顶点坐标和纹理坐标
3、定义纹理、绑定纹理
4、设置shader的参数
5、每帧draw的时候,gl.drawArrays推送到GPU绘制
1、Shader语法
语法有点类似Flash的pixelbender,但是一个更完整的C程序,可以按照C程序的语法来编写。main函数最终输出结果到一个指定变量中,都是矢量的点乘、加减等。
vertext shader最后赋值一个vec4给gl_Position,表示该点最终绘制到屏幕上的位置;fragment shader最后赋值vec4给gl_FragColor,表示颜色rgba。
详细介绍:
http://blog.csdn.net/hgl868/article/details/7846269
http://blog.csdn.net/wangyuchun_799/article/details/7770500
attribute、uniform、varying区别:http://blog.csdn.net/jackers679/article/details/6848085
uniform变量是外部application程序传递给(vertex和fragment)shader的变量,类似常量 attribute变量是只能在vertex shader中使用的变量。(它不能在fragment shader中声明attribute变量,也不能被fragment shader中使用) varying变量是vertex和fragment shader之间做数据传递用的。一般vertex shader修改varying变量的值,然后fragment shader使用该varying变量的值。因此varying变量在vertex和fragment shader二者之间的声明必须是一致的。application不能使用此变量。Varying can be used only with the data types float, vec2, vec3, vec4, mat2, mat3, mat4. (arrays of them too.)
2、定义顶点坐标和纹理坐标
代码语言:javascript复制var squareVertexPositionBuffer = this.squareVertexPositionBuffer = gl.createBuffer(); //创建一个buffer,并记录下来,后续每帧draw的时候调用
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer); //绑定位置,后一句bufferData就设置这个位置的数据
vertices = [ //这里是4个顶点
256, 256,
0, 256,
256, 0,
0, 0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
/*
gl.STATIC_DRAW The data store contents are modified once, and used many times as the source for WebGL drawing commands.
gl.DYNAMIC_DRAW The data store contents are repeatedly respecified, and used many times as the source for WebGL drawing commands.
gl.STREAM_DRAW The data store contents are specified once, and used occasionally as the source of a WebGL drawing command.
*/
gl.bindBuffer(gl.ARRAY_BUFFER, null);
3、绑定纹理
代码语言:javascript复制 //定义纹理
var texture = this.my_texture = gl.createTexture();
gl.bindTexture( gl.TEXTURE_2D, texture );
var pixels = new Uint8Array(4096); //正好是32*32的图片,每个像素4个byte
for( var i=0; i<pixels.length; ) {
pixels[i ] = i/4; // Red
pixels[i ] = i/16; // Green
pixels[i ] = i/8; // Blue
pixels[i ] = 255; // Alpha
}
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
//每帧draw之前绑定纹理
gl.bindTexture(gl.TEXTURE_2D, this.my_texture);
对应的fragment shader写法
代码语言:javascript复制precision lowp float;
varying vec2 v_texCoord;
uniform sampler2D CC_Texture0;
void main() {
gl_FragColor = texture2D(CC_Texture0, v_texCoord);
}
4、设置shader参数
代码语言:javascript复制//在初始化的时候记录shader程序,记录参数的入口位置
this.shader = cc.GLProgram.create(vertexShader, framentShader);
this.shader.retain();
this.shader.addAttribute("aVertex", cc.VERTEX_ATTRIB_POSITION); //添加一个新参数到shader中,并指定为第几个
this.shader.link();
this.shader.updateUniforms(); //表示使用cocos2d默认附加的一些参数,其实在_compileShader的时候添加到shader程序的
var program = this.shader.getProgram();
this.uniformCenter = gl.getUniformLocation( program, "center"); //记录Uniform参数入口
this.uniformResolution = gl.getUniformLocation( program, "resolution");
//override原来的draw函数,在每帧draw的时候调用:
this.shader.use();
this.shader.setUniformsForBuiltins(); //如果shader中使用了cocos2d默认附加的一些uniform参数,就需要每帧设置(例如TIME等),具体参数意义参考CCGLProgram.setUniformsForBuiltins
this.shader.setUniformLocationF32( this.uniformCenter, winSize.width/2, winSize.height/2);
this.shader.setUniformLocationF32( this.uniformResolution, 256, 256); //设置uniform参数,CCGLProgram类对opengl底层的接口做了封装。例如这个就是对应uniform2f
gl.bindBuffer(gl.ARRAY_BUFFER, this.squareVertexPositionBuffer);
gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0); //设置attribute参数
参数参考:
http://msdn.microsoft.com/zh-cn/library/ie/dn302460(v=vs.85).aspx
函数第一个参数:表示shader程序的第几个attribute参数
5、draw call
代码语言:javascript复制gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
参数参考:
http://msdn.microsoft.com/zh-cn/library/ie/dn302460(v=vs.85).aspx
http://msdn.microsoft.com/zh-cn/library/ie/dn302395(v=vs.85).aspx
最后附上cocos2dx官方的一些教程:
http://cn.cocos2d-x.org/tutorial/show?id=1336
http://cn.cocos2d-x.org/tutorial/show?id=1337