包含此页的版本:
不含此页的版本:
着色器变体,有时也称为着色器在 GPU 上运行的程序。更多信息
请参阅术语表排列是将条件行为引入着色器代码的一种方法。
Unity 将着色器源文件编译为着色器程序。每个编译的着色器程序都有一个或多个变体:针对不同条件的不同版本的着色器程序。在运行时,Unity 使用符合当前要求的变体。您可以使用着色器关键字配置变体。
有关着色器代码中条件的一般概述以及何时使用哪种技术,请参阅着色器代码中的条件。有关 Unity 如何加载着色器变体的详细信息,请参阅着色器加载。
具有大量变体的着色器称为“超级着色器”或“超级着色器”。Unity 的标准着色器就是此类着色器的一个示例。
着色器变体的主要优点是,它们允许你在着色器程序中使用运行时条件,而不会受到动态分支的GPU性能影响。着色器变体的主要缺点是,大量着色器变体会导致更长的构建时间、高着色器内存使用率和着色器编译卡顿。
当 Unity 创建着色器变体时,它使用静态分支来创建多个小型的专用着色器程序。在运行时,Unity 使用与条件匹配的着色器程序。这意味着,你可以将着色器变体用于可能导致动态分支中 GPU 性能降低的代码,而不会遭受 GPU 性能损失。
但是,大量变体可能会导致构建时间、文件大小、运行时内存使用和加载时间增加。它还会导致手动预加载(“预热”)着色器时更加复杂。当项目包含大量着色器变体时,这些问题可能会导致性能和工作流程出现重大问题。
警告:很容易无意中创建过多的着色器变体,这可能导致严重的性能问题。因此,了解 Unity 如何确定着色器变体的数量、如何从编译中排除(“剥离”)不需要的变体以及何时在着色器中使用其他类型的条件符非常重要。
在构建时,Unity 会为当前构建目标的每个图形 API 编译一组着色器变体。图形 API 和构建目标的每种组合的变体数量取决于着色器源文件以及着色器关键字的使用。
您可以检查您有多少个着色器变体。
Unity 为当前生成目标列表中的每个图形 API 编译一组着色器变体。着色器对于生成目标和图形 API 的每种组合都不同;例如,Unity 为 iOS 上的 Metal 编译着色器与 macOS 上的 Metal 编译着色器不同。
某些着色器程序或关键字可能仅面向给定的图形 API 或给定的生成目标,因此图形 API 和生成目标的每种组合的变体总数可能会有所不同;但是,编译这些变体的过程是相同的。
要查看和编辑当前构建目标的图形 API 列表,请使用玩家设置设置,可让您为 Unity 构建的最终游戏设置各种特定于玩家的选项。更多信息
请参阅术语表窗口或 PlayerSettings API。
Unity 必须确定要为构建目标和图形 API 的当前组合编译多少个着色器程序。
对于构建中包含的每个着色器源文件,Unity 会确定它定义的唯一着色器程序数:
注意: 如果着色器源文件在场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
请参阅术语表,由“资源”文件夹中的某些内容引用,或包含在“图形设置”窗口的“始终包含的着色器”部分中。
当 Unity 确定必须为当前生成目标和图形 API 编译多少个着色器程序时,它会确定必须为每个着色器程序编译多少个着色器变体。
对于每个着色器程序,Unity 会确定导致不同变体的着色器关键字的组合。这包括:
Unity 为着色器程序编译的着色器变体数量是关键字集的乘积;也就是说,Unity 为每个组合编译一个变体,其中包含每个集合中的一个元素。
例如,此集合包含三个着色器变体关键字:
该集包含四个着色器变体关键字:
受这些着色器变体关键字影响的着色器程序将产生以下 12 个变体:
随着添加更多着色器变体关键字集,Unity 编译的变体数量可能会非常迅速地增长。这种非常快速的增长的术语是组合爆炸。
例如,考虑一个相当典型的用例,其中着色器具有多组着色器变体关键字,每个关键字包含两个关键字 (<feature name>_ON和<feature name>_OFF).如果着色器有两组这样的关键字,则会产生四个变体。如果着色器有 10 个这样的关键字集,则会产生 1024 个变体。
编译后,Unity 会自动识别同一 Pass 中的相同变体,并确保这些相同的变体指向相同的字节码。这称为重复数据删除。
重复数据删除可防止同一 Pass 中的相同变体增加文件大小;但是,相同的变体仍然会导致编译过程中浪费工作,并增加运行时的内存使用量和着色器加载时间。考虑到这一点,最好去除不需要的变体。