Pipeline Configuration - grondag/frex GitHub Wiki

Pipeline Configuration

Introduction

Pipeline options expose configuration values that are visible and settable by users in the renderer configuration, and also accessible in shaders and to control some aspects of pipeline operations.

Pipeline configuration options are created with the options keyword, which must label an array of option objects:

options: [
    // option objects go here
]

A pipeline .json (or .json5) file can only contain one options array, but a pipeline can include multiple files which also have an options array. Generally it is recommended to put options in the same file that defines the pipeline features that are being configured.

Option Objects

An option object has the following attributes:

  • includeToken: Symbol used to #include the option definitions in a shader. The renderer will automatically replace #include directives using this token with #define preprocessor directives based on the option definition and configured values. A namespace prefix, separated by a colon (:) is recommended to prevent naming conflicts.

  • categoryKey: Localization string that will be used to label this category of options in the renderer's pipeline configuration UI. The text associated with the string should be defined in .lang files that are part of the resource pack containing the pipeline.

  • elements: Object containing option elements, as defined in the next section.

options: [
    {
      includeToken: "my_pipeline:my_include_token",
      categoryKey: "config.my_pipeline.category.my_config_category",
      elements: {
        // elements go here
      }
    }
 ]

In a shader, the above example would be referenced with this line:

#include my_pipeline:my_include_token

Element Types

The JSON name of an element object, converted to upper case, acts as the #define token for the element value within shaders. The exception to this rule is Enum elements, as described below.

All elements types have two attributes in common:

  • nameKey: Localization string that will be used to label this option in the renderer's pipeline configuration UI. The text associated with the string should be defined in .lang files that are part of the resource pack containing the pipeline.

  • descriptionKey: Localization string that will be used to provide a tooltip for this option in the renderer's pipeline configuration UI. The text associated with the string should be defined in .lang files that are part of the resource pack containing the pipeline.

Boolean

If the element has a default attribute with a boolean value, the renderer will parse it as a boolean element. The default attribute, as the name implies, is the value that will be used if the player does not change it.

Boolean elements have no additional attributes.

options: [
    {
      includeToken: "my_pipeline:my_include_token",
      categoryKey: "config.my_pipeline.category.my_config_category",
      elements: {
        do_the_thing: {
          default: true,
          nameKey: "config.my_pipeline.name.do_the_thing",
          descriptionKey: "config.my_pipeline.help.do_the_thing"
        }
      }
    }
 ]

In a shader, the value of a boolean entry is tested by using ``#ifdef`:

#include my_pipeline:my_include_token

#ifdef DO_THE_THING
  // do the thing here
#endif

A boolean entry can also be referenced in a pass configuration to control if a pass runs. Do this by adding the toggleConfig attribute to a pass object. For example:

passes: [
			{
				name: "thing_pass",
				program: "thing_doer",
				framebuffer: "thing_buffer",
				samplerImages: ["thing_image"],
				// this pass will only run when this entry is set to true
				toggleConfig: "do_the_thing"
			}
    ]
}

Float

If the element has a default attribute with a floating point value, the renderer will parse it as a float element. The default attribute, as the name implies, is the value that will be used if the player does not change it.

Float elements have two additional attributes:

  • min: The lowest value (inclusive) the renderer will allow the user to set in the configuration UI. If the user configures a value less than this in a config file, it will be clamped to this minimum on game load.

  • max: The highest value (inclusive) the renderer will allow the user to set in the configuration UI. If the user configures a value less than this in a config file, it will be clamped to this minimum on game load.

options: [
    {
      includeToken: "my_pipeline:my_include_token",
      categoryKey: "config.my_pipeline.category.my_config_category",
      elements: {
        some_number: {
          default: 0.42,
          min: 0.0,
          max: 1.0,
          nameKey: "config.my_pipeline.name.some_number",
          descriptionKey: "config.my_pipeline.help.some_number"
        }
      }
    }
 ]

In a shader, the value of a float element is used by referencing the element name in upper case:

#include my_pipeline:my_include_token

float doSomething(float f) {
  f *= SOME_NUMBER;

  // etc, etc...
}

Integer

If the element has a default attribute with an integer value, the renderer will parse it as an integer element.

Aside from using an integer primitive type instead of float, integer elements are identical to float elements.

Enum

If the element has a choices attribute with an array of string values, the renderer will parse it as an enum entry. The default attribute, as the name implies, is the value that will be used if the player does not change it.

Enum elements have these additional attributes:

  • define: If present, acts as the #define token for the element value within shaders instead of the JSON name of the element object converted to upper case.

  • default: A string value that must be one of the values from the choices array. As the name implies, this is the value that will be used if the player does not change it.

  • enum: If present and the value is true, then the strings in the choices array (converted to upper case) will be defined in shaders as preprocessor constants with 0-based integer values corresponding to their position in the array. If not, present, or false, there will only be a single #define constant having the name of the value in upper case. The enum form is helpful when you have bitwise math, array lookups, or other logic that benefits from a numeric constant associated with each choice.

  • prefex: When present, pre-processor constants will have this prefix. Mostly useful for readability in glsl code - making clear that the constants are related.

options: [
    {
      includeToken: "my_pipeline:my_include_token",
      categoryKey: "config.my_pipeline.category.my_config_category",
      elements: {
        some_thing: {
          define: "THE_CURRENT_THING",
          default: "blue",
          choices: ["five", "blue", "france", "ham"],
          enum: true,
          prefix: "THING_",
          nameKey: "config.my_pipeline.name.some_thing",
          descriptionKey: "config.my_pipeline.help.some_thing"
        }
      }
    }
 ]

In a shader, #include my_pipeline:my_include_token would be replaced with:

#define THING_FIVE 0
#define THING_BLUE 1
#define THING_FRANCE 2
#define THING_HAM 3

#define THE_CURRENT_THING THING_BLUE