Definition records
The keys of a parameter, choice parameters and data tables
Every shape, operator and modifier in Construct is a definition record: one
YAML text with metadata, a list of parameters, and a shaderCode: block
that holds one GLSL function. This page lists the keys that place a record
in the Things finder, the keys of a parameter, and the two keys that turn a
definition into a collection: the choice (options:) and the table of
numbers (data:).
To change a record, see Edit an SDF definition.
Record keys for lists and families
| Key | Meaning |
|---|---|
summary |
One sentence of at most 80 characters. The finder's rows and tiles show it. Required |
description |
The long text. The definition editor and the finder's preview show it |
family |
The place in the family tree, a path such as polyhedra/platonic or lattice/tpms. Use custom for a shape that fits no family. Required |
audience |
engineering, mathematical or organic. engineering when absent. The finder folds a mathematical collection until you open it |
The family tree is the file sdf/families.yaml, beside the records. A family
that the tree does not have is a validation error, and so is a summary that
is missing, longer than 80 characters or longer than one line.
Calling shared GLSL with uses:
A record can call helper functions from library records: GLSL that many
records share, such as the noise functions. Name the libraries in uses::
uses:
- lib_hash
- lib_noise
Construct puts each library's code before the record, once, after the
libraries it uses in turn. A library is a record in the family library. It
has no shape of its own, so the Things finder does not list it.
Parameter keys
Each item of parameters: describes one parameter of the GLSL function. The
function's signature decides which parameters exist, and name links an
item to one of them.
| Key | Meaning |
|---|---|
name |
The name in the GLSL signature |
displayName, description, unit, section |
What the user reads |
type, uiHint |
The value type and its control |
defaultValue, minValue, maxValue |
The value and its range |
stepValue |
The step of the control, for example 1 for a whole-number slider |
drag |
How a drag maps to the value |
gizmo |
The handle of the parameter in the viewport |
options |
The labels of a choice. On an Int only |
Choice parameters
An Int parameter with an options: list is a choice.
- name: solid
displayName: Solid
type: Int
defaultValue: 0
options: [Cube, Octahedron, Tetrahedron]
| Rule | Detail |
|---|---|
| Value | The position of a label, from 0 |
| Range | 0 to the label count minus 1. minValue and maxValue are not needed |
| Out of range | A value past the last label is the last label. A negative value is the first |
| Control | A drop-down list, in the definition editor and in the scene tree |
| In the shader | A number. Declare the parameter float and convert it with int() |
| Validation | options: on a type other than Int is an error. So is an empty label |
A choice picks numbers, not code. Keep the shader free of a switch or an
if chain over the labels: the compiled shader of a scene then stays the
same size whatever the number of labels.
Data tables
A data: block holds named, read-only tables of numbers. Each key is the
name of a table, and each table has one of three shapes.
| Shape | YAML | The shader reads |
|---|---|---|
| Flat | weights: [1.0, 0.5] |
The same list for every label |
| By a choice | planes: {by: solid, values: [...]}, with one list per label of solid, in label order |
The list of the chosen label |
| By number | planes: {values: [[...], [...]]}, a list of lists and no by: |
The list that the code selects by number. A definition that Condense seals writes its tables in this shape, because the choices of the parts are not its parameters |
A table by a choice, written in block form:
data:
planes:
by: solid
values:
- [1, 0, 0, -0.29, -1, 0, 0, -0.29]
- [0.58, 0.58, 0.58, -0.17, 0.58, -0.58, -0.58, -0.17]
- [0, 1, 0, -0.5, 0, -1, 0, -0.5]
Write each list on one line. The lists can have different lengths.
Reading a table in GLSL
In the shader code, the name of a table is an int constant. Three
functions read the tables:
| Function | Returns |
|---|---|
ivec2 defDataSlice(int table, int variant) |
The list that variant selects, as (start, length in numbers). A flat table gives its one list for every variant. A variant past the last list gives the last list |
float defData(ivec2 list, int i) |
Number i of the list, or 0 outside it |
vec4 defData4(ivec2 list, int i) |
Numbers 4i to 4i+3 of the list, for example one plane, or 0 outside it |
float sdf_example(vec3 p,
float solid,
float size)
{
ivec2 faces = defDataSlice(planes, int(solid));
float d = -1.0e20;
for (int i = 0; i < faces.y / 4; ++i) {
d = max(d, dot(vec4(p / size, 1.0), defData4(faces, i)));
}
return d * size;
}
Rules
| Rule | Detail |
|---|---|
| Names | A table name is a GLSL identifier, and no parameter has the same name |
by: |
Names a choice parameter. values has one list per label |
| Entries | Every entry is a number |
| Kinds | Primitives, fields, transforms and modifiers can read tables. A CSG operator cannot |
| Cost | The tables travel to the graphics card as one buffer, not as code. A changed number, a longer list or a new label with its list compiles nothing |
The numbers are part of the definition's fingerprint, so its thumbnail follows an edited table.
The mesh export, the bounds, the picking and the other evaluators that run on the processor read the same tables as the viewport. A definition that Condense seals carries the tables of its parts.