基于顶点的渐变效果

实际效果:
1.不支持透明渐变(因为设置a=0依然无效);
2.非shader方式实现,基于顶点数据,修改顶点颜色,所以不会打断合批;
3.版本 3.7.1
4.也有基于2.4.9的版本,有需要的可以留言;
5.直接使用即可;

源码:
import { Enum, Color, UIRenderer, log } from ‘cc’;

import { _decorator, Component } from ‘cc’;
const { ccclass, property, executeInEditMode } = _decorator;

@ccclass

@executeInEditMode

export class VertexGraident extends Component {

@property({tooltip:"是否反向"})

set invert(v)

{

    if(this._bInvert != v)

    {

        this._bInvert = v;

        this.markColorDirty();

    }

}

get invert()

{

    return this._bInvert;

}

@property

_bInvert:boolean = false;

@property({type:Enum(GRID_TYPE)})

set dir(v)

{

    if(this._dir != v)

    {

        this._dir = v;

        this.markColorDirty();

    }

}

get dir()

{

    return this._dir;

}

@property({type:Enum(GRID_TYPE)})

_dir:GRID_TYPE = GRID_TYPE.GRID_VERTICAL;

@property(Color)

set downColor(value)

{

    if(!this._downColor.equals(value))

    {

        this._downColor.set(value);

        this.markColorDirty();

    }

}

get downColor()

{

    return this._downColor.clone();

}

@property(Color)

private _downColor:Color = Color.WHITE.clone();

@property(Color)

set upColor(value)

{

    if(!this._upColor.equals(value))

    {

        this._upColor.set(value);

        this.markColorDirty();

    }

}

get upColor()

{

    return this._upColor.clone();

}

@property(Color)

private _upColor:Color = Color.WHITE.clone();

onLoad()

{

    let render = this.getComponent(UIRenderer);

    render["_updateColor"]= this.updateColor.bind(this);

    this.markColorDirty();

}

updateColor()

{

    let cmp = this.getComponent(UIRenderer);

    this.node._uiProps.colorDirty = true;

    cmp["setEntityColorDirty"](true);

    cmp.setEntityColor(cmp["_color"]);

    cmp.setEntityOpacity(this.node._uiProps.localOpacity);

    if (cmp["_assembler"]) {

        //cmp._assembler.updateColor(this);

        this.doUpdateColor(cmp);

        // Need update rendFlag when opacity changes from 0 to !0 or 0 to !0

        cmp["_renderFlag"] = cmp["_canRender"]();

        cmp.setEntityEnabled(cmp["_renderFlag"]);

    }

}

markColorDirty()

{

    let render = this.getComponent(UIRenderer);

    render["_updateColor"]();

}

doUpdateColor(cmp:UIRenderer) {

    let colors = [Color.RED, Color.RED, Color.GREEN, Color.GREEN];

    switch(this.dir)

    {

        case GRID_TYPE.GRID_VERTICAL:

            {

                colors = [this.upColor, this.upColor, this.downColor, this.downColor];

            }

            break;

        case GRID_TYPE.GRID_HORIZONTAL:

            {

                colors = [this.downColor, this.upColor, this.downColor, this.upColor];

            }

            break;

    }

    if(this.invert)

    {

        colors = colors.reverse();

    }

    const renderData = cmp.renderData;

    const vData = renderData.chunk.vb;

    const floatsPerVert = renderData.floatStride;

    let colorOffset = 5;

    for (let i = 0; i < 4; i++, colorOffset += floatsPerVert) {

        let color = colors[i];

        const colorR = color.r / 255;

        const colorG = color.g / 255;

        const colorB = color.b / 255;

        const colorA = color.a / 255;

        log("透明度", colorA);

        vData[colorOffset] = colorR;

        vData[colorOffset + 1] = colorG;

        vData[colorOffset + 2] = colorB;

        vData[colorOffset + 3] = colorA;

    }

}

}

枚举定义,因为GRID_TYPE放在了GridView中,这里为了保证当前脚本运行,单独列出
export enum GRID_TYPE

{

GRID_HORIZONTAL,

GRID_VERTICAL

}

11赞

2.4.9版本的代码,麻烦贴一下

Z0QOU7M79U23C(3Z6U16YVC

但是3.7.1的原生无效,引擎组的日常操作,上个版本有效的功能,下个版本他就移除掉…,永远不让你保持稳定。

1赞

this.getComponent(UIRenderer) 把这个改成 this.getComponent(Sprite) 就生效了,不然在编辑器里面看不到效果

大佬,我在3.6.3上原生平台也不生效,请问这个问题解决了吗 :shushing_face:

解决了吗!!

解决了吗!!

render["_useVertexOpacity"] = true;
即可开启顶点色透明模式,解决半透问题

我看一下了源码,在渲染时候的多传输几个颜色进去,就实现渐变,难道是引擎自带功能,没有开放出来的吗?

https://forum.cocos.org/t/topic/161589
原生平台不生效,是因为原生平台必须在引擎首次渲染后改顶点颜色才有效
cc.director.once(cc.Director.EVENT_AFTER_DRAW, this.updateColor, this);