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 / else | if (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这些表达式会生成 Add、Subtract、Multiply、Divide 等材质节点。纹理对象不能参与算术。
构造器
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 材质属性名,例如 BaseColor、Roughness、Metallic、Normal、Opacity、EmissiveColor、AmbientOcclusion。MaterialAttributes 本身不能参与算术;读取 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 选择输出。
VirtualFunction 的 opt 输入同样支持 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 节点来合并分支结果。条件两侧必须是标量。分支不能选择 Texture2D、TextureCube、Texture2DArray 或 VolumeTexture 值;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 中处理采样结果,或分支选择数值结果。 |