Version: 2017.1
Unity 的渲染管线
使用替换的着色器进行渲染

编写着色器时的性能技巧

仅执行所需的计算

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

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

优化的表面着色器

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

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

计算的精度

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

为获得良好性能,请始终使用尽可能低的精度。这在移动平台(如 iOS 和 Android)上尤为重要。重要的经验法则如下:

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

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

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

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

Alpha 测试

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

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

颜色遮罩 (Color Mask)

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

Unity 的渲染管线
使用替换的着色器进行渲染