如果项目使用了自定义着色器代码,在将项目从 Unity 4 升级到 Unity 5 时需要注意以下注意事项。
着色器不再应用 2 倍光强。相反,光源会自动升级为两倍亮度。这样可以在光源配置中提高一致性和简单性。例如,照射在白色漫射表面上的方向光将获得光的精确颜色。该升级不会影响动画,因此如果具有动画化的光强值,必须更改动画曲线或脚本代码,将它们设置为 2 倍,从而获得相同的效果。
如果您在自定义着色器中定义自己的光照函数,需要自己删除 * 2。
// 具有此问题的着色器代码中的常见模式如下所示
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
// 需要按如下所示的方式修复代码
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten);
Unity 5 中的内置光照管线在某些情况下可以使用更多纹理坐标插值器或数学指令计数(从而实现非一致网格比例、动态 GI 等)。现有的一些表面着色器可能会遇到纹理坐标或 ALU 指令限制,特别是以着色器模型 2.0(默认)为目标的情况下。添加“#pragma target 3.0”可以解决此问题。请参阅 http://docs.unity.cn/Manual/SL-ShaderPrograms.html 获取参考信息。
在 Unity 5.0 中,非一致网格不再在 CPU 上“预先缩放”。这意味着法线和切线矢量可以在顶点着色器中非标准化。如果在此处手动进行光照计算,则必须将它们标准化。如果使用的是 Unity 的表面着色器,那么将自动生成所有必需的代码。
Unity 5.0 使内置雾效在 Windows Phone 和游戏主机上有效,但为了实现这一点,我们稍微改变了一下雾效的工作方式。对于表面着色器和固定函数着色器,不需要做任何额外的工作 - 雾效将自动添加(可将“nofog”添加到表面着色器 #pragma 代码行来显式指定不支持雾效)。
对于手动编写的顶点/片元着色器,雾效现在不会自动发生。需要将 #pragma multi_compile_fog 和雾效处理宏添加到着色器代码中。请查看内置着色器源代码(例如 Unlit-Normal)了解如何执行此操作。
默认情况下,所有不透明表面着色器现在都会将 1.0(“白色”)输出到 Alpha 通道。如果要停止该行为,请在 #pragma surface 行中使用“keepalpha”选项。
所有 Alpha 混合表面着色器现在都使用由光照函数计算的 Alpha 分量作为混合系数(而不是 s.Alpha)。如果使用的是自定义光照函数,可能需要在结尾添加类似“c.a = s.Alpha”的内容。
Unity 在前向渲染循环中不再按材质索引进行排序。这样可以提高性能,因为可以渲染更多对象而不会在它们之间改变状态。不过,这会破坏依赖于材质索引作为排序方式的内容的兼容性。在 4.x 中,具有两种材质的网格总是首先渲染第一种材质,然后是第二种材质。在 Unity 5 中并非如此,渲染顺序取决于在渲染场景时哪种材质可减少最多的状态变化。
Unity 5.0 删除了对以下固定函数着色器功能的支持:
以上任何一项现在已经无效,着色器 Inspector 会显示有关其用法的警告。因此,应使用可编程顶点+片元着色器重写受影响的着色器。现在所有平台都支持它们,并且使用固定函数着色器没有任何优势。
如果项目中使用了版本相当旧的 Projector 或 Water 着色器包,这些着色器可能使用了此功能。请将这些着色器包升级到 5.0 版。
不再支持混合部分固定函数着色器和部分可编程着色器(例如固定函数顶点光照与像素着色器;或者顶点着色器与纹理组合器)。无论如何,这种做法以前在移动设备、游戏主机和 DirectX 11 上也一直是无效的。以前这需要改变 Legacy/Reflective/VertexLit 着色器的行为来禁止这种做法 - 虽然丢失了每顶点镜面反射支持,但从好的方面来看,现在平台之间的行为是一致的了。
大多数情况下,这应该是透明的(只会减少代码生成错误和略微加快着色器速度)。但是 HLSL 编译器在语法方面可能稍微严格一些。例如:
已删除“unity_Scale”着色器属性。在 4.x 版中,unity_Scale.w 是 1 / 变换的一致缩放,Unity 4.x 仅渲染非缩放或一致缩放的模型。其他缩放都是在 CPU 上执行的,这样的成本很高并有意外的内存开销。
在 Unity 5.0 中,所有这些都是在 GPU 上完成的,只需将具有非一致比例的矩阵传递给着色器即可。所以现在删除了 unity_Scale,因为它不能代表完整缩放比例。对于大多数以前使用“unity_Scale”的情况,我们建议首先转换为世界空间。对于转换法线的情况,现在必须对转换的法线进行标准化。在某些情况下,这会导致顶点着色器中的代码成本略微升高。
// Unity 4.x
float3 norm = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal * unity_Scale.w);
// 在 Unity 5.0 中变为如下语句
float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
// Unity 4.x
temp.xyzw = v.vertex.xzxz * unity_Scale.xzxz * _WaveScale4 + _WaveOffset;
// 在 Unity 5.0 中变为如下语句
float4 wpos = mul (_Object2World, v.vertex);
temp.xyzw = wpos.xzxz * _WaveScale4 + _WaveOffset;
前向渲染的方向光阴影不再单独执行“阴影收集器”(shadow collector) 通道。现在,它们根据摄像机的深度纹理计算屏幕空间阴影(就像在延迟光照中一样)。
这意味着,着色器中的 LightMode=ShadowCollector 通道不再有任何作用;可从着色器中删除它们。
不再使用着色器替换来生成深度纹理本身,而是使用 ShadowCaster 着色器通道来对其进行渲染。这意味着只要对象可以投射适当的阴影,那么它们也将正确出现在摄像机的深度纹理中(在以前,如果想要自定义顶点动画或灵活的 Alpha 测试,这是很难做到的)。这也意味着 Camera-DepthTexture.shader 现在没有任何用处。而且,所有内置的阴影着色器都未使用背面剔除;已更改为匹配常规渲染的剔除模式。