渐变效果竟然没提供接口?贡献一个 webgl 渐变

找半天没找到能用的,自己写了个用 shader 实现的渐变效果,仅支持 webgl

// component

cc.Class({
    extends: cc.Component,

    properties: {
        fragmentName: 'Gradient',

        from: cc.Color,
        to: cc.Color,
    },

    start() {
        this.vertStr = `
            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;
            }
        `;

        // this.colors = [cc.Color.BLUE, cc.Color.YELLOW, cc.Color.ORANGE];
        this.program = new cc.GLProgram();
        this.loadShader(this.fragmentName, this.setProgram);
    },

    loadShader (shaderName, callback) {

        cc.loader.loadRes('/Shaders/' + shaderName, null, function (err, res) {
            if (err) {
                console.error('load fail.');
                return;
            }
            var sgNode = this.node.getComponent(cc.Sprite)._sgNode;

            callback(sgNode, this.program, this.vertStr, res);
            this.setBGGradient();
        }.bind(this));
    },

    setBGGradient () {
        // var randomNumber = Math.floor(Math.random() * 3);
        // this.from = this.colors[randomNumber];

        this.updateUniform();
    },

    updateUniform() {
        this.program.use();

        if (cc.sys.isNative) {
            var state = cc.GLProgramState.getOrCreateWithGLProgram(this.program);

            state.setUniformVec3('from', this.from);
            state.setUniformVec3('to', this.to);
        }
        else {
            var from = this.program.getUniformLocationForName('from');
            var to = this.program.getUniformLocationForName('to');

            var fromNormalized = this.colorNormalized(this.from);
            var toNormalized = this.colorNormalized(this.to);
            this.program.setUniformLocationWith3f(from, fromNormalized.r, fromNormalized.g, fromNormalized.b);
            this.program.setUniformLocationWith3f(to, toNormalized.r, toNormalized.g, toNormalized.b);
        }

    },

    colorNormalized (color) {
        var normalized = {r: 0.0, g: 0.0, b: 0.0};
    
        normalized.r = color.r / 255;
        normalized.g = color.g / 255;
        normalized.b = color.b / 255;
        return normalized;
    },

    setProgram(sgNode, program, vert, frag) {

        if (cc.sys.isNative) {
            program.initWithString(vert, frag);
        }
        else {
            program.initWithVertexShaderByteArray(vert, frag);

            program.addAttribute(cc.macro.ATTRIBUTE_NAME_POSITION, cc.macro.VERTEX_ATTRIB_POSITION);
            program.addAttribute(cc.macro.ATTRIBUTE_NAME_COLOR, cc.macro.VERTEX_ATTRIB_COLOR);
            program.addAttribute(cc.macro.ATTRIBUTE_NAME_TEX_COORD, cc.macro.VERTEX_ATTRIB_TEX_COORDS);
        }
        program.link();
        program.updateUniforms();

        if (cc.sys.isNative) {
            var state = cc.GLProgramState.getOrCreateWithGLProgram(program);
            sgNode.setGLProgramState(state);
        }
        else {
            sgNode.setShaderProgram(program);
        }

    },

});

// glsl
#ifdef GL_ES
precision mediump float;
#endif

uniform vec3 from;
uniform vec3 to;

varying vec2 v_texCoord;

void main(void) {
	vec2 uv = v_texCoord.xy;
    vec3 color = uv.y * to + (1.0 - uv.y) * from;

    gl_FragColor = vec4(color, 1.0);
}

3赞

666膜拜大佬

发个效果图see see呗

公司没代码,找了张参考。就是PS里这种渐变,纵向的

@313896175qq.com

:joy: 好像这种效果我们都是直接用图片资源完成的。。 这两种哪种性能高?我们一直不敢用shader 就怕有性能问题

这能有啥性能问题,只要是webgl都有个默认shader,你看源码就知道了

我指的是帧率 drawcall方面以及在低端机子上的发热上 上次测试了一个shader效果 在低端机子上惨不忍睹 虽然这个比较简单 但是如果量大的话应该也存在这种隐患吧

而且好像2.0没有_sgNode了

:relaxed::relaxed:

这个改顶点色就可以了,不是有这个组件的么

膜拜下大佬~

那组件叫啥

我擦,shader写渐变啊

额,我怎么没找到有修改顶点色的组件

ccc确实没实现 :joy:

嗯哼,你的意思是shader重新分配顶点改顶点色么,opengl确实会自动插值颜色

不改shader,设置下4个顶点色就可以了,还可以改变渐变的方向和渐变的位置。
这样就不需要切换shader,贴图用同一张小的纯色贴图的话还可以合批。
cocos2dx原来有个GradientLayer实现渐变的,ccc暂时没实现,可能用的少