Unity3D:在 HLSL 中声明和使用着色器关键字
推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生
在 HLSL 中声明和使用着色器关键字
本页包含有关在 HLSL 代码中使用着色器关键字的信息。有关着色器关键字的一般介绍,请参阅着色器关键字。有关在着色器图中声明和使用着色器关键字的信息,请参阅关键字。
在 HLSL 代码中,使用指令声明着色器关键字,并使用指令指示着色器代码的一部分取决于着色器关键字的状态。可以在常规图形着色器(包括 Surface 着色器)和计算着色器中使用着色器关键字。#pragma#if
声明着色器关键字
若要声明着色器关键字,请在 HLSL 代码中使用以下指令之一:#pragma
命令 | 描述 |
---|---|
#pragma multi_compile | 声明一组关键字。 默认情况下,这些关键字具有全局范围并影响所有着色器阶段。 构建过程包括此集中的所有关键字。 |
#pragma shader_feature | 声明一组关键字,并指示编译器编译未启用这些关键字的变体。 默认情况下,这些关键字具有全局范围并影响所有着色器阶段。 生成过程包括此集中在生成时使用的关键字。 |
有关 和 之间的区别的信息以及有关何时使用哪一个的指南,请参阅 Shader 关键字。#pragma multi_compile#pragma shader_feature
注意:如果在“图形设置”窗口中将着色器添加到“始终包含着色器”列表中,Unity 将包含构建中所有集中的所有关键字,即使这些关键字是使用 .#pragma shader_feature
您还可以向这些指令添加后缀以修改其行为:
- 添加以指示一组关键字具有本地范围,并且不能被全局关键字覆盖;否则,关键字具有全局范围,并且可以被全局关键字覆盖。有关详细信息,请参阅着色器关键字:全局和局部范围。
可以将此后缀添加到 或 指令;例如,和 有效。_local#pragma multi_compile#pragma shader_feature#pragma multi_compile_local#pragma shader_feature_local
- 添加 、、、、 或 以指示一组关键字仅影响给定的着色器阶段,这可以减少不需要的着色器变体的数量。有关详细信息,请参阅着色器关键字:特定于阶段的关键字。
您可以将这些后缀添加到 or 指令中,无论是独立添加还是在修饰符之后;例如,并且有效。_vertex_fragment_hull_domain_geometry_raytracing#pragma multi_compile#pragma shader_feature_local#pragma multi_compile_vertex#pragma shader_feature_local_fragment
此外,还有一些“快捷方式”变体可以添加预定义的关键字集。有关这些内容的详细信息,请参阅multi_compile快捷方式。#pragma multi_compile
声明一组关键字
在集合中声明关键字。集合包含互斥关键字。
若要声明一组关键字,请使用 or 指令,后跟以空格分隔的关键字列表。#pragma multi_compile#pragma_shader_feature
此示例演示如何声明一组四个关键字:
#pragma multi_compile QUALITY_LOW QUALITY_MEDIUM QUALITY_HIGH QUALITY_ULTRA
在内部,这通过使用指令来工作。Unity 编译着色器时,会生成四个变体:一个定义QUALITY_LOW,一个定义QUALITY_MEDIUM,一个定义QUALITY_HIGH,一个定义QUALITY_ULTRA。在运行时,Unity 会根据启用了哪些关键字使用适当的变体。#define
当您用于声明一组关键字时,Unity 还会编译一个变体,其中未定义该集中的任何关键字。这允许您在不使用其他关键字的情况下定义行为。减少关键字的数量在几个方面是有益的:它可以减少 Unity 编译的变体总数,从而提高构建时间和运行时性能;它减少了着色器使用的关键字总数,从而阻止它达到着色器关键字限制;它使从 C# 脚本管理关键字状态变得更加简单,因为要启用和禁用的关键字更少。#pragma shader_feature
此示例演示如何声明仅包含一个关键字的集合:
#pragma shader_feature EXAMPLE_ON
您还可以指示 Unity 在使用 时执行此操作。为此,请将“blank”关键字添加到集合中,其名称为一个或多个下划线 (),如下所示:#pragma multi_compile_
#pragma multi_compile __ EXAMPLE_ON
声明多组关键字
您可以声明多组关键字来表示不同的功能。为此,请使用多个 or 指令。#pragma multi_compile#pragma_shader_feature
此示例演示如何声明一组四个关键字和另一组三个关键字:
#pragma multi_compile QUALITY_LOW QUALITY_MEDIUM QUALITY_HIGH QUALITY_ULTRA
#pragma multi_compile COLOR_RED COLOR_GREEN COLOR_BLUE
限制
声明关键字集的方式存在一些限制:
- 您不能在同一集中多次包含同一关键字;但是,您可以在不同的集合中声明相同的关键字。
- 不能在着色器程序中多次声明同一组关键字。
- 着色器可以使用的关键字数量有限制。着色器源文件中声明的每个关键字及其依赖项都计入此限制。有关详细信息,请参阅着色器关键字限制。
使用着色器关键字
若要编译仅在启用给定着色器关键字时使用的代码,请使用如下所示的指令:#if
// Declare a set of keywords
#pragma multi_compile QUALITY_LOW QUALITY_MEDIUM QUALITY_HIGH QUALITY_ULTRA
#if QUALITY_ULTRA
// Code here is compiled for variants that are used when the keyword QUALITY_ULTRA is enabled
#endif
这是因为 Unity 的着色器编译器将禁用的着色器变体关键字表示为值为 .0
注: 您还可以使用#if
、#elif
、#else
和#endif
预处理器指令,以及#ifdef
和#ifndef
预处理器指令以及使用着色器变体的关键字;但是,如果这样做,将来将更难转换代码以使用动态分支。
此外,and 指令可以将关键字作为参数,以便它们仅适用于启用了给定关键字的变体。有关详细信息,请参阅在 HLSL 中面向着色器模型和 GPU 功能。#pragma require#pragma target
multi_compile快捷方式
Unity 提供了几种“快捷方式”表示法,用于声明着色器关键字。
以下快捷方式与内置渲染管线中的光照、阴影和光照贴图相关:
multi_compile_fwdbase
添加了这组关键字:定向LIGHTMAP_ON DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON SHADOWS_SCREEN SHADOWS_SHADOWMASK LIGHTMAP_SHADOW_MIXING LIGHTPROBE_SH。PassType.ForwardBase 需要这些变体。multi_compile_fwdbasealpha
添加了这组关键字:定向LIGHTMAP_ON DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON LIGHTMAP_SHADOW_MIXING VERTEXLIGHT_ON LIGHTPROBE_SH。PassType.ForwardBase 需要这些变体。multi_compile_fwdadd
添加这组关键字:点方向点POINT_COOKIE DIRECTIONAL_COOKIE。PassType.ForwardAdd需要这些变体。multi_compile_fwdadd_fullshadows
添加了这组关键字:点方向点POINT_COOKIE DIRECTIONAL_COOKIE SHADOWS_DEPTH SHADOWS_SCREEN SHADOWS_CUBE SHADOWS_SOFT SHADOWS_SHADOWMASK LIGHTMAP_SHADOW_MIXING。这与 相同,但这增加了灯光具有实时阴影的功能。multi_compile_fwdadd
multi_compile_lightpass
添加了这组关键字:点方向点POINT_COOKIE DIRECTIONAL_COOKIE SHADOWS_DEPTH SHADOWS_SCREEN SHADOWS_CUBE SHADOWS_SOFT SHADOWS_SHADOWMASK LIGHTMAP_SHADOW_MIXING。这实际上是与实时光照和阴影相关的所有功能的包罗万象的快捷方式,但光照探针除外。multi_compile_shadowcaster
添加这组关键字:SHADOWS_DEPTH SHADOWS_CUBE。PassType.ShadowCaster需要这些变体。multi_compile_shadowcollector
添加这组关键字:SHADOWS_SPLIT_SPHERES SHADOWS_SINGLE_CASCADE。它还编译没有任何这些关键字的变体。屏幕空间阴影需要这些变体。multi_compile_prepassfinal
添加以下一组关键字:LIGHTMAP_ON DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON UNITY_HDR_ON SHADOWS_SHADOWMASK LIGHTPROBE_SH。它还编译没有任何这些关键字的变体。PassType.LightPrePassFinal 和 PassType.Deferred 需要这些变体。
以下快捷方式与其他设置相关:
multi_compile_particles
添加了与内置粒子系统相关的关键字:SOFTPARTICLES_ON。它还编译没有此关键字的变体。有关更多信息,请参阅内置粒子系统。multi_compile_fog
添加了这组与雾相关的关键字:FOG_LINEAR、FOG_EXP FOG_EXP2。它还编译没有任何这些关键字的变体。您可以在图形设置窗口中控制此行为。multi_compile_instancing
添加与实例化相关的关键字。如果着色器使用过程实例化,则会添加以下一组关键字:INSTANCING_ON PROCEDURAL_ON。否则,它将添加此关键字:INSTANCING_ON。它还编译没有任何这些关键字的变体。您可以在图形设置窗口中控制此行为。
这些快捷方式中的大多数都包含多个关键字。如果您知道项目不需要它们,则可以使用 删除其中一些。例如:#pragma skip_variants
# pragma multi_compile_fwdadd
# pragma skip_variants POINT POINT_COOKIE
这会告诉编译器删除关键字或从其他指令中删除。POINTPOINT_COOKIE
由3D建模学习工作室整理翻译,转载请注明出处!