Custom 材质表达式
Custom Material Expression
Custom 节点允许在材质图里直接写 HLSL:任意数量输入、指定输出类型,可选额外输出、#define 与外部 .ush/.usf 包含路径。它是「内置节点做不到」时的逃生口;代价是无法常量折叠、输入仅函数局部可见、且必须是合法 HLSL。优先用内置节点与材质函数,只在必要时上 Custom。
节点能做什么
从材质面板 Custom 分类或右键搜索放入。选中后 Details 中的关键属性:(Custom Material Expressions)
| 属性 | 含义 |
|---|---|
| Code | 要执行的 HLSL(见下方警告) |
| Output Type | 主输出数据类型 |
| Description | 节点标题栏显示名 |
| Inputs / Input Name | 输入数组;名称既是图上针脚名,也是 HLSL 里引用该输入的标识符 |
| Additional Outputs | 额外输出针脚(Output Name + Output Type) |
| Additional Defines | 额外宏(Define Name + Define Value) |
| Include File Paths | 从引擎已提供的公共着色器路径之外包含源文件 |
用法:按需加输入并命名 → 在 Code 里写带 return 的函数体,或写简单表达式(如 Input.bgr)→ 设好 Output Type。(Custom Material Expressions)
官方示例:用 Texture2DSample 在 UV 上按半径 r、步长 dist 做十字形累加模糊,再除以 2*(2*r)+1 后 return blur——典型「内置节点能拼但很丑、或需要显式循环」的场景。(Custom Material Expressions)模糊/卷积的通识背景见 图像处理与后处理、着色器纹理采样。
陷阱 1:输入参数是函数局部的
Custom 表达式总是有返回值,因为整段 Code 被包在外层函数里。所有输入(如 Tex、UV、r)是该外层函数的形参,作用域是函数局部。
若在 Code 里定义带成员函数的 struct,成员函数看不到这些形参,必须手动拷贝进结构体再调用。下面这种写法会编译失败(假定输入名与官方模糊例相同):(Custom Material Expressions)
struct InnerStruct
{
float4 Run()
{
// ERROR: Tex / TexSampler / UV 在 InnerStruct 内不可见
return Texture2DSample(Tex, TexSampler, UV);
}
};
InnerStruct S;
return S.Run();
这与手写 GLSL/HLSL 时「嵌套函数/成员访问捕获外层变量」的直觉不同——在 UE Custom 里要按「已被包进函数」来想。GLSL 片元语法对照见 片元着色器与 GLSL 基础(语言不同,但「作用域」教训可迁移)。
陷阱 2:HLSLcc 后端与类型写法
部分仍走旧 HLSLcc 的着色后端会对 vector / matrix 一类写法报语法错。官方建议写明确类型:float4、float4x4。引擎在修这类 bug,同时把精力转向 DirectXShaderCompiler (DXC)。(Custom Material Expressions)
警告:禁止常量折叠 → 可能更贵
官方两条硬警告:(Custom Material Expressions)
- Custom 阻止常量折叠,指令数往往显著多于等价内置节点图。引擎会把「整次 draw call 恒定」的链(例如
Sin → 乘参数 → 再加)收成更少指令;Custom 内部引擎什么都折叠不了。因此:只有内置节点做不到时才用 Custom。 - Code 必须是合法 HLSL。
折叠机制与 LocalN / ScalarExpressions 打包见 材质图到 HLSL 的翻译。(How the Unreal Engine Translates a Material Graph to HLSL)
flowchart LR
subgraph builtin ["内置节点链"]
N1["Sin"] --> N2["Mul 参数"] --> N3["Add"]
end
subgraph fold ["翻译器"]
F["常量折叠"]
end
subgraph custom ["Custom 节点"]
C["整段 HLSL 黑盒"]
end
builtin --> fold
fold --> H1["更少 GPU 指令"]
custom --> H2["无法折叠"]实践建议
- 先查材质表达式/材质函数库;噪声、塑形、图案等程序化块优先复用或对标 噪声函数、塑形函数、程序化图案 的思路,用节点实现。
- 需要显式循环、特殊 intrinsic、或已有
.ush工具函数时再用 Custom;用 Include File Paths / Additional Defines 接引擎着色器库,而不是把大段工具代码贴进每个材质。 - 改完用
Window → Shader Code → HLSL Code确认自己的 Code 如何被包进外层函数;再用viewmode shadercomplexity(Alt+8)看指令热度——见 UE5 性能分析。(Shader Complexity (from Viewport Modes)) - 材质域、着色模型、混合模式仍由主材质属性决定;Custom 只替换「某一段表达式」,不替代 材质系统 的整体选择。
出处
- Custom Material Expressions UE 5.8 文档
- How the Unreal Engine Translates a Material Graph to HLSL Epic KB
- Essential Material Concepts UE 5.8 文档