分享一个Shader版的CoolDown实现

Laya的Pie做Mask在native下有bug,不能正常显示。就研究了下laya的custom shader,在没有详细文档的情况下搞出来了,但又发现无法在Native下使用。。。真是X了
 既然无法使用,就分享出来,大家有兴趣的看看

正常渲染效果
22222.jpeg

 
alpha遮罩
11111.jpeg

 
用法:

var texture: Laya.Texture = Laya.Loader.getRes("progress.png");
this.spe = new coolDownSprite();
this.spe.init(texture);
//this.spe.initWithoutTexture(128, 128);
this.spe.pos(300, 350);
this.spe.setProgress(this.progress);
Laya.stage.addChild(this.spe);
----------------------源码--------------------------
import Shader = laya.webgl.shader.Shader;

    export class coolDownShader extends Shader {
        /**
         * 当前着色器的一个实例对象。
         */
        public static shader: coolDownShader = new coolDownShader();

        constructor() {
            var vs: string = " \
            attribute vec2 position; \
            attribute vec2 texcoord; \
            attribute vec4 color; \
            uniform vec2 size; \
            uniform mat4 mmat; \
            varying vec2 v_texcoord; \
            varying vec4 v_color; \
            void main(){ \
                vec4 pos =mmat*vec4(position.x,position.y,0,1);\
                gl_Position = vec4((pos.x / size.x - 0.5) * 2.0, (0.5 - pos.y / size.y) * 2.0, pos.z, 1.0);\
                v_color = color;\
                v_texcoord = texcoord;\
            } \
            ";

            var ps: string = " \
            precision mediump float; \
            varying vec2 v_texcoord; \
            varying vec4 v_color; \
            uniform sampler2D texture; \
            uniform float progress;\
            uniform vec4 uv_info; \
            void main(){ \
                vec2 pos = ((v_texcoord-uv_info.xy)/uv_info.zw - vec2(0.5,0.5))*256.0;\
                float radius = length(pos.xy);\
                float angle = -degrees(atan(pos.x, pos.y)) + 180.0;\
                float fa = radians(angle - progress * 360.0) * radius + 1.0;\
                fa = clamp(fa, 0.0, 1.0);\
                vec4 t_color = texture2D(texture, v_texcoord); \
                gl_FragColor = t_color.rgba * v_color.rgba * vec4(1,1,1,fa); \
            }\
            ";

            /*
            var ps: string = " \
            precision mediump float; \
            varying vec2 v_texcoord; \
            varying vec4 v_color; \
            uniform float progress;\
            uniform vec4 uv_info; \
            void main(){ \
                vec2 pos = ((v_texcoord-uv_info.xy)/uv_info.zw - vec2(0.5,0.5))*256.0;\
                float radius = length(pos.xy);\
                float angle = -degrees(atan(pos.x, pos.y)) + 180.0;\
                float fa = radians(angle - progress * 360.0) * radius + 1.0;\
                fa = clamp(fa, 0.0, 1.0);\
                gl_FragColor = v_color.rgba * vec4(1,1,1,fa); \
            }\
            ";
            */
            super(vs, ps, "coolDownShader");
        }
    }
import WebGLContext = laya.webgl.WebGLContext;
    import Value2D = laya.webgl.shader.d2.value.Value2D;
    import CONST3D2D = laya.webgl.utils.CONST3D2D;
    export class coolDownShaderValue extends Value2D {
        public texcoord: any;
        public progress: number;

        public uv_info: Array<any>;
        constructor() {
            super(0, 0);
            this.progress = 0.0;
            this.uv_info = [0.0, 0.0, 1.0, 1.0];
            var len: number = 8 * CONST3D2D.BYTES_PE;
            //设置在shader程序文件里定义的属性的相关描述:[属性长度, 属性类型,false, 属性起始位置索引 * CONST3D2D.BYTES_PE];
            this.position = [2, WebGLContext.FLOAT, false, len, 0];
            this.texcoord = [2, WebGLContext.FLOAT, false, len, 2 * CONST3D2D.BYTES_PE];
            this.color = [4, WebGLContext.FLOAT, false, len, 4 * CONST3D2D.BYTES_PE];
        }
    }
import Sprite = Laya.Sprite;

    export class coolDownSprite extends Sprite {
        /** 顶点缓冲区。      */
        private vBuffer: Laya.VertexBuffer2D;
        /** 片元缓冲区。      */
        private iBuffer: Laya.IndexBuffer2D;
        private vbData: Float32Array;
        private ibData: Uint16Array;
        private iNum: number = 0;
        /** 着色器变量。      */
        private shaderValue: coolDownShaderValue;

        constructor() {
            super();
        }
        /**
         * 初始化此类。
         * @param texture 纹理对象。
         * @param vb 顶点数组。
         * @param ib 顶点索引数组。
         */
        public init(texture: Laya.Texture, vb: Array<number> = null, ib: Array<number> = null): void {
            this.vBuffer = Laya.VertexBuffer2D.create();
            this.iBuffer = Laya.IndexBuffer2D.create();

            this.ibData = null;
            var vbArray: Array<number>;
            var ibArray: Array<number>;

            if (vb) {
                vbArray = vb;
            }
            else {
                vbArray = new Array<number>();
                var texWidth: number = texture.width;
                var texHeight: number = texture.height;

                //定义颜色值,取值范围0~1 浮点。
                const red: number = 1;
                const greed: number = 1;
                const blue: number = 1;
                const alpha: number = 1;

                //在顶点数组中放入4个顶点
                //每个顶点的数据:(坐标X,坐标Y,u,v,R,G,B,A)            
                vbArray.push(0, 0, texture.uv[0], texture.uv[1], red, greed, blue, alpha);
                vbArray.push(texWidth, 0, texture.uv[2], texture.uv[3], red, greed, blue, alpha);
                vbArray.push(texWidth, texHeight, texture.uv[4], texture.uv[5], red, greed, blue, alpha);
                vbArray.push(0, texHeight, texture.uv[6], texture.uv[7], red, greed, blue, alpha);

                // vbArray.push(0, 0, 0, 0, red, greed, blue, alpha);
                // vbArray.push(texWidth, 0, 1, 0, red, greed, blue, alpha);
                // vbArray.push(texWidth, texHeight, 1, 1, red, greed, blue, alpha);
                // vbArray.push(0, texHeight, 0, 1, red, greed, blue, alpha);
            }

            if (ib) {
                ibArray = ib;
            }
            else {
                ibArray = new Array<number>();
                //在顶点索引数组中放入组成三角形的顶点索引。
                //三角形的顶点索引对应顶点数组vbArray 里的点索引,索引从0开始。
                ibArray.push(0, 1, 3);//第一个三角形的顶点索引。
                ibArray.push(3, 1, 2);//第二个三角形的顶点索引。           
            }
            this.iNum = ibArray.length;

            this.vbData = new Float32Array(vbArray);
            this.ibData = new Uint16Array(ibArray);

            this.vBuffer.append(this.vbData);
            this.iBuffer.append(this.ibData);

            this.shaderValue = new coolDownShaderValue();
            this.shaderValue.textureHost = texture;
            this._renderType |= Laya.RenderSprite.CUSTOM;//设置当前显示对象的渲染模式为自定义渲染模式。   

            this.setUVInfo(texture.uv[0], texture.uv[1], texture.uv[4] - texture.uv[0], texture.uv[5] - texture.uv[1]);
            this.setProgress(0);
        }

        public initWithoutTexture(width: number, height: number, vb: Array<number> = null, ib: Array<number> = null): void {
            this.vBuffer = Laya.VertexBuffer2D.create();
            this.iBuffer = Laya.IndexBuffer2D.create();

            this.ibData = null;
            var vbArray: Array<number>;
            var ibArray: Array<number>;

            if (vb) {
                vbArray = vb;
            }
            else {
                vbArray = new Array<number>();
                var texWidth: number = width;
                var texHeight: number = height;

                //定义颜色值,取值范围0~1 浮点。
                const red: number = 1;
                const greed: number = 1;
                const blue: number = 1;
                const alpha: number = 1;

                //在顶点数组中放入4个顶点
                //每个顶点的数据:(坐标X,坐标Y,u,v,R,G,B,A)            
                vbArray.push(0, 0, 0, 0, red, greed, blue, alpha);
                vbArray.push(texWidth, 0, 1, 0, red, greed, blue, alpha);
                vbArray.push(texWidth, texHeight, 1, 1, red, greed, blue, alpha);
                vbArray.push(0, texHeight, 0, 1, red, greed, blue, alpha);
            }

            if (ib) {
                ibArray = ib;
            }
            else {
                ibArray = new Array<number>();
                //在顶点索引数组中放入组成三角形的顶点索引。
                //三角形的顶点索引对应顶点数组vbArray 里的点索引,索引从0开始。
                ibArray.push(0, 1, 3);//第一个三角形的顶点索引。
                ibArray.push(3, 1, 2);//第二个三角形的顶点索引。           
            }
            this.iNum = ibArray.length;

            this.vbData = new Float32Array(vbArray);
            this.ibData = new Uint16Array(ibArray);

            this.vBuffer.append(this.vbData);
            this.iBuffer.append(this.ibData);

            this.shaderValue = new coolDownShaderValue();
            this.shaderValue.textureHost = null;
            this._renderType |= Laya.RenderSprite.CUSTOM;//设置当前显示对象的渲染模式为自定义渲染模式。   

            this.setUVInfo(0, 0, 1, 1);
            this.setProgress(0);
        }

        public setProgress(val: number) {
            if (val < 0.0) {
                val = 0.0;
            }
            else if (val > 1.0) {
                val = 1.0;
            }
            this.shaderValue.progress = val;
        }

        /**
         * 设置uv信息
         *  单位 0~1
         * @private
         * @param {number} su 起始 u
         * @param {number} sv 起始 v
         * @param {number} w  uv的实际宽
         * @param {number} h  uv的实际高
         * 
         * @memberof coolDownSprite
         */
        private setUVInfo(su: number, sv: number, w: number, h: number) {
            this.shaderValue.uv_info = [su, sv, w, h];
        }

        //重写渲染函数。
        public customRender(context: Laya.RenderContext, x: number, y: number): void {
            (context.ctx as Laya.WebGLContext2D).setIBVB(x, y, this.iBuffer, this.vBuffer, this.iNum, null,
                coolDownShader.shader, this.shaderValue, 0, 0);
        }
 

 
已邀请:

cuixueying

赞同来自:

谢谢!

chunjine

赞同来自:

老兄,用了你的shader怎么没效果啊。是不是因为版本不一样。现在用的1.7.12beta.

要回复问题请先

商务合作
商务合作