zoukankan      html  css  js  c++  java
  • cocos2d-js Shader系列2:在cc.Sprite上使用Shader(黑白、灰度、造旧效果)

    在Sprite中使用Shader做特殊的颜色处理比较简单,只需要把Shader程序绑定到Sprite上即可:

    sprite.shaderProgram = alphaTestShader;

    Cocos2d内置了一些Shader,详细可以看代码:

    Image(40)

    其中,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;
    " : "precision mediump float;
    "; 
            source = "precision highp float;        
    " 
                + "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;        
    " 
                + "//CC INCLUDES END                
    " + 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:
    " + this._glContext.getShaderSource(shader)); 
                if (type == this._glContext.VERTEX_SHADER) 
                    cc.log("cocos2d: 
    " + this.vertexShaderLog()); 
                else 
                    cc.log("cocos2d: 
    " + 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一样。

    Image(41)

    (绿色球就是原图,上下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; 
    " 
            + "attribute vec2 a_texCoord; 
    " 
            + "varying mediump vec2 v_texCoord; 
    " 
            + "void main() 
    " 
            + "{ 
    " 
            + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  
    " 
            + "    v_texCoord = a_texCoord; 
    " 
            + "}", 
        GRAY_SCALE_FRAGMENT_SHADER: 
            "varying vec2 v_texCoord;   
    " 
            + "uniform sampler2D CC_Texture0; 
    " 
            + "void main() 
    " 
            + "{  
    " 
            + "    vec4 texColor = texture2D(CC_Texture0, v_texCoord);  
    " 
            + "    float gray = texColor.r * 0.299 + texColor.g * 0.587 + texColor.b * 0.114; 
    " 
            + "    gl_FragColor = vec4(gray, gray, gray, texColor.a);  
    " 
            + "}", 
        SEPIA_FRAGMENT_SHADER: 
            "varying vec2 v_texCoord;   
    " 
            + "uniform sampler2D CC_Texture0; 
    " 
            + "uniform float u_degree; 
    " 
            + "void main() 
    " 
            + "{  
    " 
            + "    vec4 texColor = texture2D(CC_Texture0, v_texCoord);  
    " 
            + "    float r = texColor.r * 0.393 + texColor.g * 0.769 + texColor.b * 0.189; 
    " 
            + "    float g = texColor.r * 0.349 + texColor.g * 0.686 + texColor.b * 0.168; 
    " 
            + "    float b = texColor.r * 0.272 + texColor.g * 0.534 + texColor.b * 0.131; 
    " 
            + "    gl_FragColor = mix(texColor, vec4(r, g, b, texColor.a), u_degree);  
    " 
            + "}", 
        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; 
        } 
    };
  • 相关阅读:
    php多态
    ssl certificate problem: self signed certificate in certificate chain
    test plugin
    open specific port on ubuntu
    junit vs testng
    jersey rest service
    toast master
    use curl to test java webservice
    update folder access
    elk
  • 原文地址:https://www.cnblogs.com/kenkofox/p/4074047.html
Copyright © 2011-2022 走看看