The feedback object represents a feedback frame buffer – an image, which can sample the previous iteration of itself or other feedback buffers. This is useful for simulating various progressively evolving phenomena.

By default, a feedback is an animated object, where one iteration takes place during each animation step, although this can be adjusted by update_rate. Alternatively, it can be combined with the image keyword. Then, a total step count must be set, and the entire process is run at once to produce a static final image. If you need to cycle data between two or more frame buffers, see feedback group.

Its syntax can be one of:

feedback <name> = <initializer>;
feedback <name> = <initializer> : <modifier1, modifier2, ...>;
feedback image <name> = <initializer> : <modifier1, modifier2, ...>;

The available modifiers and initializers are listed below.

The previous frame of every feedback object is accessible as a 2D texture sampler with the feedback buffer's name in all GLSL functions that follow it. Use the full_range modifier whenever the standard 32-bit color depth resolution is insufficient.


For feedback image only, you must specify:

  • update_count(<N>) – sets the total number of update steps.

Beside that, you can specify any subset of the following modifiers:

  • initialize(<function>) – specifies the function that computes the initial state of the buffer. It receives the position of the pixel between (0, 0) and (1, 1), and must return the value at that pixel as vec4.
    vec4 initializeFunction(vec2 position);
    Alternatively, a color value may be passed instead of a function, to fill the buffer with a uniform color.
  • update_rate(<updates per second>) – sets how often the buffer is updated. If unset, it will be updated every frame, which are synchronized with the monitor's refresh rate. Not applicable to feedback image.
  • filter(<filter mode>) – specifies the texture filtering mode. The possible values are:
    • none / nearest – nearest neighbor resampling / no filtering
    • linear – linear filtering, no mipmaps (default)
    • bilinear – linear filtering with discrete mipmap steps
    • trilinear – linear filtering with linear mipmap transitions
    • anisotropic / anisotropicN – anisotropic filtering (N×)
  • map(<X mapping>, <Y mapping>) – specifies the texture mapping / wrapping. You can also supply only one argument to be used for both dimensions. The possible values are:
    • clamp – clamps the texture coordinate to <0, 1>
    • repeat / wrap – repeats the texture outside its bounds (default)
    • mirror – repeats the texture but every other repetition is mirrored
    • clamp_to_border – uses a fixed border color out of bounds. The border color can be set as an additional argument (as a vec4 value)
  • hidden(<true / false>) – do not create a window for the feedback and only use it as an intermediate output
  • resizable(<true / false>) – make the window resizable and the feedback buffer dynamically adapt to its size
  • srgb(<true / false>) – changes the feedback buffer's color space to sRGB. Sampling an sRGB image will yield a color converted to the linear color space. Additionally, for generated images, the shader's output color must also be in the linear color space. Mixing sRGB and non-sRGB images will produce erroneous results unless handled carefully
  • full_range(<true / false>) – if enabled, the pixels will be stored in floating point format without clamping, allowing other shaders to sample the exact computed value at each pixel, but sacrificing some performance

Feedback group

Two or more feedback buffers can be aggregated into a feedback group (or feedback image group). Then, each update shader step shall be performed simultaneously for the entire group, and the previous state of any group member can be sampled by any group member. The syntax is:

feedback <name1, name2, ...> {
    <optional shader functions>
    <name1> = <initializer> : <modifier1, modifier2, ...>;
    <name2> = <initializer> : <modifier1, modifier2, ...>;
} : <group_modifier1, group_modifier2, ...>;

Between the declaration of the feedback buffers' names and the assignment of their initializers, the group block may contain functions, which may reference the member buffers by name.

Both the group itself and its individual members may be ammended by modifiers. The update_count / update_rate modifier can only be specified for the whole group. The initialize modifier can only be specified for individual members. All of the remaining modifiers can be specified for either. If a member has a modifier that is also set for the group, the value set for the individual member takes precedence.

glsl initializer

Initializes the feedback buffer with a GLSL update shader.

Its first argument is a GLSL function that will be evaluated at each pixel during the update. This function has up to three parameters, the first one being the sampler2D reference to the previous iteration of itself, the second one the vec2 position of the pixel between (0, 0) and (1, 1), and the third one is either the float time elapsed since the last update, in seconds, or in the case of a feedback image, the int step index. Its return value (vec4) will be stored in the buffer.

vec4 updateFunction(sampler2D self, vec2 position, float deltaTime);
vec4 updateFunction(sampler2D self, vec2 position, int stepNo);

The second argument specifies the dimensions of the buffer. You may as well pass the width and height separately as two arguments. Use sizeof(SomeImageOrAnimation) to make the buffer the same size as another object.


feedback MyFeedback = glsl(updateFunction, 256, 256) : initialize(initializeFunction), full_range(true);