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: function (shader, type, source) {
        if (!source || !shader)
            return false;
        //var preStr = (type == this._glContext.VERTEX_SHADER) ? "precision highp float;\n" : "precision mediump float;\n";
        source = "precision highp float;        \n"
            + "uniform mat4 CC_PMatrix;         \n"
            + "uniform mat4 CC_MVMatrix;        \n"
            + "uniform mat4 CC_MVPMatrix;       \n"
            + "uniform vec4 CC_Time;            \n"
            + "uniform vec4 CC_SinTime;         \n"
            + "uniform vec4 CC_CosTime;         \n"
            + "uniform vec4 CC_Random01;        \n"
            + "//CC INCLUDES END                \n" + source;
        this._glContext.shaderSource(shader, source);
        this._glContext.compileShader(shader);
        var status = this._glContext.getShaderParameter(shader, this._glContext.COMPILE_STATUS);
        if (!status) {
            cc.log("cocos2d: ERROR: Failed to compile shader:\n" + this._glContext.getShaderSource(shader));
            if (type == this._glContext.VERTEX_SHADER)
                cc.log("cocos2d: \n" + this.vertexShaderLog());
            else
                cc.log("cocos2d: \n" + this.fragmentShaderLog());
        }
        return ( status == 1 );
    }

另外,绑定到sprite之后,cocos2d会自动设置一些值,我们只需要事先做个绑定即可,而这个绑定操作,也是有友好封装的。具体可以顺藤摸瓜看代码。

                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);

在sprite上做效果,无非就是一些颜色变换或者说是滤镜而已。由于cocos没有原生的滤镜,不像flash那么方便,那么我们就要自己动手丰衣足食了。

下边实现两个灰度和造旧sepia的效果,类似Flash的ShaderFilter一样。

(绿色球就是原图,上下2个小球分别用不同的sepia参数得到的造旧效果)

var sugar4 = Sugar.create(0,0,2);
        sugar4.x = size.width/4;
        sugar4.y = size.height/1.5;
        this.addChild(sugar4);
        sugar4.scale = 3;
        var sugar = Sugar.create(0,0,2);
        sugar.x = size.width/2;
        sugar.y = size.height/2;
        this.addChild(sugar);
        sugar.scale = 3;
        var sugar2 = Sugar.create(0,0,2);
        sugar2.x = size.width/3;
        sugar2.y = size.height/3;
        this.addChild(sugar2);
        sugar2.scale = 2;
        var sugar3 = Sugar.create(0,0,2);
        sugar3.x = size.width/3*2;
        sugar3.y = size.height/3*2;
        this.addChild(sugar3);
        sugar3.scale = 2;
        Filter.grayScale(sugar);
        Filter.sepia(sugar2, 0.5);
        Filter.sepia(sugar3, 0.9);

Filter类的代码:

/**
* Created by kenkozheng on 2014/11/4.
*/
/**
* 只能用于控制Sprite的色调等,目标是实现类似Flash的内置基本滤镜
* 静态类
*/
var Filter = {
    DEFAULT_VERTEX_SHADER:
        "attribute vec4 a_position; \n"
        + "attribute vec2 a_texCoord; \n"
        + "varying mediump vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "    v_texCoord = a_texCoord; \n"
        + "}",
    GRAY_SCALE_FRAGMENT_SHADER:
        "varying vec2 v_texCoord;   \n"
        + "uniform sampler2D CC_Texture0; \n"
        + "void main() \n"
        + "{  \n"
        + "    vec4 texColor = texture2D(CC_Texture0, v_texCoord);  \n"
        + "    float gray = texColor.r * 0.299 + texColor.g * 0.587 + texColor.b * 0.114; \n"
        + "    gl_FragColor = vec4(gray, gray, gray, texColor.a);  \n"
        + "}",
    SEPIA_FRAGMENT_SHADER:
        "varying vec2 v_texCoord;   \n"
        + "uniform sampler2D CC_Texture0; \n"
        + "uniform float u_degree; \n"
        + "void main() \n"
        + "{  \n"
        + "    vec4 texColor = texture2D(CC_Texture0, v_texCoord);  \n"
        + "    float r = texColor.r * 0.393 + texColor.g * 0.769 + texColor.b * 0.189; \n"
        + "    float g = texColor.r * 0.349 + texColor.g * 0.686 + texColor.b * 0.168; \n"
        + "    float b = texColor.r * 0.272 + texColor.g * 0.534 + texColor.b * 0.131; \n"
        + "    gl_FragColor = mix(texColor, vec4(r, g, b, texColor.a), u_degree);  \n"
        + "}",
    programs:{},
    /**
     * 灰度
     * @param sprite
     */
    grayScale: function (sprite) {
        var program = Filter.programs["grayScale"];
        if(!program){
            program = new cc.GLProgram();
            program.initWithVertexShaderByteArray(Filter.DEFAULT_VERTEX_SHADER, Filter.GRAY_SCALE_FRAGMENT_SHADER);
            program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);        //cocos会做初始化的工作
            program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
            program.link();
            program.updateUniforms();
            Filter.programs["grayScale"] = program;
        }
        gl.useProgram(program.getProgram());
        sprite.shaderProgram = program;
    },
    /**
     * 造旧
     * @param sprite
     * @param degree 旧的程度 0~1
     */
    sepia: function (sprite, degree) {
        var program = Filter.programs["sepia"+degree];
        if(!program){
            program = new cc.GLProgram();
            program.initWithVertexShaderByteArray(Filter.DEFAULT_VERTEX_SHADER, Filter.SEPIA_FRAGMENT_SHADER);
            program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);        //cocos会做初始化的工作
            program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
            program.link();
            program.updateUniforms();
            var degreeLocation = program.getUniformLocationForName("u_degree");
            program.setUniformLocationF32(degreeLocation, degree);
            Filter.programs["sepia"+degree] = program;
        }
        gl.useProgram(program.getProgram());
        sprite.shaderProgram = program;
    }
};
时间: 2024-10-11 04:33:09

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

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

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

(转)Cocos2dx-JS 在 Sprite 上使用 Shader

//例如如下一个简单的变色程序,蓝色变红色 ,js 代码: var url = "res/sb.jpg";   var sp = new cc.Sprite(url);   sp.setAnchorPoint(0,0);   this.addChild(sp);   this.shader = new cc.GLProgram("res/Shaders/example_Flower.vsh", "res/Shaders/example_Flower.fsh

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

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

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

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

cocos2d js 利用texture packer生成sprite

cc.spriteFrameCache.addSpriteFrames(res.winLose_plist,res.winLose_png); var frame = cc.spriteFrameCache.getSpriteFrame("win-lost-bei.png"); var backHighlightSprite = cc.Sprite.createWithSpriteFrame(frame); backHighlightSprite.setPosition(100, 10

cocos2d lua绑定感悟---像cc.Sprite,cc.Director这些是如何识别的

其实自从打开GameScene.lua文件以来,我一直都很想搞清楚的一个问题就是cc.Sprite这些是如何识别的.其实第一反应肯定就是:它肯定是一个全局变量,要不然怎么调用create方法呢.先不考究cocos的C++类方法是如何绑定到lua的,我就是想知道这个全局变量是什么时候注册的? 知道一点lua知识的都知道 lua里面的全局变量会保存到一个全局表_G中去,问题就转换为了 什么时候向_G中注册的?在使用cc.Sprite的create之前,我好像没有没有在lua中定义cc.Sprite这

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 ClippingNode 制作标题闪亮特效

1.效果图: 之前在<Android 高仿 IOS7 IPhone 解锁 Slide To Unlock>中制作了文字上闪亮移动的效果,这次我们来看下怎样在cocos2d js 中做出类似的效果. 顺便给我公司的游戏打下广告.https://itunes.apple.com/cn/app/kuang-zhan-san-guo/id691116157? mt=8 2.效果原理 很easy.就是一张白色两边羽化的图片在标题上从左往右移动.可是普通的移动会穿帮.我们须要以标题作为模板来截取白色的图片