Cocos Creator 实现按钮图标的流光特效(Shader)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ST_DarkMoon/article/details/77977867

Cocos Creator 实现按钮图标的流光特效(Shader)

cocos creator如何使用shader可以参考:


代码

流光效果脚本组件代码:

/*************************************************************
*  流光效果 shader挂件
*  -----------------------------------------------------------
*  author : saint       |  email : [email protected]
*
*  create : 2017/09/12
*  -----------------------------------------------------------
*  
*  CopyRight(C) 2017-   |  All Right Reserved 
**************************************************************/
let vert_file = require("../ShaderFile/bright_vert.js");
let frag_file = require("../ShaderFile/bright_frag.js");

cc.Class({
    extends : cc.Component,

    properties : {
        _time : 0.0,

    },

    onLoad : function(){

        this._time = 0;
        this._sin = 0;
        this._use();
    },

    _use : function(){
        this._program = new cc.GLProgram();
        this._program.initWithVertexShaderByteArray( vert_file, frag_file);
        // 添加程序属性至GLSL中
        this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_POSITION, cc.macro.VERTEX_ATTRIB_POSITION);
        this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_COLOR, cc.macro.VERTEX_ATTRIB_COLOR);
        this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_TEX_COORD, cc.macro.VERTEX_ATTRIB_TEX_COORDS);

        this._program.link();
        this._program.updateUniforms();
        this._program.use();
        this.updateGLParameters();

        this._program.setUniformLocationWith1f(this._program.getUniformLocationForName("sys_time"),this._time);
        this.setProgram(this.node._sgNode, this._program);
    },

    update : function( dt){

        this._time += 2*dt;
        if(this._program){
            this._program.use();
            this._sin = Math.sin(this._time);
            if(this._sin > 0.99){
                this._sin = 0;
                this._time = 0;
            }        
                 this._program.setUniformLocationWith1f(this._program.getUniformLocationForName("sys_time"), this._sin);
        }
    },

    updateGLParameters : function(){
        this._time = Math.sin(Date.now());
    },

    setProgram : function(node, program){
        node.setShaderProgram(program);  

        var children = node.children;
        if (!children)
            return;
        for (var i = 0; i < children.length; i++)
        {
            this.setProgram(children[i], program);
        }
    },
});

对应的顶点着色器(bright_vert.js)代码:

module.exports =
`
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
varying vec2 v_texCoord;
varying vec4 v_fragmentColor;
void main()
{
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}
`

对应的片元着色器(bright_frag.js)代码:

module.exports = 
`
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float sys_time;
void main()
{
    vec4 src_color = texture2D(CC_Texture0, v_texCoord).rgba;

    float width = 0.2;       //流光的宽度范围 (调整该值改变流光的宽度)
    float start = sys_time;  //流光的起始x坐标
    float strength = 0.01;   //流光增亮强度   (调整该值改变流光的增亮强度)
    float offset = 0.2;      //偏移值         (调整该值改变流光的倾斜程度)
    //if( start <= v_texCoord.x && v_texCoord.x <= (start + width))
    if( v_texCoord.x < (start - offset * v_texCoord.y) &&  v_texCoord.x > (start - offset * v_texCoord.y - width))
    {

        float strength = 0.01;
        vec3 improve = strength * vec3(255, 255, 255);
        vec3 result = improve * vec3( src_color.r, src_color.g, src_color.b);
        gl_FragColor = vec4(result, src_color.a);

    }else{
        gl_FragColor = src_color;
    }
}
`

需要注意的是:

  • 1.这是h5调用 如要在原生使用需要进行平台判定并进行差异操作.具体可参考上面的 [ Creator 中使用的 Shader效果控件 ]
  • 2.如果挂载对象为一个具有button组件的节点.则当点击或者鼠标移动上去时.会使我们自定义的shader失效。这是button组件的内部封装导致的。在引擎源码CocosCreator\resources\engine\cocos2d\core\components\CCButton.js的_updateDisabledState函数中将将shader重置为默认shader的了,要使其生效可能需要对其进行修改。
_updateDisabledState: function () {
        if(this._sprite) {
            this._sprite._sgNode.setState(0); // setState(0)会重置shader。可将其注释或者其他操作。
        }
        if(this.enableAutoGrayEffect && this.transition !== Transition.COLOR) {
            if(!(this.transition === Transition.SPRITE && this.disabledSprite)) {
                if(this._sprite && !this.interactable) {
                    this._sprite._sgNode.setState(1);
                }
            }
        }
    }

(修改源码后可参考 [ cocos creator 修改源码教程并使浏览器预览生效(js) ]重新编译使得修改生效)

猜你喜欢

转载自blog.csdn.net/ST_DarkMoon/article/details/77977867