透明物体的阴影
一、透明度测试的阴影
1.投射阴影
- 还是使用 Fallback 的形式投射阴影
Fallback Transparent/Cutout/VertexLit
该默认 Shader 中会把裁剪后的物体深度信息写入到 阴影映射纹理和摄像机深度图中 注意: 使用该默认 Shader 计算投射阴影时,需要使用_Cutoff 属性 和 _Color 属性来进行相关计算 因此我们必须保证我们的 Shader 当中有名为_Cutoff 的阈值属性 和 _Color 的漫反射颜色属性 否则无法得到正确阴影结果 - 额外注意事项 为了得到正确的阴影效果,我们需要将该物体的 Cast Shadows(投射阴影)属性设置为 Two Sided(双面) 强制让 Unity 计算阴影隐射纹理时计算所有面的深度信息。 因为如果不设置,默认将物体渲染到阴影隐射纹理和摄像机深度图时只会考虑物体的正面 背对光源的面不会参与计算,设置为双面后即可参与计算,得到正确的结果
2.接收阴影
主要分 5 步骤:
- 编译指令 #pragma multi_compile_fwdbase 用于帮助我们编译所有变体 并且保证衰减相关光照变量能够正确赋值到对应的内置变量中
- 包含内置文件 #include "AutoLight.cginc"
- 结构体中声明阴影坐标宏 SHADOW_COORDS(n) n 为下一个可用的插值寄存器的索引值(结构体前面有几个 TEXCOORD 就填几)
- 坐标转换宏 TRANSFER_SHADOW(o);
- Unity 光照衰减计算宏 UNITY_LIGHT_ATTENUATION(atten, v2f 结构体, 顶点世界坐标位置);
二、透明度混合的阴影
由于透明度混合需要关闭深度写入 而阴影相关的处理需要用到深度值参与计算 因此 Unity 中从性能方面考虑(要计算半透明物体的的阴影表现效果是相对复杂的) 所有的内置半透明 Shader 都不会产生阴影效果(比如 Transparent/VertexLit) 因此 2-1. 透明混合 Shader 想要 投射阴影时 不管你在 FallBack 中写入哪种自带的半透明混合 Shader 都不会有投射阴影的效果,因为深度不会写入 2-2. 透明混合 Shader 想要 接受阴影时 Unity 内置关于阴影接收计算的相关宏 不会计算处理 透明混合 Shader 混合因子 设置为半透明效果(Blend SrcAlpha OneMinusSrcAlpha)的 Shader 因为透明混合物体的深度值和遮挡关系无法直接用传统的深度缓冲和阴影贴图来处理
结论: Unity 中不会直接为透明度混合 Shader 处理阴影
强制生成阴影
我们可以尝试让透明混合 Shader 强制投射阴影 在 FallBack 中设置一个非透明 Shader,比如 VertexLit、Diffuse 等 用其中的灯光模式设置为阴影投射的渲染通道来参与阴影映射纹理的计算 把该物体当成一个实体物体处理 但是,这种效果并不真实,不建议使用