.. _intervals: ========= 间隔 ========= 间隔是一种根据特殊变量的值是否在特定范围内生成单个 ``shader``多个变体的方法。 可以使用 ``interval`` 关键字从 ``int`` 或 ``float`` 着色器变量创建它们。 请看下面这个例子 .. code-block:: c int var; interval var:below_zero<0, zero<1, positive_less_than_four<4, four<5, five_or_higher; // float也一样 该声明将为着色器创建 5 种排列(``below_zero``, ``zero``, ``positive_less_than_four``, ``four`` 和 ``five_or_higher``),`var`区间本身可以通过特殊的预处理器标记 ``##`` 在 hlsl 块中访问。 .. code-block:: c int var; interval var:below_zero<0, zero<1, positive_less_than_four<4, four<5, five_or_higher; shader example_shader { hlsl { ##if var == five_or_higher ... ##endif } } 必须明白,这种结构并不表示 ``var`` 等于 ``5``,而是表示 ``var``` 在声明的区间 ``five_or_higher`` 内,因此这种语法也适用于 ``float`` 数字。 .. warning:: 请注意,不仅可以通过全局变量创建区间(如上例),还可以通过 ``static`` 和 ``dynamic`` 变量创建区间(在 :ref:`local-variables` 中描述)。 ``static``变量上的间隔只在材料实例化过程中解析一次(选择适当的着色器变量),因此 ``static``变量的着色器变量不会在运行时切换。 然而,每次使用着色器进行渲染时(调用``setStates()``时),``dynamic`` 和全局变量上的时间间隔都会被解析,因为这些变量在运行时会发生变化。 与``static``时间间隔相比,这对 CPU 性能的影响更大。 ------------------ 可选间隔 ------------------ 如果在 HLSL 代码块中使用了区间,则可以将此区间设为 ``optional``。 HLSL 代码中所有使用 ``optional``区间的条件都将被 HLSL 分支取代,从而减少着色器变量的数量。 .. warning:: 带有 ``optional`` 间隔的着色器只能用于 HLSL 块中的条件,并且需要使用 ``-optionalAsBranches`` 标志编译(否则 ``optional`` 间隔将与常规间隔相同)。 此功能只能用于开发构建。 .. code-block:: c int test_optional = 0; optional interval test_optional : zero < 1, one < 2, two < 3, three; shader testMaterial { // ... hlsl { float3 color = float3(0, 0, 0); ##if test_optional == one color = float3(1, 0, 0); ##elif test_optional == two || test_optional == three color = float3(0, 0, 1); ##if test_optional == two color *= 0.5; ##endif ##else color = float3(0, 0, 1); ##endif } } ------- 假设 ------- 着色器变量可在编译时通过 **assuming** 指定一个固定值。这些着色器变量在运行时不会改变,其值在二进制文件中将保持不变。 这样可以减少着色器变量的数量,或禁用特定平台的特定功能。 你可以在着色器编译器的 .blk 配置文件中**假设**间隔。 为此,请在 ``Compile``块内创建一个 ``assume_vars``块,然后按照常规 .blk 语法指定您想要的假设: .. code-block:: c Compile { // ... assume_vars { include common_assumes.blk supports_sh_6_1:i = 0 static_shadows_custom_fxaa:i=0 grass_use_quads:i=0 bloom_tex:i = 1 } } .. note:: 通过假定一个纹理,例如 ``bloom_tex:i = 1``,您可以声明该纹理永远不会是 ``NULL``。 **假设语句** 您可以在 DSHL 着色器中使用 ``assume interval_name = interval_value;``语句强制固定时间间隔。 当不同着色器共享相同的时间间隔时,这对于禁用不必要的着色器变量非常有用。 .. code-block:: c include "deferred_shadow_common.dshl" shader deferred_shadow_classify_tiles { assume use_ssss = off; // ... }