2D这里主要是指有高度的光,即限定了影子的长度。git
限定影子长度生成的Mesh有不少种,能够根据实际状况,选择不一样的方案。算法
在c#脚本里遍历Sprite生成Mesh数据。生成一个Mesh绘制影子,只有一个Draw Call。c#
3. 使用凸包算法获取凸点,保存为Mesh的数据3d
4. 软阴影能够在Mesh外面包一个Mesh,使用一张渐变纹理绘制软阴影。用UV或Tangent等通道保存渐变贴图的UV,内围点为0,外围点为1。code
使用Custome Physics Shape和默认顶点的结果:orm
遍历Srpite使用Sprite原来的Sprite Renderer加上阴影的Shader绘制阴影。每一个Sprite都须要一个Draw Call。这样作主要是由于须要使用Sprite贴图的Alpha通道绘制影子外形。blog
若是合并使用一个Draw Call绘制,阴影的外形很差控制(使用默认Sprite顶点基本上效果会不好)。可使用cutom outline或者cutom physics shape生成相对细致的外形,属于空间换时间的作法。ci
// c# // 旋转所用的根顶点,取中间接近底部的顶点 // 兼容旋转缩放 var matrix = Matrix4x4.TRS(caster.transform.position, caster.transform.rotation, caster.transform.localScale); var rootPos = (Vector2)(matrix * new Vector4(0f, -0.45f, 0, 1)); // Sprite过大也可使用spriteRenderer.bounds.size.y,实际上手动指定比较好 rootPos = caster.transform.InverseTransformPoint(rootPos); // shader // 二维按任意方向拉伸 float2 scaleByDir(float2 p, float radian, float k){ float2 dir = float2(cos(radian), sin(radian)); float2 r1 = float2(1 + (k - 1) * dir.x * dir.x, (k - 1) * dir.x * dir.y); float2 r2 = float2((k - 1) * dir.x * dir.y, 1 + (k - 1) * dir.y * dir.y); return float2(r1.x * p.x + r1.y * p.y, r2.x * p.x + r2.y * p.y); }
旋转根部的瑕疵get
解决方法能够是使用一张底部是圆形的Mask贴图,这样旋转的时候就看不出来瑕疵。我以为是一种比较好的方法,Mask贴图还可用来作软阴影(未验证)。源码
另外一种是底部uv.y
比较小的时候不进行旋转拉伸。
大于180°时,下面会消失。是由于底部不旋转,其余地方旋转大于180°时致使三角面片反了。大于180°将底部x坐标置反便可。
可是旋转角度接近与0°和180°时底部太小处理起来比较麻烦,除了手动加一个圆形阴影想不出来什么好的处理方法。相对来讲仍是使用一个阴影Mask贴图比较方便。
阴影会将Sprite自己覆盖掉。
由于覆盖地方彻底贴合Sprite,因此除了每一个Sprite在渲染阴影后再渲一遍将覆盖地方去除,目前想不其余好的方法。
// 将alpha置反,混合时取最小便可 BlendOp Min Blend One OneMinusDstColor frag { fixed alpha = tex2D(_MainTex, i.uv).a; fixed4 col = 1 - alpha; col.a = 1; return col; }
简单点计算顶点与以前旋转用的点的距离而后使用1.0 - saturate(distance * _ShadowFalloff)
求出衰减便可。
拉伸矩阵:https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/scale/