Files
video-shader-toys/SHADER_CONTRACT.md
2026-05-02 19:46:48 +10:00

115 lines
2.6 KiB
Markdown

# Shader Package Contract
Each shader package lives under `shaders/<id>/` and includes:
- `shader.json`
- `shader.slang`
## Manifest fields
`shader.json` defines:
- `id`
- `name`
- `description`
- `category`
- `entryPoint`
- `parameters`
- optional `textures`
- optional `temporal`
Supported parameter types:
- `float`
- `vec2`
- `color`
- `bool`
- `enum`
## Texture assets
Shaders can optionally declare texture assets:
```json
{
"textures": [
{
"id": "logoTexture",
"path": "logo.png"
}
]
}
```
- `id` becomes a shader-visible sampler name
- `path` is resolved relative to the shader package directory
- texture asset changes trigger shader reload just like shader and manifest edits
## Temporal manifests
Shaders can optionally declare temporal history needs:
```json
{
"temporal": {
"enabled": true,
"historySource": "source",
"historyLength": 4
}
}
```
Supported temporal history sources:
- `source` - decoded source-video history from previous frames
- `preLayerInput` - history of the input arriving at that layer before the shader runs
`historyLength` is requested by the shader and clamped by `config/runtime-host.json` via `maxTemporalHistoryFrames`.
Temporal history resets automatically when:
- layers are added, removed, or reordered
- a layer bypass state changes
- a layer changes to a different shader
- a shader is reloaded or recompiled
## Slang contract
The runtime owns the fragment entry point, the UYVY-to-RGBA decode pass, and final mix/bypass behavior.
Your `shader.slang` file implements:
```slang
float4 shadeVideo(ShaderContext context)
{
return context.sourceColor;
}
```
Available built-ins through `ShaderContext`:
- `uv`
- `sourceColor` - the already-decoded full-resolution RGBA video color at `uv`
- `inputResolution`
- `outputResolution`
- `time`
- `frameCount`
- `mixAmount`
- `bypass`
- `sourceHistoryLength`
- `temporalHistoryLength`
Manifest parameters are exposed to the shader as globals named by their `id`.
Helper function:
- `sampleVideo(float2 uv)` returns decoded full-resolution RGBA video from the live DeckLink input.
- `sampleSourceHistory(int framesAgo, float2 uv)` samples the most recent available source history frame, clamping to the oldest available frame if needed.
- `sampleTemporalHistory(int framesAgo, float2 uv)` samples the most recent available pre-layer history frame for temporal shaders, clamping to the oldest available frame if needed.
Declared texture assets are exposed as `Sampler2D<float4>` globals using the texture `id`, for example:
```slang
float4 logo = logoTexture.Sample(uv);
```