DreamShaderLang
Plugin referenceGraph

Literals

Literals

Literals

DreamShader » Graph » Literals

The three literal forms a Graph expression can contain: numeric literals, string literals, and the boolean literals true / false.

Declared in.dsm, .dsf — inside a Graph { … } body, an Outputs binding expression, or an Outputs declaration default
Kindexpression primary
GeneratesUMaterialExpressionConstant (numeric and boolean); a string literal generates nothing on its own

A 1.x Graph body is read by the DreamShaderLang 2.0 lexer (since 2.0.0): the token rules below are the 2.0 ones, and the few 1.x readings that differ are refused with a code that says what 1.x did.

Synopsis

<number-literal> := { <digit> | . } … [ { e | E } [ { + | - } ] <digit> … ] [ <suffix> … ]
<suffix>         := { f | F | h | H | u | U | l | L }
<string-literal> := " <character> … "
<bool-literal>   := { true | false }

A numeric literal starts at a digit, or at a . that is immediately followed by a digit. [ … ], { a | b } and … are meta-notation; ., e, +, - and " are literal characters.

Numeric literals

A literal without a fraction, an exponent or a float suffix is an integer to the compiler — int, or uint with a u (since 2.0.0); every other one is a float (half with an h). In the generated graph every literal is the same thing: a 1-component float Constant.

WrittenKindValueResult
1int1.0Constant, 1 component
1.0float1.0the same Constant node as 1
0.5float0.5Constant
.5float0.5Constant — a leading . is legal
1.float1.0Constant — a trailing . is legal
1e-3float0.001Constant
2.5E+2float250.0Constant
0.55ffloat0.55Constant
0.5hhalf0.5Constant
3uuint3.0Constant — an unsigned integer (since 2.0.0)
0.5.5——DSH2105 (since 2.0.0; 1.x silently read 0.5)
0x10——DSH2222 — a hexadecimal literal, which 1.x never read as one
1.0fx——DSH2105 — the letters belong to the number
3uluint3.0Constant — u and l are both integer suffixes (since 2.0.0)

Lexing details:

  • A number is one token: digits, at most one ., at most one exponent, then suffix letters. Anything still glued to it — another ., letters, digits after a suffix — belongs to the same token and makes it DSH2105 (since 2.0.0; 1.x kept the longest valid prefix and dropped the rest). So 0.5.5, 0..5, 1abc and 1.0fx are errors, not numbers.
  • An exponent needs digits: 1e and 1e+ are DSH2105. The sign of an exponent may be + or - and is read only immediately after e/E.
  • A hexadecimal literal (0x1F) is an integer to the lexer and refused in a 1.x Graph (DSH2222). There is no binary or octal notation, and no digit separators.
  • A leading - is not part of the literal; it is the unary minus operator. A negated literal folds into one Constant.

Numeric suffixes

Suffix letters are kept in the literal's text and decide its kind; the value is the number in front of them.

SuffixHLSL/GLSL meaningEffect in DreamShaderLang
f, Ffloata float literal
h, Hhalfa half literal
u, Uunsigned inta uint literal
l, Llongan integer literal

Rules:

  • Several suffix letters may follow one number. A float letter together with an integer letter (1fu) is DSH2105, and so is an integer letter on a literal with a fraction or an exponent (1.0u, 1e3l) or a float letter on a hexadecimal one.
  • The kind of a literal matters only to the compiler — see Integer and float. The graph gets a float Constant either way.

Integer and float

QuestionAnswer
Is 1 different from 1.0?To the compiler, yes: 1 is an int (since 2.0.0). In the graph, no: both are one Constant node holding 1.
Does 3u produce an integer?Yes, a uint (since 2.0.0).
Does int x = 7; produce an integer?Yes: x is an int variable (since 2.0.0). Its value in the graph is the float 7.
What makes a value an integer?An integer literal, an int / uint declaration, or an integer constructor.
What does the integer kind do?In a 1.x Graph, nothing you can see: 7 / 2 is 3.5, as in 1.x (2.0.0 – 2.1.0 refused it with DSH4243), and only int(7) / int(2) is refused. In a .dss the same 7 / 2 is DSH4243, so dsc migrate writes float(7) / 2. See Integer division.
Is there integer arithmetic or truncation?No. int x = 7.9; holds 7.9, and 7.0 / 2 is 3.5 in the material graph.

String literals

A string literal is tokenized with escapes decoded, and never evaluates to a value. It is legal only where an argument handler reads the literal text rather than evaluating it — a named UE.* / Substrate.* argument that sets a property of the node, an Output= / OutputName= output selector, or a Path(…) asset reference. Anywhere a value is wanted it is DSH4202.

EscapeProduces
\nline feed
\rcarriage return
\ttab
\""
\\\
\0nothing — the character is dropped
\<any other character>DSH2104 (since 2.0.0; 1.x dropped the backslash); the backslash is kept in the value

[!NOTE] A string never spans lines. One with no closing " before the end of its line is DSH2103 (since 2.0.0; 1.x read on to the end of the input), and the rest of the file is still read and reports its own errors.

Valid placement:

vec4 Scene = UE.SceneTexture(Id = "PostProcessInput0");

Invalid placement (anywhere a value is wanted):

float x = "0.5";   // DSH4202

Boolean literals

true and false (since 1.6.0) are read as literals while the line is parsed, in any case, before any name is looked up (since 2.0.0; 1.x resolved them after variables and properties).

Spellingmatched case-insensitively — true, True, TRUE, false, False, FALSE
Typebool, 1 component
Nodea Constant holding 1 or 0 (since 2.0.0; 1.x built a StaticBool)
Reuseequal constants are one node, so a graph has at most one per value
StaticBool Enabled = true;     // a bool variable
float      On      = TRUE;     // any case; a bool used as a number is 1

[!WARNING] Because true / false are read before any name, a Graph variable or a declared property named True or False, in any case, cannot be read: every use of the name is the literal. Avoid those names. See Name resolution.

Notes

  • Equal numeric literals are one Constant node across the whole graph: the dedupe pass compares values to 9 significant digits, so 0.5 written five times, or 1 and 1.0, is one node.
  • When every argument of a constructor is a constant, the constructor folds into one Constant2Vector / Constant3Vector / Constant4Vector node instead of Constant nodes plus AppendVector nodes — integer constructors included (since 2.0.0). See Constructors.
  • A literal is one component wide; no value carries a width other than its type's (since 2.0.0). See Conversions.
  • The literal rules here are those of Graph expressions. The declaration-level rules for Properties, Settings and metadata blocks are in Lexical elements.

Diagnostics

CodeRaised when
DSH2105A malformed number: a second ., an exponent without digits, a float and an integer suffix together, an integer suffix on a fraction, letters glued to the end.
DSH2222A hexadecimal literal in a 1.x Graph.
DSH4243/ between two integer constructor calls. Two integer literals are a float division.
DSH2103A string literal with no closing " on its line.
DSH2104An unknown escape in a string literal.
DSH4202A string literal where a value is wanted.
DSH4200An identifier that is no variable and no declaration.
DSH8214The emitter could not create the Constant node.

Example

Shader(Name="Docs/M_Literals", Root="Game")
{
    Properties { ScalarParameter K = 0.5; }

    Settings {
        Domain = "Surface";
        ShadingModel = "DefaultLit";
        BlendMode = "Opaque";
    }

    Outputs {
        float Rough;
        vec3 Color;
        Base.Roughness = Rough;
        Base.EmissiveColor = Color;
    }

    Graph {
        Rough = 0.55f * K;              // a float literal with its suffix
        float H     = .5;               // leading dot
        float Small = 1e-3;             // exponent
        float One   = 1;                // an int literal: the same Constant node as the 1.0 below
        Color = vec3(H * K, Small, 1.0) * One;
    }
}

Generated nodes:

ScalarParameter K
Constant(0.55), Multiply             -> Base.Roughness
Constant(0.5), Multiply              -> H * K
Constant(0.001)                      -> Small
Constant(1.0)                        -> One, and the third vec3 component: one node
AppendVector, AppendVector           -> vec3(H * K, Small, 1.0)
Multiply                             -> Base.EmissiveColor

See also

  • Expressions — operators, precedence and where a literal may appear
  • Constructors — constant folding of all-constant constructor calls
  • Conversions — how a 1-component literal widens to a vector target
  • Lexical elements — comments, identifiers and the declaration-level literal rules
  • Types — the full type-token catalogue
  • Name resolution — the lookup order, and why true cannot be shadowed
  • Node reuse — constant deduplication
  • Generic UE.Expression — the named string arguments a literal may fill

On this page