The feedback section represents a feedback frame buffer – an image, which can sample the previous iteration of itself or other feedback buffers. This is useful for simulating some phenomena such as cellular automata or fluid dynamics.
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.
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 a range of 256 values between 0 and 1 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);
- 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.
- synchronize(<parent feedback>) – synchronizes the feedback buffer with another buffer, so that this one is updated immediately after the other. Cannot be used with feedback image or together with update_rate.
- filter(<filter mode>)
– specifies the texture filtering mode for GLSL.
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
- 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
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);