template

Shadron offers the possibility to define functions and generators as templates. Such declarations start with the template keyword and are very similar to C++ templates, with one major difference. Template arguments are not typed and are simply passed as text, similar to macros. For this reason, make sure to wrap template arguments in parentheses where necessary, and do not use variables that won't be accessible within the function or generator. Additionally, whenever a template function or generator is called, all of its template arguments must be specified explicitly.

Template structures are currently not supported.

Function template

A function template is defined just like a regular function, prefixed by the template keyword and a list of template argument names in angle brackets. These arguments can then be used throughout the function header and body. For each invocation, a new instance of the function is generated, with template argument placeholders replaced by their values.

Example of template function definition:

template <IMAGE_NAME>
vec4 sampleImage(vec2 pos) {
    return texture(IMAGE_NAME, pos);
}

Example of usage in another function:

vec4 sampleMyImage(vec2 pos) {
    return sampleImage<MyImage>(pos);
}

Example of referencing the function in a Shadron object initializer:

image MyImageCopy = glsl(sampleImage<MyImage>, sizeof(MyImage));

Generator template

Generators may also be defined as templates in exactly the same way. Additionally, template generators do not need to have their vertex data type specified – a question mark symbol can be used in its place. The type will then be deduced based on where it is called. However, if the vertex type is omitted, the generator cannot output any vertex data directly.

Example of template generator definition:

template <INNER_GENERATOR, T>
generator ? mirror(vec3 coord, T data) {
    INNER_GENERATOR(+coord, +1.0, data);
    INNER_GENERATOR(-coord, -1.0, data);
}

Example of usage in another generator:

generator Vertex fullModel(ModelData data) {
    mirror<halfModel, ModelData>(vec3(-1.0, 0.0, 0.0), data);
}