Version: 2020.3
ShaderLab:定义 Shader 对象
ShaderLab:分配回退

ShaderLab:定义材质属性

本页面包含有关在 ShaderLab 代码中使用 Properties 代码块为 Shader 对象定义材质属性的信息。

概述

在 ShaderLab 代码中,可以定义材质属性。材质属性是 Unity 作为材质资源一部分存储的属性。这使美术师可以创建、编辑和共享具有不同配置的材质。

如果使用材质属性:

  • 可以通过对材质调用函数(例如 Material.SetFloat)来获取或设置 Shader 对象中的变量值。
  • 可以使用材质 Inspector 查看和编辑值。
  • Unity 会将进行的更改保存为材质资源的一部分,因此它们可在会话之间持续存在。

如果不使用材质属性: * 仍可以通过对材质调用函数来获取或设置 Shader 对象中的变量值。 * 这些值没有可视化编辑器。 * 更改不会在会话之间持续存在。

通常_不_创建材质属性的唯一情况是如果要完全使用脚本设置着色器属性值(例如,如果在制作程序化内容)、如果无法将属性设为材质属性或者如果不希望在 Inspector 中编辑它们。

渲染管线兼容性

功能名称 内置渲染管线 通用渲染管线 (URP) 高清渲染管线 (HDRP) 自定义 SRP
ShaderLab:Properties 代码块
在 HLSL 代码中,必须将每材质变量置于同一个 CBUFFER 中以实现 SRP Batcher 兼容性。

在 HLSL 代码中,必须将每材质变量置于同一个 CBUFFER 中以实现 SRP Batcher 兼容性。

在 HLSL 代码中,必须将每材质变量置于同一个 CBUFFER 中以实现 SRP Batcher 兼容性。

使用 Properties 代码块

要在 ShaderLab 中将材质属性分配给 Shader 对象,请在 Shader 代码块内放置一个 Properties 代码块。

签名 功能
Properties
{
    <Material property declaration>
    <Material property declaration>
}
将给定属性保存为材质资源的一部分,并在渲染期间使用存储在材质资源中的值。
Properties 代码块可以包含任意数量的材质属性声明。

材质属性声明

所有材质属性声明都遵循以下基本格式:

[optional: attribute] name("display text in Inspector", type name) = default value

确切语法因类型而异。

本节包含以下相关信息:

按类型划分的材质属性声明语法

类型名称和默认值的语法取决于属性的类型。

在着色器代码中,通常所有属性名称都以下划线字符开头。本页面上的示例遵循此约定。

类型 示例语法 注释
Int _ExampleName ("Int display name", Int) = 1 注意:尽管名称如此,但是此类型实际上受浮点数支持。
Float _ExampleName ("Float display name", Float) = 0.5

_ExampleName ("Float with range", Range(0.0, 1.0)) = 0.5
范围滑动条的最大值和最小值包含在内。
Texture2D _ExampleName ("Texture2D display name", 2D) = "" {}

_ExampleName ("Texture2D display name", 2D) = "red" {}
将以下值置于默认值字符串中可使用 Unity 的内置纹理之一:“white”(RGBA:1,1,1,1)、“black”(RGBA:0,0,0,1)、“gray”(RGBA:0.5,0.5,0.5,1)、“bump”(RGBA:0.5,0.5,1,0.5)或“red”(RGBA:1,0,0,1)。

如果将该字符串留空或输入无效值,则它默认为 “gray”。

注意:这些默认纹理在 Inspector 中不可见。
Texture2DArray _ExampleName ("Texture2DArray display name", 2DArray) = "" {} 有关更多信息,请参阅纹理数组
Texture3D _ExampleName ("Texture3D", 3D) = "" {} 默认值为 “gray”(RGBA:0.5,0.5,0.5,1)纹理。
Cubemap _ExampleName ("Cubemap", Cube) = "" {} 默认值为 “gray”(RGBA:0.5,0.5,0.5,1)纹理。
CubemapArray _ExampleName ("CubemapArray", CubeArray) = "" {} 请参阅立方体贴图数组
Color _ExampleName("Example color", Color) = (.25, .5, .5, 1) 这会在着色器代码中映射到 float4。

材质 Inspector 会显示一个拾色器。如果更愿意将值作为四个单独的浮点数进行编辑,请使用 Vector 类型。
Vector _ExampleName ("Example vector", Vector) = (.25, .5, .5, 1) 这会在着色器代码中映射到 float4。

材质 Inspector 会显示四个单独的浮点数字段。如果更愿意使用拾色器编辑值,请使用 Color 类型。

Reserved material property names

Unity has some reserved names for material properties. When you create a material property with one of these names, Unity performs predefined operations. Do not use these names unless you intend to use this functionality.

名称 示例语法 功能
_TransparencyLM _TransparencyLM ("Transmissive Texture", 2D) = "white" {} Enables custom RGB transparency during lightmapping.

For more information, see Lightmapping and shaders.

材质属性特性

材质属性声明可以具有一个可选特性,用于告知 Unity 如何处理它们。

除了此处列出的特性外,可以使用相同语法向材质属性添加 MaterialPropertyDrawer。通过这些内容可以控制材质属性在 Inspector 窗口中的显示方式。

属性 功能
[Gamma] 指示浮点数或矢量属性使用 sRGB 值,这意味着如果项目中的颜色空间需要,则它必须与其他 sRGB 值一起转换。有关更多信息,请参阅着色器程序中的属性
[HDR] 指示纹理或颜色属性使用高动态范围 (HDR) 值。

对于纹理属性,如果分配了 LDR 纹理,则 Unity 编辑器会显示警告。对于颜色属性,Unity 编辑器会使用 HDR 拾色器编辑此值。
[HideInInspector] 告知 Unity 编辑器在 Inspector 中隐藏此属性。
[MainTexture] 为材质设置主纹理,可以使用 Material.mainTexture 进行访问。

默认情况下,Unity 将具有属性名称 _MainTex 的纹理视为主纹理。如果纹理具有不同的属性名称,但希望 Unity 将它视为主纹理,请使用此特性。

如果多次使用此特性,则 Unity 会使用第一个属性并忽略后续属性。

注意:使用此特性设置主纹理时,如果使用纹理串流调试视图模式或自定义调试工具,则该纹理在游戏视图中不可见。
[MainColor] 为材质设置主色,可以使用 Material.color 进行访问。

默认情况下,Unity 将具有属性名称 _Color 的颜色视为主色。如果您的颜色具有其他属性 (property) 名称,但您希望 Unity 将这个颜色视为主色,请使用此属性 (attribute)。如果您多次使用此属性 (attribute),则 Unity 会使用第一个属性 (property),而忽略后续属性 (property)。
[NoScaleOffset] 告知 Unity 编辑器隐藏此纹理属性的平铺和偏移字段。
[Normal] 指示纹理属性需要法线贴图。

如果分配了不兼容的纹理,则 Unity 编辑器会显示警告。
[PerRendererData] 指示纹理属性将来自每渲染器数据,形式为 MaterialPropertyBlock

材质 Inspector 会将这些属性显示为只读。

将材质属性与 C# 代码结合使用

材质属性在 C# 代码中通过 MaterialProperty 类进行表示。

要访问 HLSL 代码中定义的变量,可以调用 Material.GetFloatMaterial.SetFloat。还有其他类似的方法;请参阅材质 API 文档以获取完整列表。使用这些 API 访问 HLSL 变量时,变量是否为材质属性并不重要。

在 Unity 编辑器中,可以控制材质属性在 Inspector 窗口中的显示方式。为此,最简单的方法是使用 MaterialPropertyDrawer。对于更复杂的需求,可以使用 MaterialEditorMaterialPropertyShaderGUI 类。有关为着色器创建自定义 GUI 的更多信息,请参阅 ShaderLab:分配自定义编辑器

在 ShaderLab 代码中使用材质属性设置变量

要在 ShaderLab 代码中通过材质属性设置变量的值,请在 ShaderLab 代码中将材质属性名称置于方括号中。

此示例代码演示使用材质属性设置 ShaderLab Offset 命令的 units 值的语法。

Shader "Examples/MaterialPropertyShaderLab"
{
    Properties
    {
        // 在材质 Inspector 中更改此值以影响 Offset 命令的值
        _OffsetUnitScale ("Offset unit scale", Integer) = 1
    }
    SubShader
    {
        // 此处是定义 SubShader 其余部分的代码

        Pass
        {
            Offset 0, [_OffsetUnitScale]

           // 此处是定义 Pass 其余部分的代码
        }
    }
}

在 HLSL 代码中使用材质属性设置变量

要使用材质属性在 HLSL 代码中设置变量的值,请为材质属性提供与着色器属性相同的名称。

可以在以下文章中查看此技术,其中包括正常工作的代码示例:

ShaderLab:定义 Shader 对象
ShaderLab:分配回退