Version: 2023.1
Understanding shader performance
使用 Visual Studio 调试着色器

优化着色器运行时性能

不同的平台具有截然不同的性能;与低端移动端 GPU 相比,高端 PC GPU 在图形和着色器方面的处理能力要高得多。即使在单一平台上也是如此;快速的 GPU 比慢速的集成 GPU 快几十倍。

GPU performance on mobile platforms and low-end PCs is likely to be much lower than on your development machine. It’s recommended that you manually optimize your shaders to reduce calculations and texture reads, in order to get good performance across low-end GPU machines. For example, some built-in Shader objects have “mobile” equivalents that are much faster, but have some limitations or approximations.

This page contains information on optimizing your shaders for runtime performance.

仅执行所需的计算

着色器代码需要执行的计算和处理越多,它对游戏性能的影响就越大。例如,支持每种材质的颜色可以使着色器更加灵活,但如果始终将该颜色设置为白色,则会对屏幕上渲染的每个顶点或像素执行无用的计算。

计算的频率也会影响游戏的性能。通常,与顶点数(顶点着色器执行次数)相比,渲染的像素数会更多(因此像素着色器执行次数也更多),而渲染的顶点数比渲染的对象更多。在可能的情况下,可将计算从像素着色器代码移动到顶点着色器代码中,或者将它们完全移出着色器并在脚本中设置值。

计算的精度

用 Cg/HLSL 编写着色器时,有三种基本数字类型:floathalffixed(请参阅数据类型和精度)。

For good performance, always use the lowest precision that is possible. This is especially important on lower-end hardware. Good rules of thumb are:

  • 对于世界空间位置和纹理坐标,请使用 float 精度。
  • 对于所有其他情况(矢量、HDR 颜色等),请首先尝试 half 精度。仅在必要的情况下再提高精度。
  • 要对纹理数据进行非常简单的运算,请使用 fixed 精度。

实际上,具体应该使用哪种数字类型取决于平台和 GPU。一般来说:

  • 所有新款的桌面端 GPU 将始终以完整 float 精度进行所有计算,因此 float/half/fixed 最终产生完全相同的结果。这可能会使测试变得困难,因为更难以确定 half/fixed 精度是否真正够用,因此请始终在目标设备上测试着色器以获得准确的结果。
  • 移动端 GPU 实际支持 half 精度。这种精度通常速度更快,并且使用更少的性能来执行计算。
  • Fixed 精度通常仅对于较旧的移动端 GPU 有用。大部分新款 GPU(可运行 OpenGL ES 3 或 Metal 的 GPU)在内部以相同方式来处理 fixedhalf 精度。

有关更多详细信息,请参阅数据类型和精度

Complex mathematical operations

Transcendental mathematical functions (such as pow, exp, log, cos, sin, tan) are quite resource-intensive, so avoid using them where possible on low-end hardware. Consider using lookup textures as an alternative to complex math calculations if applicable.

避免编写自己的运算(如 normalizedotinversesqrt)。Unity 的内置选项确保驱动程序可以生成好得多的代码。请记住,Alpha 测试 (discard) 运算通常会使片元着色器变慢。

优化的表面着色器

表面着色器非常适合编写与光照交互的着色器。但是,它们的默认选项已调整为涵盖大量的一般情况。可针对特定情况调整这些选项以使着色器运行速度更快,或至少让着色器变得更小巧:

  • 使用视图方向(即镜面反射)的着色器的 approxview 指令使视图方向按照顶点(而不是按像素)进行标准化。这是近似值,但通常足够好。
  • 适用于镜面反射着色器类型的 halfasview 速度更快。半矢量(光照方向和视图矢量之间)按照顶点进行计算和标准化,并且光照函数接受半矢量作为参数,而不是视图矢量。
  • noforwardadd 使着色器仅完全支持前向渲染中的单方向光。其余的光源仍然可提供每顶点光源或球谐函数光源的效果。这样可以使着色器更小并确保它始终在一个通道中渲染,即使存在多个光源也是如此。
  • noambient 在着色器中禁用环境光照和球谐函数光源。这样可以稍稍提高性能。

Alpha 测试

固定函数 AlphaTest(或者其可编程的等效函数 clip())在不同平台上具有不同的性能特征:

  • 通常,在使用该函数来移除大多数平台上的完全透明像素时,可获得少量优势。
  • 但是,在 iOS 和某些 Android 设备的 PowerVR GPU 上,Alpha 测试是资源密集型任务。不要试图在这些平台上使用这种测试进行性能优化,因为它会导致游戏运行速度比平常慢。

颜色遮罩 (Color Mask)

在某些平台(主要是 iOS 和 Android 设备的移动端 GPU)上,使用 ColorMask 省略一些通道(例如 ColorMask RGB)可能是资源密集型的操作,所以除非绝对需要,否则请不要使用。

Understanding shader performance
使用 Visual Studio 调试着色器