DreamShaderLang
插件参考DreamShaderLang

Shader

Shader

Shader

DreamShader » DreamShaderLang » Shader

一个顶层块,用于声明一个 Unreal 材质资产:其参数、渲染状态设置、输出绑定以及为它们提供输入的节点图。

声明于.dsm — 包含它的 .dsh 是一个 DSH2249(参见源文件)
类型顶层块
生成UMaterial(Graph 后端)或 UDreamShaderMaterialInstance + 一个隐藏的 UMaterial 基础(ThinCustom 后端)
多重性每个文件最多一个(参见备注)

概要

Shader(Name = "<asset-path>" [, Root = "<root>"])
{
    [Properties [=] { <property-declaration> ; … }]
    [Settings   [=] { <key> = <value> ; … }]
    [Outputs    [=] { { <output-declaration> ; | <output-binding> ; | Expression( … ) { Pin[i] = <source> ; … } } … }]
    [Graph      [=] { <graph-statement> … }]
    [Layout     [=] { { Node( … ) | Comment( … ) } ; … }]
}

节名与其 { … } 块之间的 = 是可选的语法糖 (自 1.5.0 起);节结束 } 之后的 ; 是可选的。各节可以以任意顺序出现,并且可以重复。

关键字 Shader 采用区分大小写匹配;节名采用不区分大小写匹配。参见词法元素。

一个 .dss 写入的材质与 #pragma material(...)、uniform 和一个 export void <Name>(inout material m) 相同 — 参见 DreamShaderLang 2.0;dsc migrate 会按该方式重写一个 .dsm。

头部属性

属性必需值效果
Name是字符串资产的逻辑路径。最后一个由 / 分隔的段是资产名称;前面的段成为文件夹。
Root否字符串文件夹所依附的包根目录。缺省或为空时默认为 /Game。
NoGeneration否true | false(2.1.2 之后) 只有指定该文件名的编译才会构建此块的资产;参见 NoGeneration。另一个值是 DSH2260。

属性键采用不区分大小写匹配(name= 也可以)。值可以带引号或不带引号;不带引号的值在第一个 , 或 ) 处结束。重复的键保留后一个值,并给出警告 DSH2244 (自 2.0.0 起;之前为静默)。) 之前的尾随逗号可被接受,与 1.x 相同 (2.0.0 – 2.1.0 曾以 DSH2243 拒绝它)。

完整的 Name / Root 语法、可接受的根目录拼写以及最终生成的磁盘路径在资产路径中说明。

节

节可接受重复行为参考
Properties是追加属性
Settings是合并;后一个键胜出,重复写入同一个键会给出警告 DSH3262着色器设置
Outputs是追加输出绑定
Graph是后一个主体胜出,并给出警告 DSH2258图
Layout是重置 — 第二个 Layout 会丢弃第一个,并给出警告 DSH2258布局
Code否 — DSH2246——
Inputs否 — 未知节,DSH2245——
Results否 — 未知节,DSH2245——
Options否 — 未知节,DSH2245——

Shader 中的 Properties 声明参数、const 和 UE.* 内置节点。这不是 Properties 在 VirtualFunction 内部所使用的同一语法,在那里它是 Inputs 的同义词。

Outputs / Graph 关系

Outputs 包含两种语句,按语句进行消歧:

语句形式含义
<type> <name> ;输出变量声明;Graph 必须为其赋值
<type> <name> = <expression> ;带初始化的输出声明 (自 1.3.4 起)
<target> = <variable> ;输出绑定 — Base.<Property> 或 Expression( … ).Pin[<i>]
Expression( … ) { Pin[<i>] = <variable> ; … }块形式 — 在一个终端节点上有多个引脚 (自 1.9.0 起)

决定 Graph 是否必需的规则在整个块读取完毕后进行求值:

  • 一个没有 Graph 节且 Outputs 为空的 Shader 是 DSH2255。没有 Graph 时,Outputs 语句必须自行计算这些值 — 带初始化器的输出声明,或者 (自 2.0.0 起) 右侧为表达式的绑定,例如 Base.FrontMaterial = Substrate.Layer(Coat, Body);。
  • 空的 Graph = { } 是合法的。
  • 绑定才是真正连接材质的部分。没有 Outputs 节的 Shader 会给出警告 DSH2256:材质可以构建,但没有任何连线 (自 2.0.0 起;到 1.9.x 为止则生成会失败)。
// Legal: no Graph body needed, the output declaration carries its own initializer.
Shader(Name="M_Flat")
{
    Properties = { vec3 Tint = vec3(1.0, 0.2, 0.2); }
    Outputs = {
        vec3 Color = Tint;
        Base.EmissiveColor = Color;
    }
    Graph = { }
}

生成的资产

Name + Root 解析为包路径的方式与资产路径中所述完全一致。最终落在那里的是哪个 UClass 取决于解析出的后端:

后端写入的资产备注
GraphUMaterial节点图直接构建在材质上
ThinCustom (自 1.5.0 起)UDreamShaderMaterialInstance,其父级是一个名为 MB_DreamThinBase_<leaf> 的隐藏 UMaterial 子对象一个资产,一个包;你在实例上设置的参数覆盖由你保留 — 重建会捕获它们,并恢复新基础仍然声明的每个名称 (自 1.9.0 起),参见分歧
InstanceThinCustom 的别名 (自 1.5.0 起弃用)

后端来自 Settings = { Backend = "…"; }(如果存在),否则来自项目的 Default Compiler Backend 设置。参见后端和项目设置。

[!NOTE] Graph 后端的 UMaterial 是一个普通资产,并在每次成功构建时保存 (自 2.0.0 起)。ThinCustom 产物会保持**临时(Ephemeral)**状态 — 在内存中,磁盘上没有包 — 直到某次 cook、显式 Materialize 或子实例赋予它一个包;而一旦它有了包,就会保留在磁盘上。参见临时材质。

[!WARNING] 重新生成会清除目标图。未被 Layout 固定的节点位置、添加的节点、节点属性调整,以及文本以 DreamShader: 开头的注释框都会被销毁。只有不带 DreamShader: 前缀的注释框会保留下来。在 ThinCustom 后端下,实例的参数覆盖也会被清除,但会先被捕获并在之后恢复 (自 1.9.0 起) — 源不再声明的参数是唯一会丢失其值的情况。参见重新生成。

备注

  • 每个文件最多一个 Shader(DSH2250)。在 1.9.x 之前,导入会在解析前内联到一个文本中,因此该规则会跨越导入闭包;现在头文件会单独读取,因此不能包含 Shader(DSH2249),所以 import 永远不会添加一个。.dsh 检查读取的是 token,而不是文本:提及 Shader( 的注释没有问题。请参阅源文件。
  • 没有属性的 Shader() 是 DSH2242,缺少的是 Name。
  • Shader 可以与 VirtualFunction、Function、GraphFunction 和 Namespace 块共享一个 .dsm,这些块是材质的辅助块,并且也可以与 ShaderFunction、ShaderLayer 和 ShaderLayerBlend 块共享:对该文件的一次编译会将它们全部构建出来,每个都构建为各自的资源,并且材质可以按名称调用这样的函数 (2.0.0 – 2.1.0 曾以 DSH6201 拒绝这样做)。.dsf 中的 Shader 是 DSH2259。
  • 未声明任何 Shader 块的 .dsm 仍然可以编译——它只会生成其声明的那些函数资源。
  • 绑定 Base.MaterialAttributes 会开启材质上的 Use Material Attributes。有关 Base.FrontMaterial 和其他目标,请参阅输出绑定。

诊断

每个阶段都会报告其所有错误,每个错误都在各自的行和列 (自 2.0.0 起)。

解析时

代码触发条件
DSH2241Shader 后面没有其属性列表
DSH2242属性列表没有 Name,或该列表为空
DSH2243格式错误的属性列表——缺少键、= 或值,缺少 , 或 )
DSH2244(警告) 一个属性被写了两次
DSH2250文件中出现第二个 Shader 块
DSH2249.dsh 中出现 Shader 块
DSH2257正文 {、节名称或节的 { 缺失
DSH2245出现 Properties、Settings、Outputs、Graph 和 Layout 以外的节
DSH2246出现 Code 节
DSH2258(警告) Graph 或 Layout 节被写了两次
DSH2255没有 Graph 节,且 Outputs 为空
DSH2256(警告) 没有 Outputs 节
DSH2150文件在该块内结束

绑定与生成时

代码触发条件
DSH4210一个属性、一个函数或另一个名称被声明了两次
DSH7202Settings = { Backend = … } 未指定任何后端;Instance 被读取为 ThinCustom,并带有警告 DSH7204
DSH8200Name / Root 未解析为有效的资源路径
DSH8201无法创建或复用材质——目标路径中存放着另一个类,或存放着 DreamShader 未生成的资源;原因会附加在后面
DSH8203对于 ThinCustom 实例,情况相同
DSH8206该资源已在资源编辑器中打开,因此未被重新构建
DSH8207该资源自生成以来被手动编辑过,因此未被重新构建;其携带的原因是 DSH8115 文本——请参阅差异

Properties、Settings、Outputs 和 Graph 的消息位于各自的页面。所有代码:诊断。

示例

Shader(Name="Materials/M_Emissive", Root="Game")
{
    Properties = {
        Group("Look") {
            vec3  Tint      = vec3(1.0, 0.4, 0.1) [Description="Emissive tint"];
            float Intensity = 2.0                 [Slider(0, 10)];
        }
        TextureSampleParameter2D BaseTex = Path(Game, "Textures/T_Noise");
    }

    Settings = {
        ShadingModel = "Unlit";
        BlendMode    = "Translucent";
        TwoSided     = true;
    }

    Outputs = {
        vec3  Color;
        float Alpha;

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

    Graph = {
        vec2 UV  = UE.TexCoord(Index = 0);
        vec4 Tex = BaseTex(Coordinates = UV);
        Color = Tex.rgb * Tint * Intensity;
        Alpha = Tex.a;
    }

    Layout = {
        Comment(Name="Sampling", X=-1200, Y=-200, W=900, H=400);
        Node(Var="UV", X=-1100, Y=-120);
    }
}

生成的资源:

package     /Game/Materials/M_Emissive
object path /Game/Materials/M_Emissive.M_Emissive
on disk     <Project>/Content/Materials/M_Emissive.uasset      (once Materialized, or under the Graph backend)

[!NOTE] BaseTex 被声明为 TextureSampleParameter2D,而不是紧凑的 Texture2D,因为只有 sample-parameter 系列拥有 BaseTex(Coordinates = UV) 调用形式所连接的输入引脚。紧凑的 Texture2D 会生成一个纹理 对象 参数,而它没有这样的引脚;调用它会落到函数分发器并失败。请参阅 在 Graph 中使用参数。

另请参阅

本页目录