DreamShaderLang
Settings

Material Settings

The Settings block — how a statement is read, the special Shader keys, the reflection resolver that reaches any UMaterial property, what a regenerated material resets to, and the four material-function keys.

Shader settings

DreamShader » Settings » Shader settings

The Settings section of a Shader block: a few hand-handled keys plus a reflection resolver that writes any other key onto the generated UMaterial.

Declared in.dsm — inside a Shader( … ) { … } block
Kindsection
Generatesproperty writes on the generated UMaterial (under the ThinCustom backend, on the hidden base material)

Synopsis

Shader(Name = "<asset-path>")
{
    Settings [=] {
        [BlendMode     = <blend-mode>;]     // or RenderType
        [ShadingModel  = <shading-model>;]
        [MaterialDomain = <domain>;]        // or Domain
        [Backend       = { Graph | ThinCustom };]
        [Substrate     = { Legacy | Bridge | Native };]
        [<property-name> = <literal>;] …
    }
}

The block grammar, comment handling, statement splitting and quoting rules are common to every Settings section and are specified in Settings. Since 2.0.0 a key is one name: a nested path or an index is DSH3261.

The keys and values are those of the 2.0 #pragma material(…); a Shader's Settings becomes one.

Special keys

These keys never reach the reflection resolver. The emitter skips the six whose name — after trimming, lowercasing and deleting spaces, _ and - — is one of:

blendmode   rendertype   shadingmodel   materialdomain   domain   backend
Canonical keySynonymValue grammarValue when the key is absentEffect
BlendModeRenderTypeone of the blend-mode spellingsOpaquesets UMaterial::BlendMode
ShadingModel—one of the shading-model spellingsDefaultLitcalls SetShadingModel
MaterialDomainDomainone of the domain spellingsSurfacesets UMaterial::MaterialDomain
Backend—Graph or ThinCustom; Instance is the old spelling of ThinCustomthe project's Default Compiler Backendselects the materialization strategy — see Backend

One more key is read by the compiler and never reaches the material (since 2.0.0):

KeyValue grammarValue when the key is absentEffect
SubstrateLegacy, Bridge, NativeLegacyhow a material written against the legacy attributes is read in a project that has Substrate on — Bridge folds the shading attributes of a Surface material into one Substrate.ShadingModels node on FrontMaterial. See Substrate sugar. An unknown mode is DSH7232.

Backend and Substrate are taken out of the settings when the source is bound, matched ignoring case; the rest is applied when the material is built.

When both a canonical key and its synonym are present, the canonical key wins: BlendMode beats RenderType, MaterialDomain beats Domain. There is no diagnostic for the conflict.

Key spelling for these is looked up by trim-and-lowercase only, so blendmode, BlendMode and BLENDMODE all work.

[!WARNING] A spelling that differs from a special key only by underscores is silently dropped. Blend_Mode = "Translucent"; does not set the blend mode: the direct probe for BlendMode misses the stored key blend_mode, and the reflection pass skips it because its separator-stripped form is on the special-key list. No error, no warning, no effect. The same applies to Render_Type, Shading_Model, Material_Domain and Back_end. Write the names without separators. (A space or a hyphen cannot stand in a key since 2.0.0: DSH3261.)

Application order

  1. The material is reset to the defaults.
  2. The whole block is validated — every special value is resolved and every generic value is written to a throw-away transient UMaterial. A single bad value stops the build before the real material is touched, and the rebuild is rolled back.
  3. BlendMode, then ShadingModel, then MaterialDomain; then bUsedWithVolumetricCloud follows the domain.
  4. The generic keys, in the settings' iteration order.

[!NOTE] No ordering is guaranteed between two generic keys, so do not rely on one key being written before another. The special keys are always written before any generic key, which is why a generic BlendMode-adjacent property such as TranslucencyLightingMode sees the final blend mode.

Backend is consumed before any material exists — an unrecognized Backend value is a binding error, which stops the compile before the rest of Settings is applied, so no settings diagnostic of the build is reported for that file.

Interaction with Base.FrontMaterial

(since 2.0.0) The two 1.x checks on a Base.FrontMaterial binding — an explicit ShadingModel that is not Substrate or Strata, and Base.FrontMaterial together with Base.MaterialAttributes on one Shader — have no 2.0 diagnostic, and the compiler does not force the shading model to Substrate: an explicit ShadingModel is applied as written. See Output bindings, Substrate builtins and, for Substrate = Bridge, Substrate sugar.

The reflection resolver

Every key that is not special is resolved against the generated material by Unreal reflection.

#StepDetail
1Split the key into segments on . at bracket depth 0a 1.x key is one segment since 2.0.0 (see Nested and indexed paths)
2Parse each segment's optional trailing [<integer>]as above
3Map the segment name through the alias tableapplied per segment, before the field scan
4Scan TFieldIterator<FProperty> over the current struct, including super-classesso UMaterial, UMaterialInterface and UObject properties are all reachable
5Descenda non-terminal segment must be an FStructProperty; the walk continues inside the struct
6Write the valueparsed according to the resolved property's C++ type — see Value grammar

No property of that name is DSH7118.

Property-name matching

A segment matches a property when any of these three, after deleting spaces, _ and - and lowercasing, is equal to the segment:

RuleExample
The raw FProperty nameTwoSided ← TwoSided, two_sided, TWOSIDED
The property name with a leading b stripped, when the name is b followed by an uppercase letterbFullyRough ← FullyRough; bIsSky ← IsSky; bIsThinSurface ← IsThinSurface
The property's DisplayName metadatawhatever the engine declares for that property

The b-stripping rule is one-way and permissive: the full name still matches, so both bFullyRough = true; and FullyRough = true; resolve to the same property. A property whose name begins with a lowercase b followed by a non-uppercase character (for example bias) is not b-stripped.

Nested and indexed paths

The resolver itself still walks A.B (a member of a struct property), A[N] (element N of a fixed-size C array) and any composition of the two. (since 2.0.0) A 1.x Settings key cannot reach them: the legacy front end reads one name and reports DSH3261 at the . or the [. Two of the resolver's checks remain reachable:

WrittenCode
a fixed-size array (ArrayDim greater than 1) named without an index, e.g. PhysicalMaterialMap = …DSH7121
a name no property hasDSH7118

TArray, TMap and TSet properties are not indexable at all — they fall through to the ImportText catch-all in Value grammar.

Alias table

Ten fixed key aliases are applied per path segment before the field scan. Alias keys are compared in their separator-stripped, lowercased form, so Lighting_Mode and LIGHTINGMODE both hit the first row.

AliasResolves to
LightingModeTranslucencyLightingMode
TranslucentLightingModeTranslucencyLightingMode
RefractionModeRefractionMethod
PhysicalMaterialPhysMaterial
PhysicalMaterialMaskPhysMaterialMask
LightmassLightmassSettings
MobileSeparateTranslucencybEnableMobileSeparateTranslucency
AlwaysEvaluateWorldPositionOffsetbAlwaysEvaluateWorldPositionOffset
ResponsiveAAbEnableResponsiveAA
ThinSurfacebIsThinSurface

Value grammar

The resolved property's C++ type decides how the value text is parsed. The value has already been unquoted by the parser, so true and "true" are the same input.

Property typeAccepted literalCode on failure
booltrue / false, case-insensitive, trimmedDSH7132
int32signed integer literalDSH7133
uint32integer in [0, 4294967295]DSH7134
floata numeric literal — true / false are not numbers hereDSH7135
doubleas floatDSH7136
FStringany text, trimmed — never fails—
FNameany text, trimmed — never fails—
object referencePath( … ), an absolute object path such as /Game/Textures/T_Noise, or a Class'…' referenceDSH7137 (not a reference), DSH7138 (does not load), DSH7139 (wrong class), or the resolver's own code — see Path
enum class (FEnumProperty)an enum literalDSH7140
uint8 enum (FByteProperty with an enum)an enum literalDSH7141
plain uint8integer in [0, 255]DSH7142
anything elseUnreal struct-literal text, e.g. (R=1.0,G=0.0,B=0.0,A=1.0)DSH7143

A number is read the way Unreal's LexTryParseString reads it, which stops at the first character it cannot use: OpacityMaskClipValue = "0.5abc"; is 0.5.

The type's message is wrapped as DSH7125 while the block is validated (DSH7126 if the real material then refuses it), and that reaches you as DSH8215, which names the material and quotes the code.

[!NOTE] An object-typed property whose class derives from UTexture and whose property name is exactly Texture or TextureObject writes nullptr instead of erroring when the asset fails to load. This is the material-expression convention; it also applies here.

When an object-typed value is a reference — it starts with Path( or /, or ends with ' — and does not resolve, the sentence after DSH7125's period is the resolver's message.

Enum literals

An enum-typed value is matched after trimming, lowercasing and deleting every space, _, -, :, . and /. Values carrying Hidden metadata are skipped. A candidate matches any of:

FormExample for ETranslucencyLightingMode::TLM_Surface
the short enum nameTLM_Surface
the fully-qualified nameETranslucencyLightingMode::TLM_Surface
the display nameSurface
the short name with everything up to the first _ removedSurface

This matching is separate from the ShadingModel / BlendMode / Domain alias maps described in Material enums; those three keys never reach this code.

Path( … ) values

FormMeaning
Path("/Game/Foo/Bar")absolute object path, one argument
Path(Game, "Foo/Bar")/Game/Foo/Bar
Path(Engine, "Foo/Bar")/Engine/Foo/Bar
Path(Plugin.PluginName, "Foo/Bar")the named plugin's content root
/Game/Foo/Barbare absolute path, no Path( … ) wrapper

Backslashes are normalized to / and surrounding quotes are trimmed. The complete root catalogue and its codes are in Path.

Validation

Before anything is written to the real material, each generic key/value pair is applied to a transient probe UMaterial created in the transient package. The probe write and the real write use the same code, so a value that validates always applies. The only failure specific to this stage is DSH7124, a probe that could not be created.

Defaults — what an omitted setting resets to

A generated material is reset immediately before Settings is applied. An omitted key is therefore not "left as it was on the previous generation" — it takes the value below.

PropertyReset value
BlendModeOpaque
MaterialDomainSurface
shading modelDefaultLit
TwoSidedfalse
bUseMaterialAttributesfalse
OpacityMaskClipValue0.3333
Wireframefalse
DitheredLODTransitionfalse
DitherOpacityMaskfalse
bAllowNegativeEmissiveColorfalse
bCastDynamicShadowAsMaskedfalse
bCastRayTracedShadowstrue
bEnableResponsiveAAfalse
bScreenSpaceReflectionsfalse
bContactShadowsfalse
bDisableDepthTestfalse
bOutputTranslucentVelocityfalse
bWriteOnlyAlphafalse
BlendableOutputAlphafalse
TranslucencyLightingModeTLM_VolumetricNonDirectional
bTangentSpaceNormaltrue
bAlwaysEvaluateWorldPositionOffsetfalse
bFullyRoughfalse
bIsSkyfalse
bIsThinSurfacefalse
MaterialDecalResponseMDR_ColorNormalRoughness
bHasPixelAnimationfalse (since UE 5.4)
NumCustomizedUVs0
bUsedWithVolumetricCloudtrue when Domain="Volume", otherwise false

Every other UMaterial property keeps whatever a freshly constructed material has.

bUsedWithVolumetricCloud is the one entry above that is not a constant: the domain decides it. A Volume-domain material is a volumetric material, and the volumetric cloud renderer refuses one that is not flagged for it — so you never have to write the flag by hand. Write it explicitly to override the domain's choice; a Volume material that only ever feeds volumetric fog can turn the flag back off with bUsedWithVolumetricCloud = "false"; and save the cloud shader permutations.

The round-trip set

The decompiler emits Domain, ShadingModel and BlendMode unconditionally, plus each of the following when it differs from the UMaterial class default. This is the set guaranteed to survive a UMaterial → .dsm → UMaterial round trip; it is a subset of what Settings accepts, not a limit on it.

Booleans (40, in emit order)

TwoSided                    Wireframe                     DitheredLODTransition
DitherOpacityMask           bAllowNegativeEmissiveColor   bCastDynamicShadowAsMasked
bEnableResponsiveAA         bScreenSpaceReflections       bContactShadows
bDisableDepthTest           bOutputTranslucentVelocity    bTangentSpaceNormal
bFullyRough                 bIsSky                        bIsThinSurface
bHasPixelAnimation          bUsedWithSkeletalMesh         bUsedWithMorphTargets
bUsedWithClothing           bUsedWithNanite               bUsedWithEditorCompositing
bUsedWithParticleSprites    bUsedWithBeamTrails           bUsedWithMeshParticles
bUsedWithNiagaraSprites     bUsedWithNiagaraRibbons       bUsedWithNiagaraMeshParticles
bUsedWithGeometryCache      bUsedWithStaticLighting       bUsedWithSplineMeshes
bUsedWithInstancedStaticMeshes                            bUsedWithGeometryCollections
bUsedWithHairStrands        bUsedWithWater                bUsedWithVirtualHeightfieldMesh
bCastRayTracedShadows       bWriteOnlyAlpha               BlendableOutputAlpha
bAlwaysEvaluateWorldPositionOffset                        bUsedWithVolumetricCloud

bHasPixelAnimation is emitted only on UE 5.4 and newer.

bUsedWithVolumetricCloud is the one boolean not compared against the UMaterial class default: it is compared against the value the domain would give it (see the table above). On a Volume-domain material the value that needs no line is true, so it is the false that gets written out — which is what keeps a fog-only Volume material from coming back with the flag on.

Enums (1) — MaterialDecalResponse.

Reachable but never emitted by the decompiler, and therefore lost on a round trip: OpacityMaskClipValue, NumCustomizedUVs, TranslucencyLightingMode, RefractionMethod, RefractionDepthBias, TranslucencyPass, ShadingRate, FloatPrecisionMode, BlendableLocation, BlendablePriority, bIsBlendable, UserSceneTexture, StencilCompare, StencilRefValue, bEnableStencilTest, MaxWorldPositionOffsetDisplacement, PhysMaterial, PhysMaterialMask, and every other engine property the resolver can reach by name. Exact availability is engine-version dependent — the resolver is pure reflection over the engine's own property set.

Notes

  • The reflection surface is the engine's, not the plugin's. A custom or modified engine build exposes its own properties and its own enum values through the same resolver, so this manual's tables describe the stock UE 5.3 – 5.8 surface only.
  • Under the ThinCustom backend every setting lands on the hidden base UMaterial, not on the emitted UDreamShaderMaterialInstance. Reading the blend mode off the instance shows the inherited value.
  • A Settings block on a ShaderFunction does not share this behaviour. Only four keys are read there, and every key on this page is a DSH3263 warning there.
  • Duplicate keys across multiple Settings sections merge, last one wins, with a DSH3262 warning. See Settings.
  • A settings failure is reported once for the material, as DSH8215; the message names the material and quotes the reflected writer's code and message.

Diagnostics

Because keys are lowercased when they reach the emitter, the key quoted in these messages is the lowercased spelling, not what the source wrote.

CodeRaised when
DSH7127the BlendMode / RenderType value matched no alias
DSH7129the ShadingModel value matched no alias
DSH7128the value trims and case-folds to Substrate or Strata on UE 5.3
DSH7130the MaterialDomain / Domain value matched no alias
DSH7118no property matched — the usual "unknown key" error
DSH7121a fixed-size array property named without an index
DSH7124the probe material could not be allocated
DSH7125 / DSH7126the literal write failed on the probe / on the real material; the sentence after it is the type-specific code's message from Value grammar
DSH8215the build-time diagnostic every code above reaches you inside
DSH7200a key is set twice across #pragma material lines (a 1.x Settings block reports DSH3262 instead)
DSH7232Substrate is not Legacy, Bridge or Native
DSH3261a key that is not one name — including a nested path or an index

The Backend value is checked when the source is bound — see Backend. DSH7112–DSH7117, DSH7119, DSH7120, DSH7122 and DSH7123 concern nested and indexed paths and the resolver's own invariants; a 1.x key does not reach them.

Example

Shader(Name="Docs/M_ShaderSettings", Root="Game")
{
    Properties {
        VectorParameter BaseColor = float4(0.8, 0.8, 0.8, 1.0) [Group="Surface"];
        ScalarParameter Roughness = 0.55                       [Group="Surface"; Slider(0, 1)];
    }

    Settings {
        // Special keys.
        Domain       = "Surface";
        ShadingModel = "DefaultLit";
        BlendMode    = "Masked";

        // Reflected booleans; the b-prefix is optional.
        TwoSided   = true;
        FullyRough = true;
        bIsSky     = false;

        // Reflected scalar and enum.
        OpacityMaskClipValue = 0.25;
        MaterialDecalResponse = "ColorNormalRoughness";

        // Alias -> TranslucencyLightingMode, matched by display name.
        LightingMode = "Surface";

        // Object reference.
        PhysicalMaterial = Path(Engine, "EngineMaterials/DefaultPhysicalMaterial");
    }

    Outputs {
        vec3  Color;
        float Rough;
        float Mask;
        Base.BaseColor      = Color;
        Base.Roughness      = Rough;
        Base.OpacityMask    = Mask;
    }

    Graph {
        Color = BaseColor.rgb;
        Rough = Roughness;
        Mask  = BaseColor.a;
    }
}

Resulting material state:

BlendMode                = BLEND_Masked
MaterialDomain           = MD_Surface
ShadingModel             = MSM_DefaultLit
TwoSided                 = true
bFullyRough              = true
bIsSky                   = false
OpacityMaskClipValue     = 0.25
MaterialDecalResponse    = MDR_ColorNormalRoughness
TranslucencyLightingMode = TLM_Surface
PhysMaterial             = /Engine/EngineMaterials/DefaultPhysicalMaterial

See also

  • Settings — the block grammar and key normalization shared by every block kind
  • Material enums — every accepted ShadingModel, BlendMode and Domain value
  • Backend — the materialization key
  • Function settings — why none of this applies inside a ShaderFunction
  • Project settings — the mapping maps that extend the enum spellings
  • Shader — the enclosing block
  • Output bindings — Base.FrontMaterial and Base.MaterialAttributes
  • Path — the Path( … ) grammar used by object-typed settings
  • Metadata — the analogous reflected-property block on parameters
  • Decompiler — which settings survive a round trip
  • Regeneration — what a rebuild resets
  • Diagnostics index — every code

On this page