首先先上一下效果图:
实现思路:
给每一个需要增加阴影的对象都添加一个阴影的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根据光源的位置做旋转
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;
}
}
阴影的贴图用的是这样子的