【分享】使用Sprite制作一个简单的光影效果

首先先上一下效果图:
wz573-ms76o image
实现思路:

给每一个需要增加阴影的对象都添加一个阴影的sprite,然后根据场上的光源的各种参数对阴影的Sprite进行旋转和透明度的更改。

实现过程:

首先我们要对阴影的sprite节点做一个管理。

    let shadows:Node[] = [];

获取一个shadow

    getShadow(index:number){

        //如果需要的阴影数量大于了shadows的长度就新建一个阴影。

        if(index >= this.shadows.length){

        //这里创建一个新的阴影节点加到场景中,使用预制体或者新建节点添加Sprite组件都可以

        }

        //让被获取的阴影的active为true,因为需要用到的阴影数量可能是随时在变化的,它可能在之前被关闭了

        this.shadows[i].activce = true;

        return shadows[i];

    }

接下来我们可以定义光源,这里我使用的光源是这样的,他有光源位置、光源强度、光照范围这三个参数。

    export type m2dGameLight = { pos: Vec2, str: number, range: number };

我们定义一个Light数组,可以有多个光源来对我们的阴影产生影响。

    lights:m2dGameLight[] = [];

接下来就是实现光源对阴影的影响的部分。

    updateLight(){

        //当前阴影数组的索引

        let index = 0;

        //把光影按照强度大小从大到小排列

        this.lights.sort((a,b)=>{return b.str - a.str});

        for(let obj of 遍历所有受光源影响的对象){

            //遍历所有的光源并且挑选出对该obj有影响的光源

            for( light of this.Lights){

               

                //受到光源影响中最大的光源强度

                let maxStr:number = -1;

                //获取light到obj的距离

                const dis = obj坐标到light.pos的距离

                //如果距离小于light的光照范围则这个光源是影响到了obj的shadow

                if(dis < light.range){

                    if(maxStr<0)

                        maxStr = light.str;

                    const shadow = this.getShadow(index);

                    shadow.setPosition(obj.position.x,obj.position.y);

                    //将shadow根据光源的位置做旋转

图片1
shadow.setRotationFromEuler(new Vec3(0, 0, 旋转角度)));

                    //根据光源强度的强弱和距离设置透明度,光源还受到最强的光源的影响

                    shadow.getComponent(Sprite).color.set(255, 255, 255, (light.range - dis) / light.range * 255 * (light.str / maxStr));

                    //越靠近光源,阴影的长度就越短

                    let shadowLength = 1 - (light.range - dis) / light.range * 1;

                    let shadowWidth = obj.getComponent(UITransform).contentsize.width/阴影贴图宽度;

                    shadow.getComponent(Sprite).setScale(shadowWidth,shadowLength);

                   

                    index++;

                }

            }

        )

        //没有被用到的阴影就关掉

        for (let i = index; i < this.shadows.length; i++) {

            this.shadows[i].active = false;

        }

    }

阴影的贴图用的是这样子的
QQ截图20220105231010

5赞

效果不咋地
还是需要引擎自带2d光照才行

mark~~~~~~

我记得好像有个1d的shadowmap算法

小人和建筑有个圆形灯光范围,是咋实现的哇?

同问~~~~~