DreamShaderLang
语言核心

Graph 语言

DreamShaderLang 中用于生成 Unreal 材质节点的图 DSL。

Graph = { ... } 是 DreamShaderLang 的材质图层。它不是完整通用语言,而是一门用于创建和连接 Unreal MaterialExpression 节点的 DSL。

语句

Graph 语句以分号结束:

Graph = {
    float a = 1.0;
    float b = 2.0;
    float c = a + b;
}

支持的语句:

语句示例
声明float value;
声明并初始化vec3 color = vec3(1.0, 0.0, 0.0);
赋值Color = Tint;
MaterialAttributes 成员写入Attrs.BaseColor = Color;
表达式语句ApplyTint(A, B, Result);
if / elseif (Mask > 0.5) { ... } else { ... }

声明

float a;
float2 uv;
float3 color;
float4 sampleValue;

只声明不初始化时,会创建对应类型的默认值,标量和向量默认是 0

同一条语句可以写逗号分隔声明:

float a = 1.0, b = 2.0, c;

表达式

算术

支持:

a + b
a - b
a * b
a / b
-a
+a

这些表达式会生成 AddSubtractMultiplyDivide 等材质节点。纹理对象不能参与算术。

构造器

vec3 color = vec3(1.0, 0.5, 0.2);
float4 rgba = float4(color, 1.0);

Swizzle

float r = color.r;
float2 rg = color.rg;
float3 xyz = normal.xyz;
float4 rgaa = color.rgaa;

支持通道:

通道族通道
坐标风格x / y / z / w
颜色风格r / g / b / a

Swizzle 支持 1 到 4 个通道,并允许重复通道,例如 .rrr.ggg.aaa.rgaa.rgbb

MaterialAttributes

MaterialAttributes 是 Unreal 材质属性聚合值。通常先在 Outputs 中声明并绑定,然后在 Graph 里写成员:

Outputs = {
    MaterialAttributes Attrs;
    Base.MaterialAttributes = Attrs;
}

Graph = {
    Attrs.BaseColor = BaseColor;
    Attrs.Roughness = Roughness;
    Attrs.Metallic = Metallic;
}

成员名使用 Unreal 材质属性名,例如 BaseColorRoughnessMetallicNormalOpacityEmissiveColorAmbientOcclusionMaterialAttributes 本身不能参与算术;读取 Attrs.BaseColor 会生成 Break Material Attributes 并得到 float3,写入 Attrs.Roughness 会生成 Set Material Attributes 链。

函数调用

Graph 中有五类调用:

float2 uv = UE.TexCoord(Index=0);

vec3 result;
ApplyTint(color, tint, result);

vec3 tinted = F_Tint(InColor=color, InTint=tint);
vec3 existing = BufferWriter(color, 1.0, Output="Result");
调用返回方式
UE.*返回一个图值,可赋值。
Function单输出可作为值表达式;多输出必须传显式 out 变量。
GraphFunction规则同 Function,但 helper 体内可使用 UE.*
ShaderFunction返回材质函数输出,可作为表达式使用。
VirtualFunction返回已有材质函数输出,可作为表达式使用。

Function 调用

定义:

Function ApplyTint(in vec3 color, in vec3 tint, out vec3 result) {
    result = color * tint;
}

单输出调用:

Graph = {
    vec3 src = vec3(1.0, 0.4, 0.2);
    vec3 tint = vec3(0.5, 1.0, 1.0);
    vec3 result = ApplyTint(src, tint);
}

多输出调用:

Graph = {
    vec3 src = vec3(1.0, 0.4, 0.2);
    vec3 tint = vec3(0.5, 1.0, 1.0);
    vec3 result;

    ApplyTint(src, tint, result);
}

限制:

规则说明
位置参数当前 Function 调用只支持位置参数。
显式 out所有 out 参数必须传普通变量名。
值表达式仅单输出 Function 可作为值表达式。

GraphFunction 调用

GraphFunction 是可复用 Custom 节点 helper,函数体中可以调用 UE.* 图节点:

GraphFunction BuildPulse(in float scale, out float result) {
    float t = UE.Time();
    result = sin(t * scale);
}

Graph 中可以像普通单输出 helper 一样使用:

Graph = {
    float pulse = BuildPulse(2.0);
}

多输出 GraphFunction 仍然需要显式 out 变量。普通 Function 体内不允许调用 UE.*;需要图节点输入时应改用 GraphFunction

ShaderFunction 调用

如果项目中声明并生成了:

ShaderFunction(Name="Functions/F_Tint")
{
    Inputs = {
        vec3 InColor;
        vec3 InTint;
    }

    Outputs = {
        vec3 OutColor;
    }

    Graph = {
        OutColor = InColor * InTint;
    }
}

可以在其他 Graph 中调用:

Graph = {
    vec3 tinted = F_Tint(InColor=BaseColor, InTint=Tint);
    Color = tinted;
}

如果 ShaderFunction 有多个输出,必须指定:

float value = F_MultiOutput(Input=Mask, Output="Height");
float other = F_MultiOutput(Input=Mask, OutputIndex=1);

如果输入在声明中标记为 opt,调用时可以用 default 跳过该输入:

float3 tinted = F_Tint(BaseColor, default, Output="OutColor");

VirtualFunction 调用

VirtualFunction 先声明已有材质函数资产:

VirtualFunction(Name="BufferWriter")
{
    Options = {
        Asset = Path(Plugins.MoonToon, "MaterialFunctions/Buffer/Writer");
    }

    Inputs = {
        float3 Color;
        float Alpha;
    }

    Outputs = {
        float3 Result;
    }
}

然后在 Graph 中调用:

Graph = {
    float3 result = BufferWriter(Color, 1.0, Output="Result");
}

输入会优先按声明名称匹配到真实资产 pin,名称找不到时再按顺序兜底。多输出时同样使用 Output / OutputName / OutputIndex 选择输出。

VirtualFunctionopt 输入同样支持 default

float3 result = BufferWriter(Color, default, Output="Result");

参数节点调用

StaticSwitchParameter 可以从 Properties 声明,再在 Graph 中调用同名函数:

Properties = {
    StaticSwitchParameter UseDetail = true [
        Group="Switches";
        SortPriority=30;
    ];
}

Graph = {
    float3 result = UseDetail(True=detailColor, False=baseColor);
}

也可以直接用 UE.StaticSwitchParameter(...) 创建临时静态开关节点:

float3 result = UE.StaticSwitchParameter(
    Name="UseDetail",
    Default=true,
    True=detailColor,
    False=baseColor);

Material Parameter Collection 使用 UE.CollectionParam(...) 读取:

float wind = UE.CollectionParam(
    Collection=Path(Game, "Collections/MPC_Wind"),
    Parameter="WindStrength");

if / else

Graph 支持基础条件分支:

Graph = {
    float mask = UE.Expression(Class="ComponentMask", OutputType="float1", Input=UV, R=true);

    if (mask > 0.5) {
        Color = vec3(1.0, 0.2, 0.2);
    } else {
        Color = vec3(0.0, 0.0, 0.0);
    }
}

条件支持:

写法语义
if (Mask)等价于 Mask > 0
> / <大于 / 小于。
>= / <=大于等于 / 小于等于。
== / !=等于 / 不等于。

生成器会创建 Unreal Material If 节点来合并分支结果。条件两侧必须是标量。分支不能选择 Texture2DTextureCubeTexture2DArrayVolumeTexture 值;MaterialAttributes 分支可以合并,但两侧都必须是 MaterialAttributes

Graph Region

Graph 可以用 #Region / #EndRegion 标记一组语句。它不改变计算语义,主要用于生成图布局、反编译导出和 VSCode 折叠。

Graph = {
    #Region "Surface"
    float2 uv = UE.TexCoord(Index=0);
    Color = BaseColor.rgb;
    RoughnessOut = saturate(Roughness);
    #EndRegion

    #Region "Output"
    FinalColor = Color;
    #EndRegion
}

规则:

规则说明
名称#Region 必须带名称,例如 #Region "Surface"
闭合每个 #Region 必须有匹配的 #EndRegion
作用范围region 内的变量和生成节点会被记录为同一布局分组。
计算语义region 不改变变量作用域和执行顺序。

如果同时写了 Layout section,生成器会优先使用显式 Node(...) / Comment(...) 信息,再用 region 信息组织未显式定位的节点。

当前不支持

特性建议替代
for / while放进 Function 的 HLSL helper。
任意 HLSL 语句放进 Function
多输出 helper 返回值风格调用使用显式 out 参数。
纹理分支选择在 helper 中处理采样结果,或分支选择数值结果。

本页目录