DreamShaderLang
Plugin referenceGraph

Constructors

Constructors

Constructors

DreamShader » Graph » Constructors

Call-syntax expressions named after a scalar or vector type that build a value of that width from their arguments.

Declared in.dsm, .dsf — inside a Graph { … } body, an Outputs binding expression, or an Outputs declaration default
Kindexpression, call form
GeneratesUMaterialExpressionAppendVector (one per argument after the first), or one UMaterialExpressionConstant / Constant2Vector / Constant3Vector / Constant4Vector when every argument is constant; nothing at all in the pass-through and broadcast cases

Synopsis

<constructor-call> := <constructor-name> ( <expression> [ , <expression> ] … )

Named arguments are rejected. A brace initializer is exactly a constructor call: vec3 rgb = {r, g, b}; is rewritten as vec3(r, g, b) and obeys every rule on this page.

The parser reads a constructor name as a type (since 2.0.0): the call never reaches the function lookup, and the binder checks it as it checks a .dss constructor.

Constructor names

34 names, all matched case-insensitively (FLOAT3(…) works). The component count is the number at the end of the name; a name without one, or with 1, is a scalar.

NameComponentsKindFamily
float1floatHLSL float
float11floatHLSL float
float22floatHLSL float
float33floatHLSL float
float44floatHLSL float
half1halfHLSL half — identical behaviour to float
half11halfHLSL half
half22halfHLSL half
half33halfHLSL half
half44halfHLSL half
vec22floatGLSL float vector
vec33floatGLSL float vector
vec44floatGLSL float vector
int1intHLSL signed integer
int22intHLSL signed integer
int33intHLSL signed integer
int44intHLSL signed integer
ivec22intGLSL signed integer vector
ivec33intGLSL signed integer vector
ivec44intGLSL signed integer vector
uint1uintHLSL unsigned integer
uint22uintHLSL unsigned integer
uint33uintHLSL unsigned integer
uint44uintHLSL unsigned integer
uvec22uintGLSL unsigned integer vector
uvec33uintGLSL unsigned integer vector
uvec44uintGLSL unsigned integer vector
bool1boolHLSL boolean
bool22boolHLSL boolean
bool33boolHLSL boolean
bool44boolHLSL boolean
bvec22boolGLSL boolean vector
bvec33boolGLSL boolean vector
bvec44boolGLSL boolean vector

(since 2.0.0) the parser takes every spelling the HLSL type grammar has, in any case, so a few more names are constructors:

NameComponentsNote
int1, uint1, bool11HLSL's spelling of a scalar, as float1 is
double, double1 … double41–4kind double; a float in the graph like every number
StaticBool1read as bool, as it is in a declaration
float2x2 … float4x4, mat2, mat3, mat4 (and the NxM of the other families)—a matrix, which the graph has no value for: DSH4361

Names that do not exist

AbsentReason
vec1, ivec1, uvec1, bvec1The GLSL families start at 2
hvec2, hvec3, hvec4No GLSL half family
dvec2, dvec3, dvec4No GLSL double family
Scalar, Vector, ColorRemoved type aliases; see Types

Every name above lexes as an ordinary identifier and, because it is not a type, falls through to the function lookup — DSH4208 unless a function of that name is declared.

MaterialAttributes, Substrate, the texture types and SamplerState are type names too, but no value of them can be constructed: Texture2D(…) is DSH4223.

[!WARNING] Constructor names shadow everything. A constructor name is read as a type while the call is parsed — before UE.* builtins, Substrate.* builtins, math builtins, parameters, and all user definitions are looked at. A Function, GraphFunction, ShaderFunction or VirtualFunction named float3, int, bool4, vec2 (or any other name in the tables) can be declared without a diagnostic but can never be called — every call site builds a constructor instead. See Name resolution.

Integer constructors

The integer names are int, int1..4, ivec2..4, uint, uint1..4 and uvec2..4. Their result is an int or uint value to the compiler.

The kind does exactly one thing: / is refused when both operands are integer constructor calls (DSH4243), as in 1.x. It performs no truncation, no rounding, and no range clamping — an integer constructor produces the same float-valued graph as its float counterpart, and int(7.9) is 7.9. See Integer division.

The kind comes from the constructor's own name, so wrapping in a non-integer constructor clears it: float(int(7)) is a float.

Argument rules

The call and its arguments are checked first; every check that fails is reported.

#ConditionBehaviour
1Any argument is named (float3(x = 1.0))DSH4225
2No argument at all (float3())DSH4221
3An argument is not a number or a bool — a texture object, a MaterialAttributes or a Substrate value — or is a matrixDSH4226

Then, with N the constructor's component count:

#CaseBehaviourNodes created
4exactly one argument, with N components (for N == 1, a scalar)the argument is returned unchanged; only its kind changesnone
5N > 1, exactly one argument, and that argument is a scalarbroadcast: the scalar is wired where the value is read, and the material node replicates it (since 2.0.0; 1.x built an AppendVector chain)none; one ConstantNVector when the scalar is constant
6otherwisethe arguments' component counts must sum to exactly None AppendVector per argument after the first
7the sum is not NDSH4222—

Component packing

Rule 6 is a straight left-to-right concatenation of channels — arguments of mixed widths are legal as long as the total is exact.

CallTotalValidResult
float4(rgb, 1.0)3 + 1yesfloat4
float4(uv, uv)2 + 2yesfloat4
float3(x, yz)1 + 2yesfloat3
float4(x, y, z, w)1×4yesfloat4
vec3(0.5)scalar broadcast (rule 5)yes(0.5, 0.5, 0.5)
float3(rgba)4noDSH4222
float3(uv)2noDSH4222
float(rgb)3noDSH4222
float3()0noDSH4221

[!NOTE] A constructor never narrows, in a 1.x source either. float3(rgba) is an error, not a truncation; write rgba.rgb. Narrowing happens only at conversion sites — see Conversions. Widening happens only from a scalar (rule 5); float3(uv) will not zero-fill.

Constant folding

When every argument is a constant, the whole call is one constant node instead of N Constant nodes plus AppendVector nodes: a Constant / Constant2Vector / Constant3Vector / Constant4Vector holding the values. A constant is a numeric literal, a negated one, a const property, a variable that holds one, or any arithmetic on constants: the folding pass folds operators, constructors and swizzles whose operands are all constants (since 2.0.0).

WrittenFolded to
vec2(0.5, 1.0)Constant2Vector(0.5, 1.0)
vec3(0.5)Constant3Vector(0.5, 0.5, 0.5) — the broadcast folds too
float4(1.0, 2.0, 3.0, -1.0)Constant4Vector(1, 2, 3, -1)
int3(1, 2, 3)Constant3Vector(1, 2, 3) (since 2.0.0); the value stays an int3 to the compiler
vec3(K, 0.0, 0.0)not folded when K is a parameter — two AppendVector nodes

Every value has the width of its type; a folded constructor has no width of its own that would override a declaration (since 2.0.0). See Conversions.

Equal constants are one node: vec3(0.5) written five times yields one Constant3Vector. See Node reuse.

Notes

  • Rule 4 creates no node. float3(SomeFloat3) is a no-op wrapper; float3(SomeInt3) only changes the kind to float.
  • A constructor call is an ordinary postfix expression and can be swizzled: vec4(uv, 0, 1).xy.
  • A brace initializer with an empty body (float3 v = {};) does not reach a constructor at all — it produces the type's zero value. See Declarations.
  • Nested brace initializers are not supported: float4 m = {{1,2},{3,4}}; is rewritten to float4({1,2},{3,4}), and a brace list as an argument is DSH2214.
  • An output selector (Output=, OutputIndex=) on a constructor is DSH5253.

Diagnostics

CodeRaised when
DSH4225Any name = value argument.
DSH4221A constructor with no argument.
DSH4226An argument that is a texture object, a MaterialAttributes or Substrate value, or a matrix.
DSH4222The argument widths do not sum to the constructor's width, and the call is not one scalar.
DSH4223A type with no constructor: MaterialAttributes, Substrate, a texture type, SamplerState.
DSH4361A matrix constructor: the graph has no matrix values.
DSH2214A brace list nested in a brace initializer.
DSH5253An output selector on a constructor.
DSH4208A misspelled constructor (vec1, float5) falls through to the function lookup.
DSH8214The emitter could not create an AppendVector or constant node.

Example

Shader(Name="Docs/M_Constructors", Root="Game")
{
    Properties { ScalarParameter K = 0.5; }
    Settings   { Domain = "Surface"; ShadingModel = "Unlit"; BlendMode = "Opaque"; }
    Outputs    { vec3 Color; Base.EmissiveColor = Color; }

    Graph {
        float  a    = frac(K * 3.0);
        vec3   grey = vec3(a);              // rule 5: scalar broadcast, no node
        vec3   tint = vec3(0.2, 0.4, 0.8);  // constant-folded to Constant3Vector
        vec2   uv   = float2(a, 1.0);       // rule 6: 1 + 1 packing
        Color = tint * grey + float3(uv, 0.0);   // rule 6: 2 + 1 packing
    }
}

Generated nodes:

ScalarParameter K
Constant(3.0), Multiply, Frac                      -> a
(no node)                                          -> vec3(a): `a` is wired where grey is read
Constant3Vector(0.2, 0.4, 0.8)                     -> tint               (folded, 1 node)
Multiply                                           -> tint * grey
Constant(1.0), AppendVector                        -> float2(a, 1.0)     (1 node)
Constant(0.0), AppendVector                        -> float3(uv, 0.0)
Add                                                -> Base.EmissiveColor

See also

On this page