一。目的
Unity自带的阴影功能 shadowmap占用内存过大。1024 * 1024占用8M。而我们项目内存吃紧。所以只能选用512 *512.而效果就差很多。
有明显锯齿。所以需要采用 screen space shadow blur。就是在屏幕空间里对已经投射完阴影的物体进行高斯模糊来增加阴影质量,减少锯齿感。(PS unity提供的软阴影应该是PCF。但是效果并不明显)。
经过 ScreenSpaceShadowMask Blur后
二。实现步骤
一.渲染流程
shadowcamera 的 shadowPass ->shadowcamera 正常pass ->blurPass ->main camera Pass ->全屏片
二。详细分析
1.shadowPass 主要产生shadowMap 只需让shadowCamera能看到投射阴影和接收阴影的物体同时把那些阴影开关打开unity会自动加入该pass.(Ps 如果物体是自己写的Vertext Fragement shader需要自己加入 shadow caster pass.调用unity内置即可。文件在 UnityStandardShadow.cginc里)
(shadow camera 在渲染前统一替换成一个简单的shader,只需包含投射跟接收阴影2个pass即可。即可以减少shader复杂度,又可以合并drawcall)
2.正常Pass 就是正常渲染阴影,比较shadowmap与自己的深度值。shadowcamera清屏色设置成黑色。最终效果为有阴影的地方有颜色,其余地方为黑色。(颜色值会当成最后的alpha值来处理)。
3.blur Pass
可以用commadnbuffer 也可以用OnPostRender。输入参数为shadercamera的 rendertarget。通过blit来进行高斯模糊。(建议能不用commandbuffer就不用commandbuffer。我采用commandbuffer,在小米1s上 RT->blurRT->RT会出现抖动现象,OnPostRender并没有。但是这两者原理应该是一样的,通过GPA查看,代码都是一样的。不知道为什么了。)
4.main camera pass 正常渲染场景。原则上渲染的物体没有接收阴影的。
5.全屏片 可以通过commandbuffer 也可以通过 OnPostRender。输入参数为上次经过模糊的RT的值当alpha,阴影颜色 透明度自己写两个参数进行调节即可。最终渲染流程
三。消耗
1.内存消耗
shadowmap 512 *512 2M
shadow camera RT 1/4屏 带16位深度
blur RT 1/4屏 不带深度
这是4c数据。
2.渲染消耗
多一个相机 投射阴影体,接收阴影体多渲染一次
2次blur操作。
1次全屏blit操作。
主要对于带宽影响较大的物体影响较重。
四。总结
1.commandbuffer 更自由,比如很多点都可以插自定义行为,比如对shadowmap进行操作等。但是稳定性不佳。性能Ok。
2.如果一个camera被设成成RT,他会在其他相机渲染之前渲染,不受depth影响。
五。相应资源
1.shadowPass shader
Shader "Shadow/ShadowMask" {
Properties
{
}
SubShader
{
Tags { "RenderType"="Geometry" }
Pass
{
Tags {"LightMode"="ForwardBase"}
CGPROGRAM
#pragma multi_compile_fwdbase
#pragma vertex vertForwardBase
#pragma fragment fragForwardBase
struct appdata_input
{
float4 vertex : POSITION;