# Custom Shaders

### Writing a Custom Shader

With valora, you can shade each path with its own shader, and define custom uniforms. We'll start with this simple GLSL fragment shader:

```c
#version 400

uniform vec3 color;
uniform float scale;
uniform float height;
uniform float width;

out vec4 frag;

void main() {
  vec2 pos = gl_FragCoord.xy / scale;

  vec3 white = vec3(1., 1., 1.);

  frag = vec4(mix(white, color, pos.x / width), 1.);
}
```

Save this to a file named `pattern.frag`.

Now, we'll use valora's shader API to define some uniforms and load the shader. A shader in valora is made of two parts:

1. The shader program. This is the GLSL above, which exposes an interface to provide uniforms.
2. The uniforms bound to the shader.

First let's define the uniforms type in Rust:

```rust
#[derive(UniformSet, Copy, Clone, Debug)]
struct Uniforms {
    /// A solid color overlay on the shader pattern.
    color: (f32, f32, f32),
    /// The vector scale of the output.
    scale: f32,
    /// Width of the output.
    width: f32,
    /// Height of the output.
    height: f32,
}
```

The derive macro `UniformSet` will generate mappings from the field types to something we can send to the GPU, should such a mapping exist for the type.

Now let's load the shader and draw with it:

```rust
fn main() -> Result<()> {
    run_fn(Options::from_args(), |gpu, world, _rng| {
        let mut program = ShaderProgram::new(&gpu, "pattern.frag")?;
        let uniforms = Uniforms {
            color: Hsv::new(0., 0.7, 0.7).into_rgb::<Srgb>().into_components(),
            scale: world.scale,
            width: world.width,
            height: world.height,
        };
        let shader = program.bind(uniforms);

        Ok(move |ctx: Context, canvas: &mut Canvas| {
            canvas.set_color(LinSrgb::new(1., 1., 1.));
            canvas.paint(Filled(ctx.world));

            canvas.set_shader(shader.clone());
            let square = Ngon::square(world.center(), 200.);

            canvas.paint(Filled(square));
        })
    })
}
```

If you run the painting with `cargo run --release`, and change the GLSL, you'll notice that the view pane will update live!

![A path rendered with a custom shader.](https://1276503419-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lw1VWDRh9_wPSAWr8kv%2F-LwHC341cabnLiGN_PTm%2F-LwHCDwn1lBLQw75vLg9%2F1.gif?alt=media\&token=1cd34e41-faa7-4963-b2a4-2993fb7023ab)

### Updating Uniforms

We can update our uniform values each frame. Once the uniforms are updated, we can rebind with the shader program to make a new shader.

```rust
let hue = ctx.time.as_secs_f32().sin().abs() * 40.;
uniforms.color = Hsv::new(hue, 0.7, 0.7).into_rgb::<Srgb>().into_components();
canvas.set_shader(program.bind(uniforms));
```

![](https://1276503419-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lw1VWDRh9_wPSAWr8kv%2F-LwHCdvZysxrIjgFwqYo%2F-LwHD3FHP3zdCNyBd5IP%2Fanim.gif?alt=media\&token=8343db8d-5c23-4ba4-bf3d-95d88fe92b6a)
