-
Notifications
You must be signed in to change notification settings - Fork 37
Pipeline Dynamic Properties
Since https://github.com/vram-guild/canvas/pull/389, pipeline configuration can now have dynamic properties that are based on user configuration!
Dynamic properties are values that are resolved when compiling the pipeline, based on user configuration. Dynamic properties can be applied to any part of the pipeline configuration of certain types, in particular: Integers, Floats, Booleans, Strings (names, resource locations, and GL enums), as well as framebuffer attachments.
Replace a constant value with a dynamic property object. There are two types of dynamic property objects: single option source and option map. Take a look at the following example.
sky: {
defaultZenithAngle: 15
},Using dynamic properties, we can change these config on the fly based on user choices:
sky: {
// single option source
// default is used when the named option can't be found or is incompatible
defaultZenithAngle: { default: 15, option: "sky_zenith_angle" }
},The name of the option being used for its value is referenced using the option field of the dynamic property object. The value of default field is used when the referenced option can't be found or when the referenced option has incompatible type.
In a more advanced example, option map can be used to switch between different samplers. The following is possible:
fabulous: {
passes: [
{
name: "color",
program: "color",
framebuffer: "color",
samplerImages: [
"gbuffer",
"minecraft:textures/environment/sun.png",
{
// default choice
default: "minecraft:textures/environment/moon_phases.png",
optionMap: {
// mapping an enum option `moon_texture` to texture location
moon_texture: [
{ from: "hd", to: "example_pipeline:textures/environment/moon_phases_hd.png" },
{ from: "toon", to: "example_pipeline:textures/environment/moon_phases_toon.png" }
]
}
}
]
},
]
}In case of option maps, the value of the referenced option are compared against a map in order to resolve the final value. Multiple options can be used in a single map. If the map couldn't resolve any value, the default value is used.
Note that defining a default in either cases is optional, but it's recommended to do so as a safety precaution. If a value resolution failed but no default value is defined, the pipeline might fail to compile in the worst case scenario.
{
default: <default_value>,
option: "<option_reference>"
}{
default: <default_value>,
optionMap: {
<option_reference_a>: [
{
from: <condition_a1>,
to: <result_a1>
},
{
from: <condition_a2>,
to: <result_a2>
},
// <...>
],
<OPTIONAL_option_reference_b>: [
{
from: <condition_b1>,
to: <result_b1>
},
{
from: <condition_b2>,
to: <result_b2>
},
// <...>
],
<OPTIONAL_option_reference_c>: [
{
from: <condition_c1>,
to: <result_c1>
},
{
from: <condition_c2>,
to: <result_c2>
},
// <...>
],
// <...>
}
}Both single option source and option map can't be used at the same time. If both are present, the result is undefined.
Primitives:
- Int
- Float
- Boolean
- String types:
- Named configuration reference (framebuffers, images, programs, and so on)
- Resource location (shader and texture locations)
- Sampler uniform names
- GL Enums
Special types:
- Framebuffer attachment objects
- Int
- Float
- Boolean
- Enum (value is treated as String)
Despite enum options being treated as String, it is recommended to map their values instead of using them directly. This is because enum types are technically case-sensitive, but they are always presented as ALL CAPS in the GUI and shader result. Therefore using an enum option value directly may result in undefined or inconsistent behavior.
This rule does not apply to GL Enum types as GL Enum are converted to ALL CAPS during lookup.
Framebuffer attachment objects' properties are typically inseparable. For example, an image with LOD is always tied to its LOD, and an array image is always tied to a specific layer. For this purpose, it is possible to map an option directly into whole framebuffer attachment objects. Take a look at the following example where an array texture is used in place of normal texture when certain option is enabled:
Example C: Selecting framebuffer attachment using a map
{
name: "solid",
depthAttachment: {image: "vanilla_depth", clearDepth: 1.0},
colorAttachments: [
{image: "vanilla_color", clearColor: 0x00000000},
{
default: {image: "gbuffer_solid_light", clearColor: 0x00000000},
optionMap: {
render_reflection: [
{ from: true, to: {image: "gbuffer_lightnormal", layer: 0, clearColor: 0x00000000}}
]
}
}
]
}The following properties are supported:
- All top level pipeline configuration properties
- Draw targets properties
- Image properties
- Material program properties
- Framebuffer properties
- Framebuffer attachment object within the
colorAttachmentsarray - Individual framebuffer attachment properties
- Framebuffer attachment object within the
- Pass properties
- Sampler images within the
samplerImagesarray
- Sampler images within the
- Sky properties
- Sky shadow properties
The following properties are NOT supported:
- Option properties
- Dynamic properties within dynamic properties
- Json file inclusions (
includearrays)
Older version of Canvas before dynamic properties can't understand pipelines that use dynamic properties. For pipeline developers: please inform the users of your pipeline to use the correct version of Canvas.