cocos2d Shader系列1:cocos2d-js Shader和OpenGL ES2.0

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%3D1

http://www.opengpu.org/bbs/forum.php?mod=viewthread&tid=7376&extra=page%3D1

cocos2d的Shader步骤还是类似的:

1、编写vertex shader和fragment shader

2、定义vertex buffer(需要绘制的顶点区域)

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、vertex buffer

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、绑定纹理

        //定义纹理
        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写法

precision lowp float;
varying vec2 v_texCoord;
uniform sampler2D CC_Texture0;

void main() {
    gl_FragColor = texture2D(CC_Texture0, v_texCoord);
}

4、设置shader参数

//在初始化的时候记录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

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

时间: 2024-08-18 11:42:01

cocos2d Shader系列1:cocos2d-js Shader和OpenGL ES2.0的相关文章

OpenGL ES2.0 shader内部return语句返回失败和数据精度丢失,花屏问题

最近客户反映遇到我们的产品一个很奇怪的问题,字体花屏现象 shader使用两张纹理贴图(图标和文字纹理)做多重纹理映射时,部分手机出现花屏现象,dicard后不起作用,后面的语句继续执行 添加了return语句同样问题 纠结了两三天,今天终于查出原因,如题 shader内部return语句返回失败和数据精度丢失,大部分手机一切正常. 问题机器型号ID: HM2013022 ANDROID.VERSION.RELEASE: 4.2.1 GL_VERSION: OpenGL ES 2.0 build

cocos2d-js Shader系列4:Shader、GLProgram在jsb(native、手机)和html5之间的兼容问题。cocos2d-js框架各种坑。

为了让jsb也能顺利跑起滤镜效果,在手机侧折腾了2天,因为每次在真机上运行总要耗那么半分钟,而且偶尔还遇到apk文件无法删除导致运行失败的情况. 这个调试起来,实在让人烦躁加沮丧. 还好,测试上百轮,翻jsb代码+各种猜测实验之后,终于顺利的把前3个系列的例子都通通在Android上跑起来了,也算是把兼容问题调通了. 如下图所示,右上角的小图是多纹理效果,通过扩展cc.Node自行控制绘制顶点实现的:下方的两个小图是普通的cc.Sprite,对其加入了shaderProgram 总结一下,这里有

cocos2d-js Shader系列3:多重纹理 multiple textures multiple samplers

上一篇,我们学习了怎么便捷的控制sprite的颜色,而这个都是默认一个texture的,如果要实现类似mask的效果,或者更个性化的多纹理效果,怎么实现呢? 这就是这一节需要介绍的内容. 例如上图的效果,下方2个球是原图,而上方的图就是由2个球通过某个公式合成的效果了.这里重点不是怎么合成,而是怎么把多个纹理推送到fragment shader中. 相信大家都会想到,首先需要在fragment shader中添加多一个Sample2D: uniform sampler2D CC_Texture0

cocos2d-js Shader系列2:在cc.Sprite上使用Shader(黑白、灰度、造旧效果)

在Sprite中使用Shader做特殊的颜色处理比较简单,只需要把Shader程序绑定到Sprite上即可: sprite.shaderProgram = alphaTestShader; Cocos2d内置了一些Shader,详细可以看代码: 其中,CCShaderCache缓存了一些Shader实例,而GLProgram则对gl的api做了简单的封装让接口更友好. 需要注意的是,使用GLProgram编译shader程序时,cocos2d会自动加入了一些参数. _compileShader:

解读Unity中的CG编写Shader系列一

CG=C for Graphics  用于计算机图形编程的C语言超集 前提知识点: 1.CG代码必须用 CGPROGRAM ... ENDCG括起来 2.顶点着色器与片段着色器的主函数名称可随意,但需要再#pragma vert 与#pragma fragment中声明并且与主函数名完全匹配,shader才会找到入口 3.float4是一种压缩数组,float4 vert与float vert[4]严格意义上讲不同,虽然都是存放4个float,但float4作为向量类型做点乘.内积等处理更快速

解读Unity中的CG编写Shader系列八(多光源漫反射)

转自http://www.itnose.net/detail/6117338.html 前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下我们的物体表面的漫反射强度如何叠加在一起呢?前文打的tag "LightMode"="ForwardBase"又是什么意思呢? Unity内置的DiffuseShader,也就是我们创建一个Material出来时默认的Shader也是多光源的,所以这篇文章完成的shad

解读Unity中的CG编写Shader系列四——unity中的圆角矩形shader

上篇文章中我们掌握了表面剔除和剪裁模式 这篇文章将利用这些知识实现一个简单的,但是又很常用的例子:把一张图片做成圆角矩形 例3:圆角矩形Shader 好吧我承认在做这个例子的时候走了不少弯路,由于本人对矩阵的知识掌握已经悉数还给老师,所以一开始用了一些笨办法计算圆角矩形区域. 我们知道TEXTCOORD0是一个以对象为坐标系的坐标,并且范围在该坐标的第一象限,取值为(0,0)到(1,1) 那么我们把每一张图片都看做一张1X1大小的矩形 我们要在1X1大小的矩形中擦除4个角,应该是这样: 以左上角

解读Unity中的CG编写Shader系列8——多光源漫反射

前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下我们的物体表面的漫反射强度如何叠加在一起呢?前文打的tag "LightMode"="ForwardBase"又是什么意思呢? Unity内置的DiffuseShader,也就是我们创建一个Material出来时默认的Shader也是多光源的,所以这篇文章完成的shader与默认的diffuse shader基本效果一致. 首先引入几个概念 渲染路径 Re

【Unity Shaders】Mobile Shader Adjustment —— 为手机定制Shader

本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源(当然你也可以从官网下载). ========================================== 分割线 ========================================== 写在前面 在上一篇里,我们学习了一些技巧来初步优化Shader.这次,我们学习更多的技术来实现一个更