saturate函数可以将最终的结果限制在0到1之间
计算光照时,根据兰伯特余弦定定律,我们需要忽略从负方向过来的光,所以我们可以通过max函数限制小于0的值都为0,如
max(0, dot(world_normal, world_light_dir))
但是看了很多unity的shader都是用的saturate函数而不是max函数,而且我也没有从结果上看出任何区别,好奇就特意查了一番,直到我看到catlikecoding的教程
也就是从理论来说余弦值永远不会超过1,但是由于不同平台计算浮点精度的问题,可能会导致出现大于1的情况,当然就算出了这个问题也是一个极其微观的问题,但从编码角度上来说,我们应该严谨的使用saturate函数
不过Unity为了效率,封装了DotClamped函数来专门用于计算点积
但是我并没有在UnityStandardBRDF.cginc中找到它的定义,这是因为我的Unity版本是2019.4.8,而教程是Unity5.4.0b17.我在UnityDeprecated.cginc中找到了它(即将废弃的)
inline half DotClamped (half3 a, half3 b) { #if (SHADER_TARGET < 30) return saturate(dot(a, b)); #else return max(0.0h, dot(a, b)); #endif }
个人猜测应该是老一辈的硬件设备逐步退出市场了,新一代的硬件设备不会出现这种问题,个人觉得了解这些历程有助于提高阅读代码能力
文章评论