DreamShaderLang
Plugin referenceC++ API

DreamShaderSettings.h

DreamShaderSettings.h

DreamShaderSettings.h

DreamShader » C++ API » DreamShaderSettings.h

The project-settings object, the default-backend and graph-layout enumerations, and the name-to-engine-enum resolvers that back every ShadingModel, BlendMode and Domain value spelling.

Defined in header DreamShaderSettings.h.

ModuleDreamShader (Runtime)
Include#include "DreamShaderSettings.h"
Namespaceglobal scope
Export macroDREAMSHADER_API on UDreamShaderSettings
Reflection2 UENUMs, 1 UCLASS with 17 UPROPERTYs
Pulls inCoreMinimal.h, Engine/DeveloperSettings.h, Engine/EngineTypes.h, MaterialDomain.h (since 1.3.6)

EDreamShaderDefaultBackend

/** Backend used for source files that do not specify Settings = { Backend = "..." } themselves. */
UENUM()
enum class EDreamShaderDefaultBackend : uint8
{
    Graph,
    Instance,
    ThinCustom,
};
EnumeratorValueMeaning
Graph0Build a UMaterial node graph per material — the full DSL feature surface, one visible asset.
Instance1Deprecated alias for ThinCustom (since 1.5.0). Kept for one deprecation window so existing configs and Settings = { Backend = "Instance" } sources keep working. The legacy graphless-host instance backend is retired.
ThinCustom2Build the graph on a hidden per-material base UMaterial and emit a lightweight material instance of it. The default.

[!WARNING] A project configured with DefaultBackend = Instance produces exactly the same asset as ThinCustom with no warning and no log line; the only indication is the tooltip and this documentation. A source file that writes Backend = "Instance" is told so: it builds ThinCustom with warning DSH7204 (since 2.0.0).

Resolution at compile time

The project setting is mapped by the compile pipeline (Instance and ThinCustom to ThinCustom, Graph to Graph) and handed to the binder, which applies a per-file Backend on top of it.

Settings = { Backend = … }DefaultBackendResolved backend
(absent)InstanceThinCustom
(absent)ThinCustomThinCustom
(absent)GraphGraph
"Instance"(any)ThinCustom, warning DSH7204 (since 2.0.0)
"ThinCustom"(any)ThinCustom
"Graph"(any)Graph
"" (empty string)(any)error DSH7201 (since 2.0.0; 1.x took it as Graph)
anything else(any)error DSH7202

The Backend value is compared case-insensitively with surrounding whitespace and quotes trimmed. See Backend.

EDreamShaderGraphLayoutStyle (since 2.0.0)

/** How the nodes of a generated graph are placed. */
UENUM()
enum class EDreamShaderGraphLayoutStyle : uint8
{
    Classic,
    Blocks,
    SourceBands,
    Layered,
};
EnumeratorValueMeaning
Classic0The 1.x layout, computed on the finished graph.
Blocks1One box per #pragma region or run of statements, in source order; named reroutes between boxes. The default.
SourceBands2One horizontal band per source statement; inserts no reroute.
Layered3One layered drawing of the whole graph; inserts no reroute.

The three non-Classic styles are computed on the compiler's IR. Node positions are not part of a generated asset's digest. See Graph layout.

UDreamShaderSettings

UCLASS(Config=Engine, DefaultConfig, meta=(DisplayName="DreamShader"))
class DREAMSHADER_API UDreamShaderSettings : public UDeveloperSettings
{
    GENERATED_BODY()

public:
    UDreamShaderSettings();

    virtual FName GetContainerName() const override;
    virtual FName GetCategoryName() const override;
    virtual FName GetSectionName() const override;
#if WITH_EDITOR
    virtual FText GetSectionText() const override;
    virtual FText GetSectionDescription() const override;
    virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif

    bool TryResolveShadingModel(const FString& InName, EMaterialShadingModel& OutShadingModel) const;
    bool TryResolveBlendMode(const FString& InName, EBlendMode& OutBlendMode) const;
    bool TryResolveMaterialDomain(const FString& InName, EMaterialDomain& OutMaterialDomain) const;

    static FString NormalizeMappingKey(const FString& InName);
    static void BuildDefaultShadingModelMappings(TMap<FString, TEnumAsByte<EMaterialShadingModel>>& OutMappings);
    static void BuildDefaultBlendModeMappings(TMap<FString, TEnumAsByte<EBlendMode>>& OutMappings);
    static void BuildDefaultMaterialDomainMappings(TMap<FString, TEnumAsByte<EMaterialDomain>>& OutMappings);

    virtual void PostInitProperties() override;

    // 17 UPROPERTYs — see below.

private:
    static FString NormalizeShadingModelKey(const FString& InName);
    static FString NormalizeBlendModeKey(const FString& InName);
    static FString NormalizeMaterialDomainKey(const FString& InName);
};

Obtain it with GetDefault<UDreamShaderSettings>() — it is a UDeveloperSettings, so the class default object is the live configured instance. There is no subsystem and no getter on the module.

Panel location

All five panel overrides are inline and return constants.

OverrideReturnsAvailability
GetContainerName()TEXT("Project")always
GetCategoryName()TEXT("DreamPlugin")always
GetSectionName()TEXT("DreamShader")always
GetSectionText()"Dream Shader"WITH_EDITOR only
GetSectionDescription()"Dream Shader Settings"WITH_EDITOR only

The panel is therefore Project Settings ▸ DreamPlugin ▸ Dream Shader — not under Plugins. The UCLASS specifiers Config=Engine, DefaultConfig persist every Config property to the project's Config/DefaultEngine.ini, section [/Script/DreamShader.DreamShaderSettings].

Constructor

UDreamShaderSettings::UDreamShaderSettings() sets exactly two members:

SourceDirectory.Path          = TEXT("DShader");
GeneratedShaderDirectory.Path = TEXT("Intermediate/DreamShader/GeneratedShaders");

[!NOTE] The three *Mappings maps start empty and stay empty unless a user adds entries. The built-in alias catalogues are never materialized into them; they are rebuilt into a throwaway local map inside each TryResolve* call. An empty Mappings panel does not mean "no aliases are recognized".

Properties

Every UPROPERTY is Config, EditAnywhere.

PropertyTypeCategoryDefaultExtra metadata
ShadingModelMappingsTMap<FString, TEnumAsByte<EMaterialShadingModel>>Mappingsempty—
BlendModeMappingsTMap<FString, TEnumAsByte<EBlendMode>>Mappingsempty—
MaterialDomainMappingsTMap<FString, TEnumAsByte<EMaterialDomain>>Mappingsempty—
SourceDirectoryFDirectoryPathPathsDShaderRelativeToGameDir
GeneratedShaderDirectoryFDirectoryPathPathsIntermediate/DreamShader/GeneratedShadersRelativeToGameDir
bScanPluginSourceDirectoriesboolPathstrueDisplayName="Scan Plugin Source Directories", ToolTip
DefaultBackendEDreamShaderDefaultBackendCompilerThinCustomDisplayName="Default Compiler Backend", ToolTip
bShowEphemeralMaterialsboolCompilerfalseDisplayName="Show Ephemeral Materials", ToolTip
PreprocessorDefinesTMap<FString, FString>CompileremptyDisplayName="Preprocessor Defines", ToolTip
GraphLayoutStyleEDreamShaderGraphLayoutStyleCompilerBlocksDisplayName="Graph Layout Style", ToolTip
bAutoCompileOnSaveboolCompilertrue—
SaveDebounceSecondsfloatCompiler0.25fClampMin="0.05", ClampMax="10.0", UIMin="0.05", UIMax="2.0"
bVerboseLogsboolCompilerfalse—
bExportDecompiledLayoutboolDecompilertrue—
bOpenInNewWindowboolEditortrue—
InstanceSubfolderFStringEditorTEXT("Instances")DisplayName="Material Instance Subfolder", ToolTip
bSyncSourceReferencesOnAssetRenameboolEditortrueDisplayName="Sync Source References On Asset Rename", ToolTip

What each property does is on Project settings; this page documents the declaration.

[!NOTE] There is deliberately no persistence on/off toggle. The header records the reason: ThinCustom products are Ephemeral by default in the editor — source files are the authoring surface — and materialize on an explicit action, a cook, or when a child instance is created. Graph materials and material functions have no Ephemeral state at all. DefaultBackend is the single compiler knob. See Ephemeral materials.

NormalizeMappingKey

static FString NormalizeMappingKey(const FString& InName);

Applies, in order: TrimStartAndEndInline(), ToLowerInline(), then removal of every " ", "_" and "-".

InputResult
"Two Sided Foliage""twosidedfoliage"
"two-sided_foliage""twosidedfoliage"
" TWOSIDEDFOLIAGE ""twosidedfoliage"
"Runtime Virtual Texture""runtimevirtualtexture"

Alias matching is therefore case-, space-, underscore- and hyphen-insensitive.

[!WARNING] Do not confuse this with UE::DreamShader::NormalizeSettingKey, which only trims and lower-cases. NormalizeMappingKey applies to setting values (enum aliases); NormalizeSettingKey applies to setting keys. See the normalizer comparison.

The three private forwarders NormalizeShadingModelKey, NormalizeBlendModeKey and NormalizeMaterialDomainKey call NormalizeMappingKey and add nothing.

The resolvers

bool TryResolveShadingModel(const FString& InName, EMaterialShadingModel& OutShadingModel) const;
bool TryResolveBlendMode(const FString& InName, EBlendMode& OutBlendMode) const;
bool TryResolveMaterialDomain(const FString& InName, EMaterialDomain& OutMaterialDomain) const;

All three share one algorithm:

StepAction
1Normalize InName with NormalizeMappingKey.
2Linear-scan the user-configured map, normalizing each stored key on the fly. On a match, write OutValue and return OutValue != <ENUM>_MAX.
3If nothing matched, build the default catalogue into a fresh local map and scan it identically.
4Return false. OutValue is left untouched.
AspectBehaviour
PrecedenceThe user map always wins; the first normalized-key match returns immediately.
Disabling an aliasAn entry mapped to MSM_MAX / BLEND_MAX / MD_MAX overwrites OutValue with that sentinel and returns false. It does not fall through to the built-in table.
AmbiguityTwo user entries whose keys normalize identically are resolved in TMap iteration order, which is unspecified.
OutValue on failureUntouched by steps 1–4 unless the MAX sentinel case above applied.
Constnessconst; safe on the CDO.

[!NOTE] Step 3 rebuilds the entire default catalogue — including a full StaticEnum walk with per-index metadata queries — on every miss of the user map. Because the user maps are empty by default, that is effectively every call. This is fine at generation frequency; do not call these in a per-node or per-frame loop.

Building the default catalogues

static void BuildDefaultShadingModelMappings(TMap<FString, TEnumAsByte<EMaterialShadingModel>>& OutMappings);
static void BuildDefaultBlendModeMappings(TMap<FString, TEnumAsByte<EBlendMode>>& OutMappings);
static void BuildDefaultMaterialDomainMappings(TMap<FString, TEnumAsByte<EMaterialDomain>>& OutMappings);

Each appends to OutMappings — it does not clear it — in two phases.

Phase 1: reflected

Walk StaticEnum<T>() index by index. For each index:

StepRule
1Read the value and the name string.
2Read the Hidden metadata — only under WITH_EDITORONLY_DATA.
3Apply the per-enum skip predicate; continue if it returns true.
4Build the alias: take the name, drop everything up to and including the last : (scoped-enum support), then RemoveFromStart(<Prefix>, ESearchCase::CaseSensitive).
5Add it, additively.

[!WARNING] UEnum metadata is editor-only. In non-editor and shipping builds bHidden is hard-coded to false, so nothing is dropped for being hidden and only the name- and value-based parts of the skip predicate apply. A shipping build can therefore recognize a few extra aliases the editor rejects. This is a deliberate fix: UEnum::HasMetaData does not compile in those configurations.

Phase 2 adds literal aliases through the same additive helper.

Additive-only semantics

The helper skips an alias when it trims to empty, or when the map already contains that exact FString key — an exact, case-sensitive, unnormalized key comparison. Because the reflected phase runs first, an explicit alias that is character-identical to a reflected one is a silent no-op.

EMaterialShadingModel — prefix MSM_

Skip predicate:

ConditionResult
Name is Strata or MSM_Strata, or the value is MSM_StrataKept when DREAMSHADER_WITH_SUBSTRATE_BUILTINS (UE ≥ 5.4); dropped otherwise. This test runs first and short-circuits the Hidden check.
Hidden metadataskip
Name is NUM, MSM_NUM, MAX, MSM_MAX, FromMaterialExpression or MSM_FromMaterialExpressionskip
Value is MSM_NUM, MSM_MAX or MSM_FromMaterialExpressionskip

Reflected aliases — 12, plus Strata on UE ≥ 5.4:

UnlitDefaultLitSubsurfacePreintegratedSkin
ClearCoatSubsurfaceProfileTwoSidedFoliageHair
ClothEyeSingleLayerWaterThinTranslucent
Strata (since UE 5.4)

Explicit aliases — 8, plus 2 on UE ≥ 5.4:

AliasValueNote
Default LitMSM_DefaultLit
LitMSM_DefaultLit
Preintegrated SkinMSM_PreintegratedSkin
Clear CoatMSM_ClearCoat
Subsurface ProfileMSM_SubsurfaceProfile
Two Sided FoliageMSM_TwoSidedFoliage
Single Layer WaterMSM_SingleLayerWater
Thin TranslucentMSM_ThinTranslucent
SubstrateMSM_Strata(UE 5.4+ only)
StrataMSM_Strata(UE 5.4+ only); no-op — the reflected phase already added the identical key

EBlendMode — prefix BLEND_

Skip predicate: Hidden metadata, or the name is MAX or BLEND_MAX, or the value is BLEND_MAX.

Reflected aliases — 8:

OpaqueMaskedTranslucentAdditive
ModulateAlphaCompositeAlphaHoldoutTranslucentColoredTransmittance

BLEND_TranslucentGreyTransmittance and BLEND_ColoredTransmittanceOnly are engine value aliases marked UMETA(Hidden) and are dropped by the Hidden test in editor builds.

Explicit aliases — 4:

AliasValue
CutoutBLEND_Masked
TransparentBLEND_Translucent
PremultipliedAlphaBLEND_AlphaComposite
PremultipliedBLEND_AlphaComposite

EMaterialDomain — prefix MD_

Skip predicate: Hidden metadata unless the value is MD_RuntimeVirtualTexture, or the name is MAX or MD_MAX, or the value is MD_MAX. The exception is deliberate — the engine marks MD_RuntimeVirtualTexture hidden, and DreamShader keeps it usable.

Reflected aliases — 7:

SurfaceDeferredDecalLightFunctionVolume
PostProcessUIRuntimeVirtualTexture

Explicit aliases — 9 written, 8 effective:

AliasValueNote
DeferredDecalMD_DeferredDecalno-op — the reflected key is identical
DecalMD_DeferredDecal
Light FunctionMD_LightFunction
Post ProcessMD_PostProcess
UserInterfaceMD_UI
User InterfaceMD_UI
Runtime Virtual TextureMD_RuntimeVirtualTexture
VirtualTextureMD_RuntimeVirtualTexture
Virtual TextureMD_RuntimeVirtualTexture

[!NOTE] The spaced aliases are lookup-redundant: NormalizeMappingKey strips spaces, so Two Sided Foliage and TwoSidedFoliage normalize to the same key that the reflected phase already covers. They exist as distinct map entries so that the Project Settings panel and the bridge manifest consumed by the editor extensions can offer human-readable spellings.

The user-facing catalogue, including which spellings are recommended, is on Material enums.

Notes

  • The reflected phase enumerates the engine's enum, so the exact reflected set is whatever the engine version defines. The tables above list the result on a current engine; the only entry the plugin itself gates by version is Strata.
  • TEnumAsByte<T> is used throughout because TMap value types in a UPROPERTY must be reflectable and these engine enums are not enum class.
  • PostEditChangeProperty (editor only) reacts to one property: an edit of PreprocessorDefines bumps the define revision, before Super broadcasts the change. Every other settings change is handled by the editor module's own panel hooks.
  • PostInitProperties folds the pre-2.0 config key bShowInMemoryMaterialsInContentBrowser into bShowEphemeralMaterials when only the old key is present (since 2.0.0).
  • MaterialDomain.h is included by this header (since 1.3.6), so a translation unit that includes DreamShaderSettings.h gets EMaterialDomain without adding an include of its own.

Example

Resolving a user-written spelling to an engine enum:

#include "DreamShaderSettings.h"

bool ApplyShadingModelSetting(UMaterial* Material, const FString& InValue, FString& OutError)
{
    const UDreamShaderSettings* Settings = GetDefault<UDreamShaderSettings>();

    EMaterialShadingModel ShadingModel = MSM_DefaultLit;
    if (!Settings->TryResolveShadingModel(InValue, ShadingModel))
    {
        OutError = FString::Printf(TEXT("Unknown ShadingModel '%s'."), *InValue);
        return false;
    }

    Material->SetShadingModel(ShadingModel);
    return true;
}

All four of these calls succeed and select the same shading model:

ApplyShadingModelSetting(M, TEXT("TwoSidedFoliage"),   Error);
ApplyShadingModelSetting(M, TEXT("Two Sided Foliage"), Error);
ApplyShadingModelSetting(M, TEXT("two-sided_foliage"), Error);
ApplyShadingModelSetting(M, TEXT("  TWOSIDEDFOLIAGE"), Error);

Enumerating the built-in catalogue without a settings object — this is how the workspace service exports the alias manifest:

TMap<FString, TEnumAsByte<EBlendMode>> Aliases;
UDreamShaderSettings::BuildDefaultBlendModeMappings(Aliases);   // 12 entries: 8 reflected + 4 explicit

See also

On this page