DreamShaderLang
Custom Pass Runtime

HLSL passes

The HLSL a compute pass, or a fullscreen pass without a material, runs — written in an hlsl block of the .dsp or in a .usf, the names its bindings make, the fixed parameters and helpers of DreamPass.ush, and how the code reaches the engine through a pre-check and a snapshot. Needs UE 5.8.

DreamShaderBuiltins.ush

DreamShader » Builtins » DreamShaderBuiltins.ush

An HLSL header shipped with the plugin, defining DS_* macros and functions that mirror the HLSL the material translator emits for the corresponding UE.* builtin nodes.

Kindshipped HLSL header
On disk<Plugin>/Shaders/DreamShaderBuiltins.ush
Virtual shader path/Plugin/DreamShader/DreamShaderBuiltins.ush
Include guardDREAMSHADER_BUILTINS_USH
Defines25 DS_* symbols — 22 macros and 3 functions
Emitted by the pluginno — see Reachability

Synopsis

#include "/Plugin/DreamShader/DreamShaderBuiltins.ush"

The virtual path

At module startup DreamShader registers a shader source directory mapping from the virtual directory /Plugin/DreamShader to the plugin's Shaders folder, unless a mapping for that virtual directory already exists. The mapping is unconditional — it does not depend on any project setting, backend choice or engine version — so /Plugin/DreamShader/DreamShaderBuiltins.ush always resolves for the engine's shader preprocessor.

This is a separate mapping from the generated shader virtual directory, /DreamShaderGenerated, which the module also registers. Since 2.0.0 DreamShader writes no per-source helper .ush there: the HLSL of a Function is embedded in the code of its Custom node. See Generated HLSL.

Reachability

Nothing in the plugin emits an include for this header, and nothing in the plugin references any DS_* symbol. The only occurrence of the name outside the file itself is a source comment.

PathIncludes this header?
A Custom node made from a Function blockno — the body is the node's code, other Functions it calls are embedded as DreamShaderFn_* members of a generated wrapper struct, and the node's include list holds only the #include lines at the head of the body (since 2.0.0; 1.x wrote a per-source helper .ush)
The Graph backendno — it emits material nodes, not HLSL
The ThinCustom backendno
A hand-written #include in a Function HLSL bodyyes — the virtual path resolves

The header's own comment describes it as being included by generated DSI_*.ush files inside the material translation unit. That was the arrangement used by the Instance backend, which has been retired: the resolved backend set is now Graph and ThinCustom, and Backend = "Instance" is an alias for ThinCustom (deprecated in 1.5.0). No DSI_*.ush file is produced any more, so the comment describes a path that no longer runs. See Backend.

Every state read the header exposes now has a material-node equivalent in the UE.* catalogue, and SampleTexture2D(tex, uv) in a Graph block desugars directly to a TextureSample node. Reaching for this header is therefore only useful inside hand-written HLSL.

Symbols

Parameters is the material parameter struct in scope at the include site; Tex is a texture parameter identifier, from which the sampler name is derived by token pasting (Tex##Sampler).

SymbolKindExpansionNode equivalent
DS_TIMEmacro(View.GameTime)UE.Time()
DS_REAL_TIMEmacro(View.RealTime)—
DS_DELTA_TIMEmacro(View.DeltaTime)—
DS_PERIODIC_TIME(Period)macro(fmod(View.GameTime, (Period)))UE.Time(Period=…)
DS_TexCoord(Parameters, CoordinateIndex)float2 functionParameters.TexCoords[CoordinateIndex].xy, or float2(0, 0) when NUM_TEX_COORD_INTERPOLATORS is 0UE.TexCoord
DS_VertexColor(Parameters)float4 functionParameters.VertexColorUE.VertexColor
DS_CameraVector(Parameters)macro((Parameters).CameraVector)UE.CameraVector
DS_ReflectionVector(Parameters)macro((Parameters).ReflectionVector)UE.ReflectionVector
DS_PixelNormalWS(Parameters)macro((Parameters).WorldNormal)UE.PixelNormalWS
DS_VertexNormalWS(Parameters)macro((Parameters).TangentToWorld[2])UE.VertexNormalWS
DS_TwoSidedSign(Parameters)macro((Parameters).TwoSidedSign)UE.TwoSidedSign
DS_ViewportUV(Parameters)macro(GetViewportUV(Parameters))UE.ViewportUV
DS_PixelDepth(Parameters)macro(GetPixelDepth(Parameters))UE.PixelDepth
DS_WorldPosition(Parameters)macro(WSDemote(GetWorldPosition(Parameters)))UE.WorldPosition
DS_TranslatedWorldPosition(Parameters)macro(GetTranslatedWorldPosition(Parameters))UE.TranslatedWorldPosition
DS_ObjectPosition(Parameters)macro(WSDemote(GetObjectWorldPosition(Parameters)))UE.ObjectPosition
DS_ObjectRadius(Parameters)macro(GetPrimitiveData(Parameters).ObjectRadius)UE.ObjectRadius
DS_ObjectBounds(Parameters)macro(float3(GetPrimitiveData(Parameters).ObjectBoundsX, …ObjectBoundsY, …ObjectBoundsZ))UE.ObjectBounds
DS_CameraPosition(Parameters)macro(WSDemote(GetWorldCameraOrigin(Parameters)))UE.CameraPosition
DS_PerInstanceRandom(Parameters)macro(GetPerInstanceRandom(Parameters))UE.PerInstanceRandom
DS_PerInstanceFadeAmount(Parameters)macro(GetPerInstanceFadeAmount(Parameters))UE.PerInstanceFadeAmount
DS_Panner(UV, Time, Speed)float2 functionUV + float2(frac(Time * Speed.x), frac(Time * Speed.y))UE.Panner
DS_SampleTexture2D(Tex, UV)macroTexture2DSample(Tex, Tex##Sampler, UV)SampleTexture2D(tex, uv) in a Graph block
DS_SampleTexture2DLod(Tex, UV, Lod)macroTexture2DSampleLevel(Tex, Tex##Sampler, UV, Lod)—
DS_SampleTexture2DBias(Tex, UV, Bias)macroTexture2DSampleBias(Tex, Tex##Sampler, UV, Bias)—

The WSDemote calls lower the engine's large-world-coordinate vectors to float3. The translated (camera-relative) position form is already float3 and keeps precision near the camera.

The header's comment notes that the DSL used to write the unprefixed spellings SampleTexture2D / SampleTexture2DLod / SampleTexture2DBias and have the generator lower them to these macros. No such rewrite is performed today. SampleTexture2D is still a reserved name in a Graph block, where it desugars to a TextureSample node — see UE.Expression — but the Lod and Bias spellings have no Graph equivalent.

Notes

[!NOTE] Put the #include first. An #include written at the top of a Function body (only whitespace and comments before it) is taken out of the body and put on the Custom node's include list, which the engine includes outside the generated function — see Function ▸ Includes — so the header's function definitions compile normally. An #include that comes after a statement, or after any other # line, stays in the body, which the engine pastes inside a function; there the 22 macros still work (a #define is legal anywhere) but the three function definitions (DS_TexCoord, DS_VertexColor, DS_Panner) are not legal inside another function body.

[!WARNING] DS_TexCoord and DS_VertexColor depend on translator side effects that nothing arranges any more. DS_TexCoord reads Parameters.TexCoords[…], which only exists when at least one interpolator slot was allocated during material translation (NUM_TEX_COORD_INTERPOLATORS > 0); with no slot allocated the function compiles and returns float2(0, 0). DS_VertexColor reads Parameters.VertexColor, which is only fed when the material was translated with vertex-colour usage set. The retired Instance backend arranged both by compiling matching dummy input chunks. Under the Graph and ThinCustom backends nothing does, so use UE.TexCoord and UE.VertexColor — or a wired Function input — instead of these two.

  • The remaining reads are side-effect free. Every field and Get*(Parameters) helper they touch is populated unconditionally at pixel entry, so they compile in any opaque Surface pixel evaluation with no usage flag or interpolator request.
  • DS_PerInstanceRandom and DS_PerInstanceFadeAmount are meaningful only for instanced or GPU-culled draws. On a plain mesh they read back safe constants (0 and 1 respectively) with no compile error.
  • The header is guarded by DREAMSHADER_BUILTINS_USH, so including it more than once in the same translation unit is harmless.
  • Inside a Function body the GLSL-alias pass rewrites whole identifiers before the body is emitted — vec3 → float3, mix → lerp, fract → frac, mod → fmod, and so on. It skips string literals and comments, so the include path in #include "…" is never rewritten.

Example

A top-level Function whose HLSL body uses only the macro half of the header:

Function vec2 Wobble(in vec2 uv, in float speed)
{
    #include "/Plugin/DreamShader/DreamShaderBuiltins.ush"
    float t = DS_TIME * speed;
    return uv + float2(sin(t), cos(t)) * 0.02;
}

The include resolves through the registered virtual directory, and DS_TIME expands to (View.GameTime).

The node-based equivalent, which needs no include and no HLSL helper at all:

GraphFunction vec2 Wobble(in vec2 uv, in float speed)
{
    float t = UE.Time() * speed;
    return uv + vec2(sin(t), cos(t)) * 0.02;
}

See also

On this page