effects of a video, image, shape, frame or instance.
The loop
POST /v1/shaderswith the source and its params. The answer is201with the shader’sid, or422 shader_compile_errorwith every error’s line and column.POST /v1/shaders/{id}/proberenders one frame of it on a full-canvas shape (a PNG preview, not billed). Poll the job withGET /v1/renders/{id}.- Put it in a composition:
effects: [{"shader": {"id": "sh_...", "params": {...}}}]. - To change the source, post it again: a new source is a new shader with a new id.
Compile a shader
POST /v1/shaders
201
half4 main(float2 uv), with uv from (0, 0) at the top-left of the
element to (1, 1) at its bottom-right. A source that defines Jitter’s
half4 jitterMain(float2 uv) compiles in Jitter’s dialect (jitter: true); pass
"jitter": true to require it. Do not declare uniforms: everything a source reads comes
from the prelude below or from its params, each read as u_<name>.
hash is the SHA-256 of "sksl\n" plus the source, the shader’s identity. The variants’
text comes back with GET /v1/shaders/{id}?view=full, beside the source.
Compile errors
422
line and col are 1-based positions in your source. Line 0 marks an error outside
it: a param (param 'time': u_time is a prelude name) or a limit. A name the prelude
does not have is reported where it is first used (unknown prelude symbol 'u_amount').
The failed shader is stored too, so GET /v1/shaders/{id} keeps its errors; an effect
that names it is refused with shader_compile_error.
Use it in an effect
type or a shader, and beside a shader only
intensity (static or intensity_keyframes). A shape with fill: "none" and no stroke
is a generator: the shader paints the whole box from nothing. On any other element the
shader reads the element’s own pixels through sampleSource.
A param’s value is one of these or keyframes,
[{time, value}] in timeline seconds,
linear between and held outside. A param left out takes its declared default; a value
outside the declared min and max is refused, as are params the shader does not
declare (shader_param_invalid). The render carries the compiled variants, so it never
depends on the shader still existing once it is queued.
Limits
The prelude
Functions:
sampleSource(float2 uv) (the source, premultiplied), uvToLocal and
localToUv (uv into and out of the content box), transformUv(uv, aspect, pivot, translate, scale, angleRad), simplexNoise(float2 p, float2 res, float scale) (in -1
to 1) and Skia’s unpremul. Jitter’s dialect adds jitterSampleSource,
jitterUvToLocal, jitterLocalToUv, jitterTransformUv, jitterSimplexPerlinNoise,
u_width/u_height and u_source_width/u_source_height as aliases of the same.
GET /v1/capabilities serves all of this as the shaders section.
Shared shaders
GET /v1/shaders lists this workspace’s shaders and the shared ones (shared: true),
newest first. A shared shader works in any workspace’s effects and cannot be deleted
(403). Deleting your own shader leaves renders already queued with it untouched; a
document that still names it is refused with shader_not_found at its next render.
Availability
The compiler runs beside the API. A deployment without it answersPOST /v1/shaders with
503 shader_compiler_unavailable, and shaders.compiler_available in
GET /v1/capabilities is false. Rendering a shader needs the v5 render task: while a
deployment does not send it (shaders.renders is false), an effect with a shader is
refused with unsupported_feature.
