> For the complete documentation index, see [llms.txt](https://docs.nursultan.fun/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nursultan.fun/interface/shaders.md).

# Shaders

A shader is a small program that works out the colour of every pixel. It is what you reach for when shapes and images cannot give you the effect: waves, glows, noise, gradients driven by a formula.

## Compiling one

Write it once, at the top level of the script:

```kotlin
val glow = shader("glow", """
    #version 150

    uniform vec2 uSize;
    uniform float uTime;

    in vec2 texCoord;
    out vec4 fragColor;

    void main() {
        vec2 uv = gl_FragCoord.xy / uSize;
        float pulse = 0.5 + 0.5 * sin(uTime * 2.0);
        fragColor = vec4(0.35, 0.78, 1.0, pulse * 0.6);
    }
""")
```

The first argument is a name, which is how the shader shows up in logs. The second is the fragment shader source in GLSL.

## Checking it built

Compilation can fail, and you want to notice right away:

```kotlin
if (!glow.ready()) {
    log.error("shader did not build: " + glow.error())
}
```

## Drawing with it

```kotlin
on<Render2DEvent> { e ->
    glow.set("uSize", e.width(), e.height())
    glow.set("uTime", client.millis() / 1000f)
    e.render().shader(glow, 8f, 8f, 160f, 40f)
}
```

`shader(...)` draws a rectangle filled by your shader.

## Passing values in

```kotlin
glow.set("uAlpha", 0.5f)
glow.set("uSize", width, height)
glow.set("uColor", 0.35f, 0.78f, 1.0f)
glow.set("uRect", x, y, w, h)
glow.set("uSteps", 8)
```

The name has to match a `uniform` in the source. Values are set before drawing, in the same frame.

## Things to keep in mind

* The shader compiles once when the script loads, not per frame — never call `shader(...)` inside a render handler.
* Only the fragment shader is yours; the vertex one is the standard one.
* A compile error takes down neither the client nor the script — nothing simply draws, and the reason is in `error()`.
* Everything a shader draws is visible to you only.

## When you do not need one

Backdrop blur already exists — `render.blur(...)`, no shader needed. A two-colour gradient is `render.gradient(...)`. A shader is worth it when the effect really is computed per pixel.
