前向渲染中在fwdadd中实现点光源的阴影效果

  • 实现效果
  • 错误结果
  • 具体步骤如下
  • 1. 选择光源的阴影类型
  • 2. 为材质勾选接收阴影和投射阴影选项
  • 3. shader设置
  • 补充


实现效果

unity光照阴影加深_unity光照阴影加深


可以看到不仅有平行光照射在底面上的投影,点光源在竖直面板上的投影也出现了,达到了预期效果。

错误结果

unity光照阴影加深_unity_02


平行光的阴影投射在底面上,但是点光源光线穿过了物体直接投射在竖直平面上,显然不对,问题出在点光源在初始时没有选择阴影类型,使得在最初的UpdateDepthTexture步骤就没有生成阴影。

具体步骤如下

1. 选择光源的阴影类型

这一步被我忽视了,昨天一直找不到原因,导致最后的实现结果中只有光线衰减而看不到点光源投射的阴影。

unity光照阴影加深_unity_03


在这里选择了soft shadow类型。

2. 为材质勾选接收阴影和投射阴影选项

unity光照阴影加深_d3_04

3. shader设置

ForwardBase中需要导入“AutoLight.cginc”

#include "AutoLight.cginc"

在struct v2f 中调用宏

struct v2f{
                float4 pos :SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                // 宏
                SHADOW_COORDS(2)
            };

在顶点着色器中添加相关操作,对输出的o进行转化

v2f vert(a2v v){
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                // 宏
                TRANSFER_SHADOW(o);
                return o;
            }

最后在片元着色器中获得光照的衰减值和阴影值(统一为atten)

fixed4 frag(v2f i):SV_Target{
                fixed shadow = SHADOW_ATTENUATION(i);
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

                fixed3 diffuse = _LightColor0.rgb* _Diffuse.rgb*max(0,dot(worldNormal,worldLightDir));

                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
                fixed3 halfDir = normalize(worldLightDir+viewDir);
                
                fixed3 specular = _LightColor0.rgb* _Specular.rgb*pow(max(0,dot(halfDir,worldNormal)),_Gloss);
				// 该函数得到衰减值相关,返回值填充到第一个参数的位置中,即atten
                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

                return fixed4(ambient+(diffuse+specular)*atten,1.0);
            }

fwdadd中类似,但是注意将

#pragma multi_compile_fwdadd

替换成

#pragma multi_compile_fwdadd_fullshadows

因为fwdadd中默认不开启阴影设置,其他与fwdbase中的配置完全相同。

补充

在我的shader中没有引入LightMode为ShadowCaster的pass,但是结果还是出现了,因为在最后使用了Fallback"Specular"等方法, 当渲染过程中在当前shader中没有找到ShadowCaster的pass时,就会向上寻找,从而在Fallback中找到对应的pass,最终实现阴影效果。
值得注意的是,霜狼_May的教程中有提到,建议还是自己将那一段pass写在自己的shader中,防止fallback引入过多无用的pass扰乱结果的生成。