DreamShaderLang
插件参考DreamShaderLang

输出绑定

输出绑定

输出绑定

DreamShader » DreamShaderLang » 输出绑定

位于 Shader 的 Outputs 部分中的语句,用于将图值连接到材质属性输入,或连接到显式创建的 UMaterialExpression 上的引脚。

声明于.dsm — 仅在 Shader 块的 Outputs 部分内
类型语句
生成到 UMaterial 的属性输入、或到所创建输出节点的连接

绑定的 2.0 写法是对材质参数的赋值,m.EmissiveColor = Color; — 参见 DreamShaderLang 2.0;dsc migrate 会以该方式重写 .dsm。

概要

Outputs [=]
{
    <output-declaration>…
    <output-binding>…
}
output-declaration := <type> <name> [ = <expression> ] ;

output-binding     := Base. <target> = <source> ;
                    | Expression( <key> = <value> [, <key> = <value> ]… ) . Pin[ <index> ] = <source> ;
                    | Expression( <key> = <value> [, <key> = <value> ]… ) { <pin-binding>… } [;]

pin-binding        := Pin[ <index> ] = <source> ;

<source> 是一个表达式 (自 2.0.0 起):可以是 1.x 写法中的输出变量名,也可以是 Graph 表达式可以是的任何内容 — Base.FrontMaterial = Substrate.Layer(Coat, Body, 0.01);。它在 Graph 运行之后读取,并遵循 1.x Graph 表达式的规则(DSH2200–DSH2222)。<index> 前后的 [ 和 ] 是字面量。

该部分按其起始标记逐个标记、逐条语句地读取:

语句起始于读取为
两个词,<type> <name>输出声明,带或不带初始化器 (初始化器自 1.3.4 起)
Base . <name> =材质属性绑定
Expression ( … ) .表达式绑定的语句形式
Expression ( … ) {块形式 (自 1.9.0 起)
其他任何内容,包括除 Expression( … ) 之外的任何内容之后的 {DSH3266 — 或当它作为 Expression( … ) 目标开始时为 DSH3267

Expression( … ) { … } 是 Outputs 内部唯一会打开花括号的构造,正如 Group("Name") { … } 是 Properties 内部的唯一构造。

声明会成为材质入口的局部变量,位于 Graph 之前;没有初始化器的声明从零开始,如同 1.x(纹理或 Substrate 输出没有零值,必须由 Graph 赋值)。绑定会成为 Graph 之后对材质的赋值。声明语法见 Inputs / Outputs / Results。

绑定目标种类

目标文本起始于种类含义
Base.(不区分大小写)材质属性连接到 UMaterial 的某个属性输入
Expression((不区分大小写)表达式输入创建一个 UMaterialExpression 并连接到其某个输入引脚
其他任何内容—DSH3266

Base.<target> 目录

(自 2.0.0 起) 名称是引擎自身的名称:引擎材质属性表中每个具有 EMaterialProperty 的属性,均使用引擎赋予其的名称,外加下面的 1.x 别名。名称进行精确匹配;在 1.x 文件中,仅忽略大小写即可匹配的名称仍会解析,并给出警告 DSH5276(旧规则 L19)。不匹配任何内容的名称会引发 DSH5200。

1.x 文档中记载的写法,以及各自解析到的属性和值类型;引擎的表可能包含更多名称,那些名称也会解析:

Base. 写法EMaterialProperty值类型
BaseColorMP_BaseColorFloat3
MaterialAttributes, AttributesMP_MaterialAttributesMaterialAttributes
FrontMaterial (自 UE 5.4 起)MP_FrontMaterialSubstrate
EmissiveColor, EmissiveMP_EmissiveColorFloat3
OpacityMP_OpacityFloat1
OpacityMaskMP_OpacityMaskFloat1
MetallicMP_MetallicFloat1
SpecularMP_SpecularFloat1
RoughnessMP_RoughnessFloat1
NormalMP_NormalFloat3
AmbientOcclusion, AOMP_AmbientOcclusionFloat1
RefractionMP_RefractionFloat3
WorldPositionOffset, WPOMP_WorldPositionOffsetFloat3
PixelDepthOffset, PDOMP_PixelDepthOffsetFloat1
SubsurfaceColorMP_SubsurfaceColorFloat3
ClearCoatMP_CustomData0Float1
ClearCoatRoughnessMP_CustomData1Float1
CustomData0MP_CustomData0Float1
CustomData1MP_CustomData1Float1
DiffuseColorMP_DiffuseColorFloat3
SpecularColorMP_SpecularColorFloat3
SurfaceThicknessMP_SurfaceThicknessFloat1
DisplacementMP_DisplacementFloat1
CustomizedUV0 … CustomizedUV7MP_CustomizedUVs0 … MP_CustomizedUVs7Float2
AnisotropyMP_AnisotropyFloat1
TangentMP_TangentFloat3

[!WARNING] 1.x 还接受 CustomizedUVs0 … CustomizedUVs7。引擎将这些属性命名为 CustomizedUV0 … CustomizedUV7,因此 s 写法是 DSH5200 (自 2.0.0 起);请写作 CustomizedUV<n>。

[!NOTE] ClearCoat 和 CustomData0 是同一个材质属性,ClearCoatRoughness 和 CustomData1 也是如此。在同一个 Shader 中绑定一对写法的两者会写入同一个输入两次;后一条语句生效,且不给出诊断。

仅分支版目标

这些属性仅存在于 Moon 引擎分支中;在标准 Unreal 构建中它们是 DSH5200。Mooa… 别名是该分支重命名前的写法。

Base. 写法EMaterialProperty值类型
MoonEncodedAttribute0, MooaEncodedAttribute0MP_MoonEncodedAttribute0Float4
MoonEncodedAttribute1, MooaEncodedAttribute1MP_MoonEncodedAttribute1Float4
MoonEncodedAttribute2, MooaEncodedAttribute2MP_MoonEncodedAttribute2Float4
MoonEncodedAttribute3, MooaEncodedAttribute3MP_MoonEncodedAttribute3Float4
MoonEncodedAttribute4, MooaEncodedAttribute4MP_MoonEncodedAttribute4Float4

具有副作用的目标

Base.MaterialAttributes

(自 1.2.5 起)

绑定 Base.MaterialAttributes 会设置 UMaterial::bUseMaterialAttributes = true — 即使用材质属性复选框 — 从而使材质暴露单个属性输入,而不是各个单独的属性输入。所绑定的值必须是 MaterialAttributes 值;其他任何值都会引发 DSH4228。

有关该值类型、成员写入和读取,请参见 MaterialAttributes。

Base.FrontMaterial

(自 UE 5.4 起)

所绑定的值必须是 Substrate 值,由 Substrate.* 内置函数或 Substrate 语法糖生成;其他任何值都会引发 DSH4228。

(自 2.0.0 起) FrontMaterial 是普通属性:1.x 生成器对它施加的额外规则 —— 强制 着色模型为 Substrate、拒绝除 "Substrate" 以外的显式 ShadingModel、 拒绝它与 Base.MaterialAttributes 并列、以及整个表面的 Custom 节点路径 —— 均不再适用。在材质需要它的 Settings 中写入 ShadingModel = "Substrate";(在 UE 5.3 上,该设置为 DSH7128)。针对旧版属性编写的材质在 Substrate 项目中如何读取,由 Substrate = 设置决定 —— 请参见 Substrate sugar。

Outputs = {
    Substrate Surface;
    Base.FrontMaterial = Surface;
}
Graph = {
    Surface = Substrate.Unlit(EmissiveColor = Color);
}

Expression( … ).Pin[i] 目标

非 Base 绑定形式会创建一个任意 UMaterialExpression —— 实际上是一个自定义输出 节点 —— 并将源连接到其某个输入引脚。

Expression( Class = "<ExpressionClass>" [, <key> = <value> ]… ) . Pin[ <index> ] = <source> ;

目标的两种形式都会成为材质入口中的一个 UE.Expression(Class = "…", …) 节点调用, 因此目标受与 Graph 中 UE.Expression 调用相同的规则约束。

要求,按检查顺序排列

要求违反时的代码
头部为 Expression( <key> = <value> [, …] ),每个值非空DSH3267
没有键被写入两次(比较时忽略大小写)DSH3267
存在 Class 参数DSH3267
) 之后为 .Pin[<index>] = <source> 或 { … } 块,索引为整数字面量DSH3267
= 后面有内容DSH3270
该类是引擎拥有的类DSH5212
该索引指向该类的某个输入引脚DSH5285
其他每个参数都指向该类的某个引脚或属性DSH5213

Class 匹配时忽略大小写。下面的复用键会将其他每个键转为小写并去掉每个 值的引号;节点调用按原样携带每个参数。

类解析

(自 2.0.0 起) 类在引擎的表达式目录中按精确名称查找,顺序如下:短名称(ThinTranslucentMaterialOutput)、类名称 (MaterialExpressionThinTranslucentMaterialOutput)、类路径 (/Script/Engine.MaterialExpressionThinTranslucentMaterialOutput)、前面加上 MaterialExpression 的短名称,以及带有其 U (UMaterialExpressionThinTranslucentMaterialOutput)的 C++ 名称,后者 1.x 会拒绝。在 1.x 文件中,若某名称 仅忽略大小写地与一个类匹配,也能解析,并给出警告 DSH5276。其他任何情况都是 DSH5212。同样的规则记录在 UE.Expression 上。

其他参数

除 Class 以外的每个参数都会与该类进行匹配:先匹配输入引脚,再匹配反射 属性。值会被读取为数字、true / false、带引号的字符串或裸词,裸词指向 图中的一个值,或者对于枚举属性,指向一个枚举项。

(自 2.0.0 起) 指向输入引脚的参数会像 Pin[<index>] 那样连接该引脚; 1.x 会拒绝它。将同一个引脚双向连接会得到 DSH4215。既不是引脚也不是属性的名称会得到 DSH5213 —— 但在 1.x 文件中针对图值的情况除外,该名称会在节点存在后 按该名称连接(DSH5291,信息; 当构建出的节点没有该引脚时为 DSH8212)。属性无法接受的值会得到 DSH8213。

引脚索引与节点复用

  • Pin[<index>] 是按引擎声明顺序对节点输入列表的从零开始的索引。Expression(Class="ThinTranslucentMaterialOutput").Pin[0] 为 TransmittanceColor, .Pin[1] 为 SurfaceCoverage。超出末尾的索引会得到 DSH5285。
  • 节点的每个引脚可以在语句形式和块形式中绑定一次: DSH3268。
  • 节点在同一个 Outputs 区段内按类加排序后的参数列表去重。两个 其 Expression( … ) 规格完全相同的绑定共享一个节点并绑定不同引脚; 任何参数不同就会创建第二个节点,同一个头部出现在第二个 Outputs 区段中也是如此。
  • 源必须是图中的一个值:没有任何声明指向的名称会得到 DSH4200,而引脚无法接受的值会得到 DSH5214。必需引脚未连接会得到警告 DSH5279。
  • 节点落在哪里是图形布局的职责。

此形式最常用于自定义输出时的引脚顺序:

ClassPin[i],按顺序
ThinTranslucentMaterialOutput0 TransmittanceColor、1 SurfaceCoverage
ClearCoatNormalCustomOutput0 Input
RuntimeVirtualTextureOutput0 BaseColor、1 Specular、2 Roughness、3 Normal、4 WorldHeight、5 Opacity、6 Mask、7 Displacement、8 Mask4

任何其他 UMaterialExpressionCustomOutput 子类也以相同方式工作;其引脚顺序是引擎声明输入的顺序,材质编辑器在节点上从上到下显示该顺序。一个 完整的 RuntimeVirtualTextureOutput 文件是示例 15。

Outputs = {
    float3 Transmittance;
    float  Coverage;
    float3 CoatNormal;

    // Both statements reuse one ThinTranslucentMaterialOutput node.
    Expression(Class="ThinTranslucentMaterialOutput").Pin[0] = Transmittance;
    Expression(Class="ThinTranslucentMaterialOutput").Pin[1] = Coverage;

    // A different class → a second node.
    Expression(Class="ClearCoatNormalCustomOutput").Pin[0] = CoatNormal;
}

块形式

(自 1.9.0 起)

一个引脚众多的终端节点在语句形式中必须为每个引脚重复其整个 Expression( … ) 规格, 而且由于该规格就是去重键,一个被遗忘的参数会悄无声息地把节点拆成两个。块形式只需写入一次规格:

Expression( <key> = <value> [, <key> = <value> ]… )
{
    Pin[ <index> ] = <source> ;
    …
}
Outputs = {
    float _PhaseG_Out;
    float _PhaseG2_Out;
    float _PhaseBlend_Out;

    Expression(Class="VolumetricAdvancedMaterialOutput",
        PerSamplePhaseEvaluation="false",
        MultiScatteringApproximationOctaveCount=0,
        bGroundContribution="false")
    {
        Pin[0] = _PhaseG_Out;
        Pin[1] = _PhaseG2_Out;
        Pin[2] = _PhaseBlend_Out;
    }
}

单节点保证

块形式和语句形式读入为同一种东西:每个复用键对应一个节点调用,该键下的每个 引脚都绑定为其参数之一。一个块的所有引脚共享头部的类和 参数列表,这正好就是复用键 —— 因此一个包含 N 个引脚的块 总是产生一个节点。参数列表不会在各个引脚之间发生偏移,因为只有一份 副本。

其他一切都不变:块形式和语句形式在下游无法区分。它们 共享相同的类解析、相同的参数检查、相同的引脚索引检查和相同的 诊断。

规则

规则详情
什么可以打开花括号仅 Expression( … )。变量或 Base. 目标之后的 { 是 DSH3266;在 Expression( … ).Pin[i] 目标之后它是 DSH3267
头部形态Expression( … ),且闭合的 ) 之后没有任何内容——引脚选择器在块内按每条语句书写
内部语句仅 Pin[ <index> ] = <source> ;——否则为 DSH3267
注释与空行块内任意位置均可
空块DSH3269——不绑定任何引脚的块不会创建任何内容,因此会被拒绝而非忽略
未闭合的块解析会一直运行到文件末尾:DSH2150
结尾的 ;在闭合的 } 之后可选,如同 Group("Name") { … } 之后一样
重复同一个节点可以多次书写一个块,并且可以在同一个 Outputs 节内与语句形式的绑定自由混用

混用两种形式

一个块和一条在类和参数列表上一致的松散语句寻址的是同一个节点,因此它们填充该节点的不同引脚:

Outputs = {
    float3 Transmittance;
    float  Coverage;

    Expression(Class="ThinTranslucentMaterialOutput")
    {
        Pin[0] = Transmittance;
    }

    // Same specification → same node → this fills its other pin.
    Expression(Class="ThinTranslucentMaterialOutput").Pin[1] = Coverage;
}

每个引脚一次

“一个引脚只能绑定一次”的规则在读取该节时检查,涵盖两种形式,以类 + 排序后的参数列表 + 引脚索引为键。同一个引脚的第二次绑定是 DSH3268,在第二次绑定时报告。

[!NOTE] 参数列表不同的两个块——哪怕只差一个参数——是两个不同的节点,并且各自有自己的 Pin[0]。这不是双重绑定,也不会被诊断;这正是使语句形式中的重复变得危险的同一规则。

诊断

1.x 解析器针对此形式的代码 DSH3133–DSH3137 不再触发 (自 2.0.0 起):

1.x 代码现在触发
DSH3133——除 Expression( … ) 之外任何内容之后的花括号DSH3266,或 Expression( … ).Pin[i] 目标之后的 DSH3267
DSH3134——未终止的块DSH2150
DSH3135——块中除 Pin[i] = <source>; 之外的语句DSH3267
DSH3136——空块DSH3269
DSH3137——引脚被绑定两次DSH3268

保留名称 return

(自 2.0.0 起) return 是每个文件中的关键字。它不能命名输出声明(DSH3266),也不是绑定源:Base.EmissiveColor = return; 是 DSH2151。1.x 为该名称保留了其全表面 Custom 节点路径,而编译器不再具有该路径。

校验规则

条件代码
声明的类型不是类型DSH4201
在 Outputs 中声明了两次的名称DSH4220
没有任何内容声明的源名称DSH4200
材质没有的 Base. 名称DSH5200
材质引脚无法接受的值;更宽的向量不会被收窄到材质引脚中,即使在 1.x 文件中也不会DSH4228
Expression( … ) 引脚无法接受的值DSH5214

对 Outputs 声明的名称进行 Graph 声明会被读取为对该输出的赋值,这正是 1.x 对其的处理方式。

说明

  • 没有 Outputs 节的 Shader 在构建时会产生警告 DSH2256;既没有 Graph 也没有 Outputs 中任何内容的会被 DSH2255。
  • 绑定和声明可以自由交错;绑定可以引用同一节中稍后声明的变量。
  • 重复的 Outputs 节会追加到两个列表。
  • 在 Shader 中的任何 Outputs 语句上都不接受 [ … ] 元数据块。
  • 每个绑定都会通过一对生成的 NamedReroute 进行路由,其名称按照书写时的 Base. 名称命名为 DS_<pin>_<n>,因此材质根节点在大型图中保持可读。参见 图布局。
  • 绑定到当前着色模型或混合模式不使用的属性不会被诊断——Unreal 只是让该输入不被读取。请检查材质编辑器中灰显的输入。材质完全没有输入的属性是 DSH8217。

诊断

每个诊断都带有它所针对的语句的行和列。

读取该节

代码触发条件
DSH3266该节不是以 { 打开的;语句既不是声明也不是绑定;声明不以 ; 结尾
DSH3267Expression( … ) 目标格式有误:其头部、其引脚选择器、缺失的 Class、重复的键、块中除 Pin[i] = <source>; 之外的语句
DSH3268一个节点的一个引脚被绑定两次
DSH3269Expression( … ) { } 块不绑定任何引脚
DSH3270= 之后没有任何内容
DSH2150文件在该节内或块内结束
DSH2151源不是表达式,例如 return
DSH2200–DSH2222源或初始化器使用了 1.x Graph 表达式不具有的内容

绑定

代码触发条件
DSH4201声明的类型不是类型
DSH4220名称被声明两次
DSH4200源没有命名任何已声明的内容
DSH4228材质引脚无法接受的值
DSH5200未知的 Base. 名称
DSH5276警告:仅忽略大小写才匹配的 Base. 名称、类或参数
DSH5212Class= 未命名此引擎的任何表达式类
DSH5285Pin[i] 超过了节点的最后一个输入
DSH5213参数既未命名引脚也未命名该类的属性
DSH5291信息:在 1.x 文件中,携带图值的未知参数稍后按名称连接
DSH4215在一次节点调用中一个引脚被连接两次
DSH5214Expression( … ) 引脚无法接受的值
DSH5279警告:节点的必需引脚未连接

构建资产

代码触发条件
DSH8217材质没有绑定属性的输入
DSH8211表达式类在目录中但不在运行的引擎中
DSH8212按名称连接的引脚在已构建的节点上不存在
DSH8213反射参数的值无法写入该节点
DSH8214无法创建节点

完整列表见诊断索引。

示例

Shader(Name="DreamShaderTests/Corpus/M_Outputs")
{
    Properties = {
        vec3  Tint = vec3(0.4, 0.8, 1.0);
        float A    = 0.75;
    }

    Settings = {
        Domain       = "Surface";
        ShadingModel = "Unlit";
    }

    Outputs = {
        vec3  Color;
        float Alpha;

        Base.EmissiveColor = Color;
        Base.Opacity       = Alpha;
    }

    Graph = {
        Color = Tint;
        Alpha = A;
    }
}

产生的连接:

UMaterial /Game/DreamShaderTests/Corpus/M_Outputs
  MP_EmissiveColor  <- NamedReroute DS_EmissiveColor_<n>  <- VectorParameter "Tint"  RGB output
  MP_Opacity        <- NamedReroute DS_Opacity_<n>        <- ScalarParameter "A"     R output
  bUseMaterialAttributes = false

另请参阅

本页目录