Unity3D:优化着色器运行时性能
推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生
优化着色器运行时性能
不同的平台具有截然不同的性能;与低端移动端 GPU 相比,高端 PC GPU 在图形和着色器方面的处理能力要高得多。即使在单一平台上也是如此;快速的 GPU 比慢速的集成 GPU 快几十倍。
移动平台和低端 PC 上的 GPU 性能可能远低于开发计算机上的性能。建议您手动优化着色器以减少计算和纹理读取,以便在低端 GPU 计算机上获得良好的性能。例如,某些内置着色器对象具有“移动”等效项,这些等效项要快得多,但有一些限制或近似值。
本页包含有关优化着色器以提高运行时性能的信息。
仅执行所需的计算
着色器代码需要执行的计算和处理越多,它对游戏性能的影响就越大。例如,支持每种材质的颜色可以使着色器更加灵活,但如果始终将该颜色设置为白色,则会对屏幕上渲染的每个顶点或像素执行无用的计算。
计算的频率也会影响游戏的性能。通常,与顶点数(顶点着色器执行次数)相比,渲染的像素数会更多(因此像素着色器执行次数也更多),而渲染的顶点数比渲染的对象更多。在可能的情况下,可将计算从像素着色器代码移动到顶点着色器代码中,或者将它们完全移出着色器并在脚本中设置值。
计算的精度
用 Cg/HLSL 编写着色器时,有三种基本数字类型:float
、half
和 fixed
(请参阅数据类型和精度)。
为了获得良好的性能,请始终使用尽可能低的精度。这在低端硬件上尤其重要。好的经验法则是
- 对于世界空间位置和纹理坐标,请使用
float
精度。 - 对于所有其他情况(矢量、HDR 颜色等),请首先尝试
half
精度。仅在必要的情况下再提高精度。 - 要对纹理数据进行非常简单的运算,请使用
fixed
精度。
实际上,具体应该使用哪种数字类型取决于平台和 GPU。一般来说:
- 所有新款的桌面端 GPU 将始终以完整
float
精度进行所有计算,因此float/half/fixed
最终产生完全相同的结果。这可能会使测试变得困难,因为更难以确定 half/fixed 精度是否真正够用,因此请始终在目标设备上测试着色器以获得准确的结果。 - 移动端 GPU 实际支持
half
精度。这种精度通常速度更快,并且使用更少的性能来执行计算。 Fixed
精度通常仅对于较旧的移动端 GPU 有用。大部分新款 GPU(可运行 OpenGL ES 3 或 Metal 的 GPU)在内部以相同方式来处理fixed
和half
精度。
有关更多详细信息,请参阅数据类型和精度。
复杂的数学运算
超越数学函数(如、、)是相当耗费资源的,因此请尽可能避免在低端硬件上使用它们。如果适用,请考虑使用查找纹理作为复杂数学计算的替代方法。powexplogcossintan
避免编写自己的运算(如 normalize
、dot
、inversesqrt
)。Unity 的内置选项确保驱动程序可以生成好得多的代码。请记住,Alpha 测试 (discard
) 运算通常会使片元着色器变慢。
优化的表面着色器
表面着色器非常适合编写与光照交互的着色器。但是,它们的默认选项已调整为涵盖大量的一般情况。可针对特定情况调整这些选项以使着色器运行速度更快,或至少让着色器变得更小巧:
- 使用视图方向(即镜面反射)的着色器的
approxview
指令使视图方向按照顶点(而不是按像素)进行标准化。这是近似值,但通常足够好。 - 适用于镜面反射着色器类型的
halfasview
速度更快。半矢量(光照方向和视图矢量之间)按照顶点进行计算和标准化,并且光照函数接受半矢量作为参数,而不是视图矢量。 noforwardadd
使着色器仅完全支持前向渲染中的单方向光。其余的光源仍然可提供每顶点光源或球谐函数光源的效果。这样可以使着色器更小并确保它始终在一个通道中渲染,即使存在多个光源也是如此。noambient
在着色器中禁用环境光照和球谐函数光源。这样可以稍稍提高性能。
Alpha 测试
固定函数 AlphaTest(或者其可编程的等效函数 clip()
)在不同平台上具有不同的性能特征:
- 通常,在使用该函数来移除大多数平台上的完全透明像素时,可获得少量优势。
- 但是,在 iOS 和某些 Android 设备的 PowerVR GPU 上,Alpha 测试是资源密集型任务。不要试图在这些平台上使用这种测试进行性能优化,因为它会导致游戏运行速度比平常慢。
颜色遮罩 (Color Mask)
在某些平台(主要是 iOS 和 Android 设备的移动端 GPU)上,使用 ColorMask 省略一些通道(例如 ColorMask RGB
)可能是资源密集型的操作,所以除非绝对需要,否则请不要使用。
由3D建模学习工作室整理翻译,转载请注明出处!