Developer documentation
Shaders
Each pass is a fragment shader in GLSL ES 3.00. It runs once for every pixel of the layer, reads what it needs, and writes one color.
What every pass gets#
What every effect pass's fragment shader is given, besides the uniforms its manifest sets. A pass draws once over the whole layer, one fragment per pixel, and writes its color to its one out vec4 (any name). Reads outside the layer come back transparent, or wrap around when the layer's effects are set to Tileable (Wrap Edges).
vTexCoordin vec2: where this pixel is, 0 to 1 across the layer and down it, (0, 0) at the top left. Set by the vertex shader every pass shares.uInputTexsampler2D: what this pass works on. The first pass gets the layer (as the effects before this one left it); each pass after that gets the one before's output.uSourceTexsampler2D: the layer as this effect got it, in every pass. Later passes use it to combine their work with the original, the way a glow adds a blur back onto the sharp layer.uTexelSizevec2: one pixel's size in texture coordinates, (1 / width, 1 / height). Add it tovTexCoordto read a neighbor.uResolutionvec2: the layer's size in pixels, (width, height).
A minimal pass, which changes nothing:
#version 300 es
precision mediump float;
in vec2 vTexCoord;
uniform sampler2D uInputTex;
out vec4 FragColor;
void main() {
FragColor = texture(uInputTex, vTexCoord);
}To read the pixel to the right, add one pixel's width: texture(uInputTex, vTexCoord + vec2(uTexelSize.x, 0.0)).
Settings in a shader#
A pass's uniforms hand it the effect's settings: "uColor": "$color" sets the uniform uColor from the setting color. What the shader gets depends on the setting's type:
intA whole number, in a number field. The shader gets an
int. Can be animated.floatA number with decimals, in a number field. The shader gets a
float. Can be animated.boolOn or off, a check box. The shader gets an
int(or abool): 1 or 0. Can be animated.colorA color, from a swatch that opens a color picker. The shader gets a
vec4: red, green, blue and alpha, 0 to 1.vec2Two numbers, X and Y, side by side. The shader gets a
vec2.enumOne of the setting's
options, from a dropdown. The shader gets anint: the option's index, from 0.gradientA gradient, in a gradient editor. The shader gets a
sampler2D: 256 × 1 pixels, the gradient from left to right. Read it withtexture(uGradient, vec2(t, 0.5)).paletteA list of colors, chosen from the document's palette or a saved one. The shader gets a
sampler2D(the colors in a row, one pixel each, up to 256) and anintuniform named the same with "Count" on the end:uPaletteanduPaletteCount.
How the output joins the layer#
replaceThe effect's output becomes the layer's new look, and the next effect works on it. The default.
behindThe effect's output is drawn behind the layer, for shadows and glows. The next effect works on the layer as it was before this one.
Several passes#
Passes run in order, each reading the one before through uInputTex, while uSourceTex stays the layer as the effect got it. Gaussian Blur is two passes, across and then down. Bloom picks out the bright pixels, blurs them, and in its last pass adds them back onto the sharp layer from uSourceTex. Both are among the built-in effects.