.. _materials: ********* 材质 ********* 材质是着色器和资源(漫反射、法线和其他参数)的组合。 通常情况下,多个资产共享相同的着色器,但需要具有不同的纹理和属性。 在这种情况下,每个资产都将拥有自己的材质*实例*和特定资源。 DSHL 有一种方法可以在着色器中以通用的、非特定资产的方式访问这些纹理。 -------- 纹理 -------- 可以使用 ``material`` 关键字引用纹理。 作为着色器创建者,只需在代码中引用这些插槽,即可指定着色器必须有多少个 ``material.texture[..]`` 插槽。 然后,在编译着色器后,引用的纹理插槽将出现在着色器的 bindump 中。 例如,在 Asset Viewer 材质编辑器中选择着色器时,这些插槽就会显示出来,你就可以为它们指定想要的纹理。 使用示例 .. code-block:: c shader materials_example { texture diffuse = material.texture.diffuse; texture normal = material.texture[1]; // 至此,材质纹理通道已经定义,并可在资产查看器中查看 (ps) { diffuse_tex@static = diffuse; normal_tex@static = normal; } // 现在可以通过 hlsl{} 块访问这些纹理了 } .. note:: ``material.texture.diffuse`` 等同于 ``material.texture[0]`` .. _material-parameters: ---------- 参数 ---------- 除纹理外,材质还可以包含任意参数。 您可以在着色器中使用 “静态”( ``static``)或 “动态”( ``dynamic``)关键字将这些参数声明为局部变量,请查看 :ref:`local-variables` 了解两者的区别。 使用一些有意义的默认值来初始化它们是一种好的做法。 与纹理类似,这些参数将保存到着色器绑定块中,并可在重新编译着色器后在 “资产查看器 ”中进行编辑。 .. code-block:: c static float some_parameter = 1.5; dynamic float4 another_parameter = (1, 2, 3, 4); (ps) { some_parameter@f1 = some_parameter; another_parameter@f4 = another_parameter; } .. warning:: 如果没有必要,请勿使用 ``dynamic`` 参数,因为这会带来更多开销。请参阅 :ref:`local-variables` 获取更多信息。 ------------------- 双面渲染 ------------------- DSHL 中有两个特殊的材质参数: ``two_sided`` 和 ``real_two_sided``。 这两个参数默认存在于**每个**材质中,并可在资产查看器中设置。 这些参数在 DSHL 中就像布尔值: 您可以对它们执行条件语句 :ref:`conditionals` (这将导致创建着色器变体)。 .. code-block:: c if (two_sided) { cull_mode = none; } ``two_sided`` 是一个提示,表示该材质的每个三角形都应从两侧渲染,因此应禁用该着色器的剔除功能(示例中已禁用)。 ``real_two_sided`` 是一个提示,表示将使用一个特殊的网格来渲染此着色器: 每个三角形都会被复制和翻转,因此网格的两面都会被渲染。 请注意,在这种情况下无需禁用剔除功能,因为我们使用的是*真正*的双面网格(因此得名)。 ---------------------- render_stage 指令 ---------------------- 可以使用 ``render_stage `` 为着色器指定渲染阶段。 .. code-block:: c shader materials_example { render_stage opaque; // ... } 它用于根据渲染阶段区分 ``ShaderMesh`` 类中的不同材质(该类可包含许多材质和网格)。 (类中的不同材质(该类可能包含许多材质和网格)。 例如,您可以调用 ``ShaderMesh::getElems(STG_opaque)`` 从一个 ``ShaderMesh`` 中获取所有在其 DSHL 着色器中指定了 ``render_stage opaque`` 的材质。 如果您希望按特定顺序绘制材质,这将非常有用。 可用的阶段 - ``opaque`` -- 不透明 - ``atest`` -- alpha 测试 - ``imm_decal`` -- 即时贴花 - ``decal`` -- 贴花 - ``trans`` -- 半透明 - ``distortion`` -- 扭曲 还有一个 ``render_trans`` 传统别名用于 ``render_stage trans``。 **Color write mask** 可以使用 ``static int`` 材质参数来设置颜色遮罩 :ref:`color-write-mask`。 请注意,您需要同时为 **所有** 渲染目标指定遮罩。 .. code-block:: c static int writemask = 1904; // = (0b0111 << 4) | (0b0111 << 8) // 其中 0b0111 是 RGB 的位掩码 color_write = static writemask; // 1904 的写掩码相当于 // color_write[0] = rgb; // color_write[1] = rgb; 此示例将渲染目标 1 和 2 的颜色写入掩码设置为 ``rgb``(如果您使用的是 ``writemask`` 材质参数的默认值)。 其他渲染目标的遮罩值为 ``0b0000``,这意味着不会绘制任何内容。