Link Search Menu Expand Document

ISF language reference

This is the canonical shader contract for the ISF Shaders process. For GLSL syntax, generated declarations and portability, see GLSL runtime reference. For worked tasks, see Shader cookbook.

Standard ISF and score extensions

Interactive Shader Format combines GLSL with a JSON description. The upstream JSON reference and GLSL reference define the portable ISF interface; the tables below describe score’s runtime, including extensions.

The standard input vocabulary is event, bool, long, float, point2D, color, image, audio, and audioFFT. Standard multipass declarations include TARGET, PERSISTENT, FLOAT, WIDTH, and HEIGHT. Standard shader variables include TIME, TIMEDELTA, DATE, FRAMEINDEX, PASSINDEX, RENDERSIZE, and isf_FragNormCoord; the pixel/normalized image sampling helpers are part of ISF.

Do not assume another ISF host supports score’s point3D, audioHist, cubemaps, volume inputs, depth companions, explicit sampler-state fields, OUTPUTS, ALPHA, COMPOSITE, or the additional pass fields LAYER, Z, FORMAT, and PIPELINE_STATE. Likewise, PROGRESS, SAMPLERATE, isf_FragCoord, clipSpaceCorrMatrix, MSAA_SAMPLES, IMG_TEXEL, TEX_DIMENSIONS, and IMG_CUBE are score runtime conveniences rather than a portable ISF baseline. MODE selects score shader families; CSF, raw raster, and VSA integration are not standard ISF rendering modes.

Header names become generated shader declarations. Use valid, distinct GLSL identifiers and do not redeclare generated uniforms, samplers or outputs in the body. Compatibility acceptance of gl_FragColor is score preprocessing, not Vulkan GLSL syntax.

JSON header

Every shader starts with a JSON block enclosed in /*{ ... }*/.

/*{
  "ISFVSN": "2",
  "DESCRIPTION": "Brightness filter",
  "CATEGORIES": ["Color", "Filter"],
  "INPUTS": [
    { "NAME": "inputImage", "TYPE": "image" },
    { "NAME": "brightness", "TYPE": "float", "DEFAULT": 1.0, "MIN": 0.0, "MAX": 2.0 }
  ]
}*/

Common fields

Field Description
ISFVSN ISF version. Use "2".
DESCRIPTION Description shown in browsers and inspectors.
CREDIT Author credit.
CATEGORIES Library categories.
INPUTS UI controls, texture inputs, audio textures, buffers, and uniforms.
PASSES Multipass render plan.
OUTPUTS Explicit output textures: multiple color outputs, depth, layers, cubemaps, formats, MSAA.
ALPHA Output alpha convention: "straight" or "premultiplied".
COMPOSITE Default composition mode: "over", "add", "multiply", "screen", "replace".
EXTENSIONS GLSL extensions to require.

If MODE is omitted, the file is treated as an ISF shader. MODE is reserved for other shader families such as CSF and raw raster.

Scalar input types

Scalar inputs create UI controls and uniforms with the same name.

ISF type GLSL type Typical fields
float float DEFAULT, MIN, MAX
bool bool DEFAULT
event bool for one frame none
long int VALUES, LABELS, DEFAULT
point2D vec2 DEFAULT, MIN, MAX
point3D vec3 DEFAULT, MIN, MAX
color vec4 DEFAULT, MIN, MAX

An event input fires for one rendered frame on true or an ossia impulse. Connect a trigger/message cable to it when an effect needs a reset or one-shot action; unlike a bool, it is not a latched switch.

Example:

"INPUTS": [
  { "NAME": "gain", "TYPE": "float", "DEFAULT": 1.0, "MIN": 0.0, "MAX": 4.0 },
  { "NAME": "mode", "TYPE": "long", "VALUES": [0, 1], "LABELS": ["Normal", "Invert"], "DEFAULT": 0 },
  { "NAME": "tint", "TYPE": "color", "DEFAULT": [1, 0.8, 0.4, 1] }
]

Texture inputs

2D image

{ "NAME": "inputImage", "TYPE": "image" }

Use the ISF sampling macros:

vec4 c = IMG_THIS_NORM_PIXEL(inputImage);

3D image / volume

{ "NAME": "volume", "TYPE": "image", "DIMENSIONS": 3 }

3D inputs are GLSL sampler3D values. Sample them with texture(volume, vec3(u, v, w)).

Cubemap

{ "NAME": "environment", "TYPE": "cubemap" }

Cubemaps are GLSL samplerCube values. Sample with texture(environment, dir) or IMG_CUBE(environment, dir).

Sampleable depth

For inputs that carry a depth companion, set DEPTH: true. This exposes a depth sampler next to the color sampler where the upstream producer provides one.

Sampler state

Texture inputs can declare sampler state directly on the input object:

{
  "NAME": "tex",
  "TYPE": "image",
  "FILTER": "nearest",
  "WRAP": "clamp_to_edge",
  "MIPMAP_MODE": "linear",
  "ANISOTROPY": 8.0
}

Supported fields include WRAP, WRAP_S, WRAP_T, WRAP_R, FILTER, MIN_FILTER, MAG_FILTER, MIPMAP_MODE, BORDER_COLOR, COMPARE, ANISOTROPY, LOD_BIAS, MIN_LOD, and MAX_LOD.

Audio inputs only use FILTER and WRAP.

Audio textures

ISF audio inputs create GPU textures from audio data:

{ "NAME": "wave", "TYPE": "audio", "MAX": 512, "FILTER": "nearest" }
{ "NAME": "fft", "TYPE": "audioFFT", "MAX": 512 }
{ "NAME": "hist", "TYPE": "audioHist", "MAX": 512 }

Use FILTER: "nearest" when FFT bin accuracy matters.

Texture macros

Use the helpers instead of raw gl_FragCoord coordinate math. They keep orientation correct across OpenGL, Vulkan, Metal, and Direct3D.

Macro Description
IMG_PIXEL(tex, coord) Sample at pixel coordinate.
IMG_NORM_PIXEL(tex, coord) Sample at normalized [0, 1] coordinate.
IMG_THIS_PIXEL(tex) Sample at this fragment’s pixel coordinate.
IMG_THIS_NORM_PIXEL(tex) Sample at this fragment’s normalized coordinate.
IMG_TEXEL(tex, coord) Texel fetch at integer coordinate.
IMG_SIZE(tex) / TEX_DIMENSIONS(tex) Texture size in pixels.
IMG_CUBE(tex, dir) Cubemap sample.

Textures coming from other nodes’ render targets are premultiplied. There is no straight-alpha sampling macro: when a source must be unpremultiplied before color math, sample it normally and divide by alpha yourself:

vec4 c = IMG_NORM_PIXEL(inputImage, isf_FragNormCoord);
if (c.a > 0.0) c.rgb /= c.a;

Built-in uniforms

Uniform Type Description
TIME float Playback time in seconds.
TIMEDELTA float Time since previous frame.
PROGRESS float Timeline progress from 0 to 1.
FRAMEINDEX int Frame counter.
PASSINDEX int Current pass index.
RENDERSIZE vec2 Current render target size.
DATE vec4 (year, month, day, seconds).
SAMPLERATE float Audio sample rate.
isf_FragNormCoord vec2 Current normalized fragment coordinate.
isf_FragCoord vec4 Platform-corrected fragment coordinate.
clipSpaceCorrMatrix mat4 Clip-space correction matrix for custom vertex shaders.
MSAA_SAMPLES int Active sample count when MSAA is enabled.

Outputs

Without an OUTPUTS array, an ISF shader writes one color output named isf_FragColor.

void main() {
    isf_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

gl_FragColor is accepted for compatibility and rewritten to isf_FragColor.

Multiple render targets

"OUTPUTS": [
  { "NAME": "color", "TYPE": "color" },
  { "NAME": "luma", "TYPE": "color", "FORMAT": "r16f" },
  { "NAME": "depth", "TYPE": "depth", "FORMAT": "d32f" }
]

Color outputs become layout(location = N) out vec4 name;. A depth output is written through gl_FragDepth.

Output fields

Field Description
NAME Output name.
TYPE "color" or "depth". Defaults to "color".
FORMAT Texture format such as rgba8, rgba16f, rgba32f, r32f, d32f.
WIDTH, HEIGHT Fixed size or expression.
LAYERS Texture array layer count.
DEPTH 3D texture depth.
CUBEMAP Allocate as cubemap.
GENERATE_MIPS Generate mipmaps after rendering.
SAMPLES MSAA sample count.
ALPHA Per-output alpha convention.
COMPOSITE Per-output compositing mode.

All color outputs in one pass share the render target size. Cubemap outputs are square.

Multipass rendering

PASSES defines intermediate passes and feedback buffers.

"PASSES": [
  { "TARGET": "feedback", "PERSISTENT": true, "FLOAT": true },
  {}
]
Pass field Description
TARGET Intermediate output to render. Missing target means final output.
PERSISTENT Preserve the target across frames.
FLOAT Use floating-point storage.
FILTER "NEAREST" for nearest sampling.
WIDTH, HEIGHT Fixed size or expression.
LAYER Render into a texture-array layer.
Z Render into a 3D texture slice.
FORMAT Per-pass intermediate format.
PIPELINE_STATE Per-pass raster state override.

ISF v1 PERSISTENT_BUFFERS are converted to persistent passes internally. The legacy field accepts an array of target names or an object mapping names to WIDTH, HEIGHT and FLOAT settings. Each name must match a pass’s TARGET; an unmatched name is ignored with a diagnostic. Prefer PERSISTENT: true on the pass in new shaders.

The last pass normally renders to the process output. Use PASSINDEX to branch between pass code paths.

Size expressions

WIDTH, HEIGHT, and related size fields accept numbers or expressions:

{ "TARGET": "half", "WIDTH": "$WIDTH / 2", "HEIGHT": "$HEIGHT / 2" }

Available variables include $WIDTH, $HEIGHT, $inputName for scalar controls, and $WIDTH_inputImage / $HEIGHT_inputImage for input texture sizes. Expressions support standard arithmetic and common functions such as min, max, sqrt, ceil, floor, pow, sin, and cos.

The texture inlet inspector also provides an explicit size checkbox with width and height controls. Uncheck it for Auto sizing; this is distinct from allocating a fixed-size target in the shader header. The Show shader previews toolbar action controls library and inspector previews. See Graphics pipeline for sizing and backend limits, and Shader cookbook for feedback, MRT and sampler recipes.

Alpha and compositing

Declare the alpha convention your shader writes:

{
  "ALPHA": "straight",
  "COMPOSITE": "over"
}
  • ALPHA: "straight" or "premultiplied".
  • COMPOSITE: "over", "add", "multiply", "screen", or "replace".

This is especially important when mixing shader outputs with text, videos, transparent 3D renders, or layered raw raster passes.

Examples

Simple color filter

/*{
  "DESCRIPTION": "Simple brightness/contrast adjustment",
  "ISFVSN": "2",
  "INPUTS": [
    { "NAME": "inputImage", "TYPE": "image" },
    { "NAME": "brightness", "TYPE": "float", "DEFAULT": 1.0, "MIN": 0.0, "MAX": 3.0 },
    { "NAME": "contrast", "TYPE": "float", "DEFAULT": 1.0, "MIN": 0.0, "MAX": 3.0 }
  ]
}*/

void main() {
    vec4 color = IMG_THIS_NORM_PIXEL(inputImage);
    color.rgb = (color.rgb - 0.5) * contrast + 0.5;
    color.rgb *= brightness;
    isf_FragColor = color;
}

Generator

/*{
  "DESCRIPTION": "Animated circle generator",
  "ISFVSN": "2",
  "INPUTS": [
    { "NAME": "radius", "TYPE": "float", "DEFAULT": 0.3, "MIN": 0.01, "MAX": 1.0 },
    { "NAME": "color", "TYPE": "color", "DEFAULT": [1, 0.5, 0, 1] }
  ]
}*/

void main() {
    vec2 uv = isf_FragNormCoord - 0.5;
    float d = length(uv);
    float circle = 1.0 - smoothstep(radius - 0.01, radius, d + sin(TIME * 3.0) * 0.05);
    isf_FragColor = mix(vec4(0), color, circle);
}

Feedback trail

/*{
  "DESCRIPTION": "Feedback trail effect",
  "ISFVSN": "2",
  "INPUTS": [
    { "NAME": "inputImage", "TYPE": "image" },
    { "NAME": "decay", "TYPE": "float", "DEFAULT": 0.95, "MIN": 0.0, "MAX": 1.0 }
  ],
  "PASSES": [
    { "TARGET": "feedback", "PERSISTENT": true },
    {}
  ]
}*/

void main() {
    if (PASSINDEX == 0) {
        vec4 prev = IMG_THIS_NORM_PIXEL(feedback);
        vec4 curr = IMG_THIS_NORM_PIXEL(inputImage);
        isf_FragColor = max(curr, prev * decay);
    } else {
        isf_FragColor = IMG_THIS_NORM_PIXEL(feedback);
    }
}

MRT output

/*{
  "DESCRIPTION": "Color and luminance outputs",
  "ISFVSN": "2",
  "INPUTS": [
    { "NAME": "inputImage", "TYPE": "image" }
  ],
  "OUTPUTS": [
    { "NAME": "color", "TYPE": "color" },
    { "NAME": "luminance", "TYPE": "color", "FORMAT": "r16f" }
  ]
}*/

void main() {
    vec4 c = IMG_THIS_NORM_PIXEL(inputImage);
    color = c;
    float lum = dot(c.rgb, vec3(0.2126, 0.7152, 0.0722));
    luminance = vec4(vec3(lum), 1.0);
}