最近研究阴影比较多,这里就介绍两种比较古早的阴影技术吧:Blob Shadow和Planar Shadow。虽然都是比较早期的技术,但是在某些低开销的场合你仍然能看到它们的身影:其中Blob Shadow多用于2D游戏中,Planar Shadow多用于一些moba游戏。
Blob Shadow
早期的游戏中,Blob Shadow基本全是挂一个黑色渐变的圈在人物脚底下。


因为受技术/硬件/性能等各方原因,早期游戏都不太好实时表现阴影,所以都选择这种以一张特殊图片的方案表现阴影。现代的游戏中,Blob Shadow在2D top-down类型的游戏中用的比较多,以Unity官方的Happpy Harvest Demo为例:
人物阴影以及对应素材:


树木阴影以及对应素材:


窗户阴影以及对应素材:


以上阴影其实都是Blob Shadow的思想。
Blob Shadow实现起来非常简单,就不赘述了。
Planar Shadow
Planar Shadow的思想也很简单,将整个模型拍扁到平面上,只需要在Vertex Shader里做坐标变换即可。


自己简单推导了一下:

shader代码表示:
shadowPosWS.xz = vertexInput.positionWS.xz - lightDir.xz * max(_Height , vertexInput.positionWS.y) /lightDir.y;
shadowPosWS.y = min(vertexInput.positionWS.y,_Height);
output.positionCS = TransformWorldToHClip(shadowPosWS);


PlanarShadow混合
利用模板测试和Offset,使自身混合时正确,解决Z fighting。
Stencil
{
Ref 0
Comp equal
Pass incrWrap
Fail keep
ZFail keep
}
Offset -1 , 0
PlanarShadow阴影渐变
方法很多,这里写个从根节点到坐标渐变的方式:
float3 center = float3(unity_ObjectToWorld[0].w , _Height , unity_ObjectToWorld[2].w);
float falloff = 1- saturate(distance(shadowPosWS , center) * _ShadowFalloff);
output.color.xyz = _ShadowColor.xyz;
output.color.w = lerp(0.2,1,_ShadowColor.w * falloff);

PlanarShadow支持SRP Batch
利用URP RenderObjects Pass,一遍绘制所有需要投影的物体。
