DreamShaderLang
Builtins

Substrate Nodes

The Substrate.* call namespace — 24 wrappers over Unreal's Substrate BSDF, composition and utility nodes. UE 5.4+.

Substrate.* is a sibling call namespace to UE.* that wraps Unreal's Substrate BSDF, composition and utility material nodes. Each name maps to a fixed expression class — 24 names resolving to 22 distinct classes, because two of them are alias pairs.

Outputs = {
    Substrate Surface;
    Base.FrontMaterial = Surface;
}
Graph = {
    Surface = Substrate.Unlit(EmissiveColor = Glow);
}

Availability

since UE 5.4

Substrate.* requires Unreal Engine 5.4 or newer, and Substrate enabled in the project. These are two separate conditions and DreamShader only checks the first one.

The whole namespace — the descriptor table, the class check, and the Substrate type token — is compiled in only on UE 5.4+. On UE 5.3 every call fails with Substrate builtin call '{Name}' requires Unreal Engine 5.4 or newer.

DreamShader does not read Project Settings ▸ Engine ▸ Rendering ▸ Substrate. A source file that compiles to a Substrate graph on a non-Substrate project produces the asset and then fails during Unreal's own material translation, with an error that does not mention DreamShader.

Everything gated on the engine version:

SurfaceGateBelow the gate
Substrate.<Name>(…) callsUE 5.4Substrate builtin call '{Name}' requires Unreal Engine 5.4 or newer.
The Substrate declared-type tokenUE 5.4the token does not resolve
OutputType="Substrate" on a generic UE.* callUE 5.4UE.{Name} OutputType="Substrate" requires Unreal Engine 5.4 or newer.
Base.FrontMaterial output bindingUE 5.4Base.FrontMaterial requires Unreal Engine 5.4 or newer.
Settings = { ShadingModel = "Substrate"; }, and the "Strata" spellingUE 5.4ShadingModel="Substrate" requires Unreal Engine 5.4 or newer.

The editor tooling reflects the same gate. On UE 5.3 the manifest Saved/DreamShader/Bridge/substrate-builtins.json is written with an empty entry array, supported: false and unsupportedReason: "Substrate builtins require Unreal Engine 5.4 or newer." — so completion in the editor extensions offers nothing. See Editor tools.

Synopsis

NotationMeaningExample
<x>Placeholder — substitute a real value; the angle brackets are not typed.Name = <string>
[ x ]Optional — the whole group may be left out.[, Root = <string>]
{ a | b }Choice — take exactly one of the alternatives separated by |.{ Node( … ) | Comment( … ) }
Repetition — the preceding item may appear any number of times.<property-declaration> …
Substrate . <Name> ( [ <argument-name> = <expression> ]
                     [ , <argument-name> = <expression> ] …
                     [ , { Output | OutputName } = "<pin-name>" ]
                     [ , OutputIndex = <integer> ] )

The namespace prefix and the name are matched case-insensitively: SUBSTRATE.UNLIT(…) resolves. Argument names are matched case-insensitively and whitespace-trimmed, but are otherwise exact — no separator stripping.

Argument model

Every Substrate.* call goes through the generic reflected path, so it inherits UE.Expression's rules.

RuleBehaviour
All arguments must be nameda positional argument fails with Generic Substrate.{Name} calls require named arguments.
Class= is rejectedSubstrate.{Name} uses a fixed MaterialExpression class and does not accept Class. — the class comes from the descriptor and cannot be overridden
OutputType= / ResultType= are ignoredthe output type is synthesized from the descriptor; supplying either has no effect and no diagnostic
Output= / OutputName=selects an output pin by name
OutputIndex=selects an output pin by 0-based index
Both selectors togetherUE.{Name} cannot use OutputName/Output together with OutputIndex.
Anything elsedispatched by reflection, below

Reflection-driven binding

Argument binding is not table-driven. For each remaining argument the generator tries, in order:

  1. Input pin name — every input pin the node reports, compared case-insensitively after trimming.
  2. UPROPERTY name — any reflected property on the class or a superclass, compared the same way. Boolean properties additionally match with a leading b stripped.
  3. If the property is an FExpressionInput or an FMaterialAttributesInput, the argument becomes a wired input and its value is evaluated as an expression. Otherwise it is written as a literal property.
  4. No match → UE.{Name}: '{Argument}' is not a property on '{Class}'.

A pin-name match wins over a reflected property of the same name.

Engine pin names containing spaces are unreachable. Argument-name normalization trims and lower-cases but does not strip spaces, so a pin displayed as Diffuse Albedo cannot be spelled as an argument name. Use the UPROPERTY name instead — DiffuseAlbedo — which is what the tables below list. Where a pin name and a property name coincide, either spelling works.

The accepted argument names follow the engine, not the plugin. Steps 1 and 2 query the live UMaterialExpressionSubstrate* class, so the exact accepted set is whatever the running engine version exposes; an input added or removed by an engine release appears or disappears with no plugin change.

The tables below list the inputs these classes expose. The Completion column marks the curated subset DreamShader publishes to editor completion and to the Bridge manifest, which is fixed by the plugin. Any non-input reflected property on the same class — enums, floats, booleans — is also settable as a literal argument even though it is not listed here.

Selecting an output

Output= / OutputName= matches an output pin's name verbatim, case-insensitively, including names that contain spaces — output pin names are matched as whole names, not parsed as argument names. OutputIndex= takes a 0-based index. Only the four utility wrappers have more than one output.

Catalogue

Substrate output marks the wrappers whose result is a Substrate material value — 0 components, bindable to Base.FrontMaterial. The four marked no are the utility nodes and return ordinary numeric values.

Substrate.<Name>UMaterialExpression classSubstrate output
ShadingModelsUMaterialExpressionSubstrateShadingModelsyes
SlabUMaterialExpressionSubstrateSlabBSDFyes
SimpleClearCoatUMaterialExpressionSubstrateSimpleClearCoatBSDFyes
VolumetricFogCloudUMaterialExpressionSubstrateVolumetricFogCloudBSDFyes
UnlitUMaterialExpressionSubstrateUnlitBSDFyes
HairUMaterialExpressionSubstrateHairBSDFyes
EyeUMaterialExpressionSubstrateEyeBSDFyes
SingleLayerWaterUMaterialExpressionSubstrateSingleLayerWaterBSDFyes
LightFunctionUMaterialExpressionSubstrateLightFunctionyes
PostProcessUMaterialExpressionSubstratePostProcessyes
UIUMaterialExpressionSubstrateUIyes
ConvertMaterialAttributesUMaterialExpressionSubstrateConvertMaterialAttributesyes
ConvertToDecalUMaterialExpressionSubstrateConvertToDecalyes
HorizontalMixUMaterialExpressionSubstrateHorizontalMixingyes
HorizontalMixing — alias of HorizontalMixUMaterialExpressionSubstrateHorizontalMixingyes
VerticalLayerUMaterialExpressionSubstrateVerticalLayeringyes
VerticalLayering — alias of VerticalLayerUMaterialExpressionSubstrateVerticalLayeringyes
AddUMaterialExpressionSubstrateAddyes
WeightUMaterialExpressionSubstrateWeightyes
SelectUMaterialExpressionSubstrateSelectyes
TransmittanceToMFPUMaterialExpressionSubstrateTransmittanceToMFPno
MetalnessToDiffuseAlbedoF0UMaterialExpressionSubstrateMetalnessToDiffuseAlbedoF0no
HazinessToSecondaryRoughnessUMaterialExpressionSubstrateHazinessToSecondaryRoughnessno
ThinFilmUMaterialExpressionSubstrateThinFilmno

The two alias pairs are exact duplicates — same class, same inputs, same output typing. Neither spelling is deprecated.

Output typing

DescriptorDeclared output typeComponent countFlags
Substrate outputSubstrate0Substrate value, authoritative
Utility nodeautotaken from the selected pin's real value typenumeric

The declared type is then checked against the selected output pin's actual value type. If a wrapper declared as a Substrate output resolves to a pin that is not a Substrate value, the call fails with Substrate.{Name} output is not a Substrate value.

A Substrate value can only be:

  • assigned to a Substrate-typed Graph variable or Outputs declaration;
  • passed to another Substrate.* wrapper's Substrate-typed input;
  • bound to Base.FrontMaterial.

A Substrate value cannot be swizzled, used with + - * / (Arithmetic operators cannot be applied to Substrate values.), passed to a math builtin (Math function '{Name}' only accepts numeric scalar/vector arguments.), switched by a StaticSwitchParameter (StaticSwitchParameter '{Name}' cannot switch Substrate values.), or produced by an HLSL Custom node.

Node reference

BSDFs

Substrate.Slab

The general-purpose Substrate BSDF slab — the one to reach for first.

ArgumentValueCompletion
DiffuseAlbedonumericyes
F0numericyes
F90numeric
Roughnessnumericyes
Anisotropynumeric
Normalnumericyes
Tangentnumeric
SSSMFPnumeric
SSSMFPScalenumeric
SSSPhaseAnisotropynumeric
EmissiveColornumeric
SecondRoughnessnumeric
SecondRoughnessWeightnumeric
FuzzRoughnessnumeric
FuzzAmountnumeric
FuzzColornumeric
GlintValuenumeric
GlintUVnumeric

Substrate.SimpleClearCoat

A slab with a fixed second clear-coat lobe.

ArgumentValueCompletion
DiffuseAlbedonumericyes
F0numericyes
Roughnessnumericyes
ClearCoatCoveragenumericyes
ClearCoatRoughnessnumericyes
Normalnumericyes
EmissiveColornumeric
BottomNormalnumeric

Substrate.Unlit

Emissive-only BSDF. The smallest complete Substrate surface.

ArgumentValueCompletion
EmissiveColornumericyes
TransmittanceColornumeric
Normalnumeric

Substrate.Hair

ArgumentValueCompletion
BaseColornumericyes
Scatternumericyes
Specularnumericyes
Roughnessnumericyes
Backlitnumericyes
Tangentnumericyes
EmissiveColornumericyes

Substrate.Eye

ArgumentValueCompletion
DiffuseColornumericyes
Roughnessnumericyes
CorneaNormalnumericyes
IrisNormalnumericyes
IrisPlaneNormalnumericyes
IrisMasknumericyes
IrisDistancenumericyes
EmissiveColornumericyes

Substrate.SingleLayerWater

ArgumentValueCompletion
BaseColornumericyes
Metallicnumericyes
Specularnumericyes
Roughnessnumericyes
Normalnumericyes
EmissiveColornumericyes
TopMaterialOpacitynumericyes
WaterAlbedonumericyes
WaterExtinctionnumericyes
WaterPhaseGnumericyes
ColorScaleBehindWaternumericyes

Substrate.VolumetricFogCloud

Participating-media BSDF for volumetric fog and cloud materials.

ArgumentValueCompletion
Albedonumericyes
Extinctionnumericyes
EmissiveColornumericyes
AmbientOcclusionnumericyes

Substrate.ShadingModels

Legacy-style shading-model surface expressed as a Substrate material. Editor completion offers no parameters for this wrapper; every argument below is still accepted.

ArgumentValueCompletion
BaseColornumeric
Metallicnumeric
Specularnumeric
Roughnessnumeric
Anisotropynumeric
EmissiveColornumeric
Normalnumeric
Tangentnumeric
SubSurfaceColornumeric
ClearCoatnumeric
ClearCoatRoughnessnumeric
Opacitynumeric
TransmittanceColornumeric
WaterScatteringCoefficientsnumeric
WaterAbsorptionCoefficientsnumeric
WaterPhaseGnumeric
ColorScaleBehindWaternumeric
ClearCoatNormalnumeric
CustomTangentnumeric
ThinTranslucentSurfaceCoveragenumeric

Domain output nodes

Substrate.LightFunction

ArgumentValueCompletion
Colornumericyes

Substrate.PostProcess

ArgumentValueCompletion
Colornumericyes
Opacitynumericyes

Substrate.UI

ArgumentValueCompletion
Colornumericyes
Opacitynumericyes

Conversion

Substrate.ConvertMaterialAttributes

Converts a MaterialAttributes value into a Substrate material.

ArgumentValueCompletion
MaterialAttributesMaterialAttributesyes
Attributes — alias of MaterialAttributesMaterialAttributes
WaterScatteringCoefficientsnumericyes
WaterAbsorptionCoefficientsnumericyes
WaterPhaseGnumericyes
ColorScaleBehindWaternumericyes

MaterialAttributes is the reflected property name and Attributes is the engine's pin name for the same input; both bind input 0. Passing a numeric value fails with Substrate.ConvertMaterialAttributes input '{Pin}' expects a MaterialAttributes value.

Substrate.ConvertToDecal

Converts a Substrate material into a decal material.

ArgumentValueCompletion
DecalMaterialSubstrateyes
Coveragenumericyes

Composition

Substrate.HorizontalMix

Screen-space horizontal blend of two Substrate materials. Also spelled Substrate.HorizontalMixing — the two names are interchangeable.

ArgumentValueCompletion
BackgroundSubstrateyes
ForegroundSubstrateyes
Mixnumericyes

Substrate.VerticalLayer

Layers one Substrate material over another. Also spelled Substrate.VerticalLayering — the two names are interchangeable.

ArgumentValueCompletion
TopSubstrateyes
BaseSubstrateyes
Thicknessnumericyes

Substrate.Add

ArgumentValueCompletion
ASubstrateyes
BSubstrateyes

Substrate.Weight

Scales a Substrate material's contribution.

ArgumentValueCompletion
ASubstrateyes
Weightnumericyes

Substrate.Select

Static selection between two Substrate materials.

ArgumentValueCompletion
ASubstrateyes
BSubstrateyes
SelectValuenumericyes

Utility nodes

These four return ordinary numeric values, not Substrate values, and they are the only wrappers with more than one output. Select with Output= or OutputIndex=.

Substrate.TransmittanceToMFP

Converts a transmittance colour and thickness into a mean-free-path parameterisation.

ArgumentValueCompletion
TransmittanceColornumericyes
Thicknessnumericyes
Output indexName
0 (default)MFP
1Thickness

Substrate.MetalnessToDiffuseAlbedoF0

Converts a legacy base-colour / metallic / specular triple into the slab parameterisation.

ArgumentValueCompletion
BaseColornumericyes
Metallicnumericyes
Specularnumericyes
Output indexName
0 (default)DiffuseAlbedo
1F0

Substrate.HazinessToSecondaryRoughness

Converts a haziness control into a second-roughness lobe.

ArgumentValueCompletion
BaseRoughnessnumericyes
Hazinessnumericyes
Output indexName
0 (default)Second Roughness
1Second Roughness Weight

Note the spaces in those output names. They are matched as whole names, so Output = "Second Roughness Weight" works even though a pin name with spaces would be unreachable as an argument name.

Substrate.ThinFilm

Computes thin-film interference specular colours.

ArgumentValueCompletion
Normalnumericyes
F0numericyes
F90numericyes
Thicknessnumericyes
IORnumericyes
Output indexName
0 (default)Specular Color
1Edge Specular Color

Binding to Base.FrontMaterial

A Substrate material reaches the generated UMaterial through the Base.FrontMaterial output binding, and through no other route.

Outputs = {
    Substrate Surface;              // declared-type token; case-insensitive, no other spelling
    Base.FrontMaterial = Surface;
}
Graph = {
    Surface = Substrate.Unlit(EmissiveColor = Color);
}
RuleBehaviour
Declared-type tokenthe single spelling Substrate, whitespace-stripped and case-insensitive. Strata is not a type token
Shading modelthe binding force-sets the material's shading model to Substrate — no Settings entry is needed
Explicit ShadingModel settingallowed only as "Substrate" or "Strata"; any other value fails
Base.MaterialAttributes in the same Shaderrejected — the two bindings are mutually exclusive
Backendrequires a Graph block; an HLSL Custom node cannot produce or drive a Substrate value
Engine versionUE 5.4+

Strata is the pre-rename spelling. It is accepted as a Settings = { ShadingModel = … } value — an alias for the same shading model — but never as a type token and never as a call namespace. See Enum values.

Notes worth knowing

  • There is no wrapper for every Substrate class. UMaterialExpressionSubstrateToonBSDF has no entry in the catalogue. Reach it — and any future Substrate class — through the generic path:

    UE.Expression(Class = "SubstrateToonBSDF", OutputType = "Substrate", …)

    Class-name resolution accepts SubstrateToonBSDF, MaterialExpressionSubstrateToonBSDF and the full /Script/Engine.… object path interchangeably. The U-prefixed C++ spelling is not accepted — see Class resolution.

  • Registered UE.* sugar does not apply inside this namespace. Substrate.TexCoord(…) is not a thing; unknown names fail with Unsupported Substrate builtin call '{Name}' in Graph.

  • Substrate nodes do participate in node reuse: two textually identical Substrate.Slab(…) calls over identical argument values collapse to a single node. This is the same cache the generic UE.Expression path uses, and it is why one multi-output utility node can serve two reads with different Output= selectors.

  • The decompiler exports an existing Substrate graph back to DreamShaderLang, deriving channel swizzles from each connection's write mask since 1.5.0.

  • The complete Substrate.* surface is exported for editor tooling to Saved/DreamShader/Bridge/substrate-builtins.json (schema DreamShader.SubstrateBuiltins, version 1), one entry per name with its qualifiedName, className, outputType, isSubstrateOutput and curated parameters. See Editor tools.

Diagnostics

Several messages below begin with the literal text UE. even for a Substrate.* call. They come from the shared generic-builtin path, which formats its prefix as UE. unconditionally; only the messages that carry the namespace explicitly render as Substrate.. This is cosmetic — the {Name} in such a message is still the Substrate wrapper name.

At the call site

MessageCauseFix
Substrate builtin call '{Name}' requires Unreal Engine 5.4 or newer.Any Substrate.* call on UE 5.3.Substrate is unavailable below UE 5.4. Use a legacy shading model.
Unsupported Substrate builtin call '{Name}' in Graph.The name is not one of the 24 in the catalogue.Check the spelling, or reach the class through UE.Expression with OutputType="Substrate". Details
Generic Substrate.{Name} calls require named arguments.A positional argument.Name every argument.
Substrate.{Name} uses a fixed MaterialExpression class and does not accept Class.Class= was supplied. The class comes from the descriptor.
UE.{Name}: '{Argument}' is not a property on '{Class}'.The argument matched neither a pin name nor a reflected property.Pin names containing spaces are unreachable — use the UPROPERTY name, e.g. DiffuseAlbedo.
Substrate.{Name} input '{Pin}' expects a Substrate value.A Substrate-typed pin was given a numeric value.
Substrate.{Name} input '{Pin}' does not accept Substrate values.A numeric pin was given a Substrate value.
Substrate.{Name} input '{Pin}' expects a MaterialAttributes value.A MaterialAttributes pin was given something else — typically Substrate.ConvertMaterialAttributes.
Substrate.{Name} output is not a Substrate value.The selected pin's value type is not Substrate although the descriptor declares one.
UE.{Name} output '{Pin}' was not found on '{Class}'.The named output pin does not exist.Utility output names may contain spaces, e.g. "Second Roughness Weight".
UE.{Name} OutputIndex is out of range for '{Class}'.Negative index, or past the last output.
UE.{Name} could not resolve MaterialExpression class '{Class}'.The descriptor's class is not present in the running engine.

Substrate values elsewhere in the pipeline

MessageCauseFix
Arithmetic operators cannot be applied to Substrate values.A Substrate value used with + - * /.Compose Substrate values with Substrate.Add, Substrate.Weight or Substrate.VerticalLayer.
Math function '{Name}' only accepts numeric scalar/vector arguments.A Substrate value passed to a math builtin.Details
StaticSwitchParameter '{Name}' cannot switch Substrate values.A Substrate value on a True= / False= branch.Use Substrate.Select instead.
Graph variable '{Name}' uses Substrate, which requires Unreal Engine 5.4 or newer.A Substrate-typed Graph declaration on UE 5.3.
Base.FrontMaterial requires Unreal Engine 5.4 or newer.The binding target used on UE 5.3.
{File}: Base.FrontMaterial requires ShadingModel="Substrate" or no explicit ShadingModel setting.A conflicting explicit shading model.Delete the ShadingModel setting, or set it to Substrate or Strata. Details
{File}: Base.FrontMaterial and Base.MaterialAttributes cannot be used by the same Shader.Both bindings present. They are mutually exclusive.
{File}: Base.FrontMaterial expects a Substrate value and cannot be driven by a material Custom node. Use a Graph block and Substrate.* nodes.The binding source came from an HLSL Custom node.
{File}: Material output '{Output}' expects a numeric value, but got Substrate.A Substrate value bound to a numeric material output.
DreamShader Function '{Name}' result '{Result}' uses Substrate, which is not supported by HLSL Custom node functions. Use GraphFunction or ShaderFunction instead.A Function declared a Substrate result.Details
ShadingModel="Substrate" requires Unreal Engine 5.4 or newer.Settings = { ShadingModel = "Substrate"; } or "Strata" on UE 5.3.

The complete list lives in the diagnostics index.

Example

Shader(Name="Docs/M_Substrate")
{
    Properties = {
        vec3  BaseColor = vec3(0.6, 0.1, 0.1);
        float Metallic  = 0.0;
        float Specular  = 0.5;
        float Rough     = 0.3;
        vec3  Glow      = vec3(0.1, 0.6, 1.0);
    }

    Outputs = {
        Substrate Surface;
        Base.FrontMaterial = Surface;
    }

    Graph = {
        // Utility node: two numeric outputs, selected by name.
        vec3 Albedo = Substrate.MetalnessToDiffuseAlbedoF0(
            BaseColor = BaseColor, Metallic = Metallic, Specular = Specular,
            Output = "DiffuseAlbedo");
        vec3 F0 = Substrate.MetalnessToDiffuseAlbedoF0(
            BaseColor = BaseColor, Metallic = Metallic, Specular = Specular,
            Output = "F0");

        Substrate Body = Substrate.Slab(
            DiffuseAlbedo = Albedo,
            F0            = F0,
            Roughness     = Rough);

        Substrate Emissive = Substrate.Unlit(EmissiveColor = Glow);

        Surface = Substrate.Add(A = Body, B = Emissive);
    }
}

Generated nodes:

SubstrateMetalnessToDiffuseAlbedoF0   -> output "DiffuseAlbedo"  -> Albedo    (3 components)
                                      -> output "F0"             -> F0        (3 components)
                                         (one node, reused for both reads)
SubstrateSlabBSDF                     -> Body                    (Substrate value)
SubstrateUnlitBSDF                    -> Emissive                (Substrate value)
SubstrateAdd                          -> Surface                 (Substrate value)
Material ShadingModel forced to Substrate by the Base.FrontMaterial binding

Where to next

On this page