DreamShaderLang
语言核心

Function 与 helper

HLSL 风格 helper、GraphFunction、输出和自包含模式。

FunctionGraphFunction 是 DreamShaderLang 的 helper 层。它们让复杂计算留在 HLSL 风格代码里,而不是强行把所有逻辑展开成 Graph 节点。

helper适合
Function纯 HLSL 风格 Custom 节点逻辑。
GraphFunction需要在 helper 体内调用 UE.* 图节点,再把结果传入 Custom 节点的逻辑。

基本声明

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

函数头:

Function [SelfContained|Inline] Name(parameter-list) { body }

参数:

in Type name
out Type name

至少需要一个 out 参数。

单输出 Function 可以作为 Graph 值表达式使用:

Graph = {
    vec3 tinted = ApplyTint(baseColor, tint);
}

多输出 Function 仍然需要显式传 out 变量。

多输出

Function SplitBrightness(in vec3 color, out vec3 normalized, out float brightness) {
    brightness = max(max(color.r, color.g), color.b);
    normalized = color / max(brightness, 0.0001);
}

调用:

Graph = {
    vec3 normalized;
    float brightness;

    SplitBrightness(Tint, normalized, brightness);
}

DreamShader 会为第一个 out 创建 Custom 节点主输出,为后续 out 创建 Additional Output。

GraphFunction

GraphFunction 同样生成 Custom 节点,但函数体里可以直接写 UE.* 调用。DreamShader 会把这些 UE.* 调用转换成材质节点,并把节点输出作为自动生成的 Custom 输入。

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

调用方式:

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

规则:

规则说明
UE.*允许在 GraphFunction 体内使用。
普通 HLSL可以继续使用 sinsaturate、循环等 HLSL 写法。
单输出可作为值表达式。
多输出必须显式传 out 变量。
递归会进行递归调用检测。

普通 Function 体内不允许直接调用 UE.*。如果需要图节点输入,改用 GraphFunction

纹理参数

Namespace(Name="Texture")
{
    Function Sample2DRGB(in Texture2D texture, in float2 uv, out float3 color) {
        color = Texture2DSample(texture, textureSampler, uv).rgb;
    }
}

Texture2D 作为 Custom 节点输入时,生成器会处理对应 sampler 命名。函数体里常见写法是 textureSampler

Function 内置函数

VSCode 扩展 1.4.9 起使用统一的 Function builtin metadata,为 HLSL 原生函数、GLSL 风格别名和 Unreal 纹理采样 helper 提供补全、Hover、Signature Help、Inlay Hint、语义高亮和本地诊断白名单。

常用 HLSL 原生函数包括:

abs, acos, all, any, asin, atan, atan2, ceil, clamp, cos, cross,
ddx, ddy, distance, dot, exp, floor, frac, fwidth, length, lerp,
log, max, min, mul, normalize, pow, reflect, refract, round,
rsqrt, saturate, sign, sin, smoothstep, sqrt, step, tan, transpose

GLSL 风格别名:

别名等价
mixlerp
fractfrac
modfmod

Unreal 纹理采样 helper:

Texture2DSample, Texture2DSampleLevel, Texture2DSampleBias, Texture2DSampleGrad,
Texture2DArraySample, Texture2DArraySampleLevel,
TextureCubeSample, TextureCubeSampleLevel,
Texture3DSample, Texture3DSampleLevel

示例:

Function SampleVolume(in VolumeTexture texture, in float3 uvw, out float value) {
    value = Texture3DSample(texture, textureSampler, uvw).r;
}

普通函数与自包含函数

普通 helper:

Function Remap01(in float value, out float result) {
    result = saturate(value * 0.5 + 0.5);
}

生成行为:

行为说明
.ush生成 helper include 文件。
Custom 节点通过 include 调用生成的函数符号。
适合当前项目持续使用 DreamShader。

自包含 helper:

Function SelfContained Remap01(in float value, out float result) {
    result = saturate(value * 0.5 + 0.5);
}

生成行为:

行为说明
嵌入代码把需要的 helper 代码写入 Custom 节点。
include尽量减少对生成 .ush 的依赖。
适合需要把生成材质迁移到未安装 DreamShader 的项目。

InlineSelfContained 等价:

Function Inline Remap01(in float value, out float result) {
    result = saturate(value * 0.5 + 0.5);
}

命名空间函数

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

调用:

Color::ApplyTint(BaseColor, Tint, ColorOut);

命名空间函数在内部会被转换成安全符号,避免 HLSL 里直接使用 ::

命名空间中也可以声明 GraphFunction

Namespace(Name="Time")
{
    GraphFunction Pulse(in float speed, out float value) {
        value = sin(UE.Time() * speed);
    }
}

设计建议

场景建议
简单节点连接写在 Graph
多处复用公式写成 Function
helper 内需要 UE.* 节点写成 GraphFunction
循环和复杂流程写成 Function
面向团队共享放进 .dsh 或 Package。
命名可能冲突放进 Namespace

常见错误

错误原因
Function ... must declare at least one out parameter没有声明 out 参数。
currently uses positional arguments only普通 Function 调用使用了命名参数。
out argument must be a plain variable nameout 位置传了表达式,而不是变量名。
must be called with explicit out variables多输出 Function / GraphFunction 被当作单值表达式使用。
UE.* calls are not allowed in Function普通 Function 体内调用了图节点入口,应改用 GraphFunction

本页目录