## Intro

SkSL ("Skia Shading Language") is a variant of GLSL which is used as Skia's internal shading language. With some minor modifications, GLSL code from sites like [https://www.shadertoy.com/](https://www.shadertoy.com/) can be converted for use in Cavalry.

For more detail on the differences between GLSL and SkSL see the [Skia documentation](https://github.com/google/skia/blob/main/src/sksl/README.md).

:::caution Integer Uniforms

The SkSL Shader does not accept integer uniforms, please use floats instead.

:::

## UI

**Blend Mode** - See [Blend Modes](/content/docs/nodes/general/blend-modes/index.html).

**Shader Code** - Paste/edit SkSL code here.

**Inputs** - Click the `+` button to choose a uniform type and add one. Uniforms can be renamed by right clicking on an attribute and choosing **Rename...**. This name can then be used as a variable in the **SkSL Code**.

To sample an input shader use `inputShader.eval(p)` where `inputShader` is the name of the uniform and `p` is the coordinate to be sampled.

### Export to Plugin

Click `Export to Plugin...` to load an export window which can be used to export the Layer as a [Plugin](/content/docs/tech-info/third-party-plugins/index.html).

**Author** - Set the string to populate the `"author"` key in `definitions.json`. This field will be remembered between sessions.

**Plugin Name** - Set the string to populates the `"niceName"` key in `strings.json`

**Encrypt** - When checked, the exported files will be encrypted.

**Export...** - Click `Export` to choose a location to export the files to. The **Author** and **Plugin Name** fields are required.

Notes

Note that it's likely some adjustments to the exported files will be required. For example, icons, tooltips etc may need to be added.

### Built in Uniforms

Built in Uniforms can be added to the **Shader Code**:

- `resolution` - the size of the Shape being rendered which can be used to produce Shaders that scale to their contents. See the example in `Create > Demo Scenes > Custom Shaders and Filters > Truchet Tiles`.

## Examples

Demo Scenes

Several examples can be loaded via the `Create > Demo Scenes > Custom Shaders and Filters` menu.

Example

1. Create a [Rectangle](/content/docs/nodes/shapes/basic-shape/rectangle/index.html).
2. In the [Attribute Editor](/content/docs/user-interface/menus/window-menu/attribute-editor/index.html)'s **Fill** tab right click in the **Shaders** attribute > `Add Shader > SkSL Shader`.
3. Double click the **SkSL Shader** to load its Attribute Editor UI.
4. Right click on the **n0** uniform, choose **Rename...** and rename to `time`.
5. Replace the default **Shader Code** with the example code below.

A blue flame will appear on the Rectangle. Try connecting a [Frame Behaviour](/content/docs/nodes/behaviours/frame/index.html) to the **time** uniform.

```jsx
// Created by Anatole Duprat - XT95/2013

// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

float noise(vec3 p) //Thx to Las^Mercury
{
    vec3 i = floor(p);
    vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
    vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5;
    a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
    a.xy = mix(a.xz, a.yw, f.y);
    return mix(a.x, a.y, f.z);
}

float sphere(vec3 p, vec4 spr)
{
    return length(spr.xyz-p) - spr.w;
}

float flame(vec3 p)
{
    float d = sphere(p*vec3(1.,.3,1.), vec4(.0,-1.,.0,1.));
    return d + (noise(p+vec3(.0,time*0.1,.0)) + noise(p*3.)*.5)*.25*(p.y) ;
}

float scene(vec3 p)
{
    return min(100.-length(p) , abs(flame(p)) );
}

vec4 raymarch(vec3 org, vec3 dir)
{
    float d = 0.0, glow = 0.0, eps = 0.02;
    vec3  p = org;
    bool glowed = false;
    for(int i=0; i<64; i++)
    {
        d = scene(p) + eps;
        p += d * dir;
        if( d>eps )
        {
            if(flame(p) < .0)
                glowed=true;
            if(glowed)
                glow = float(i)/64.;
        }
    }
    return vec4(p,glow);
}

half4 main(vec2 fragCoord)
{
    vec2 uv = 4.0 * fragCoord.xy / resolution.xy;
    uv.x *= resolution.x / resolution.y;
    vec3 org = vec3(0., -4.5, 4.);
    vec3 dir = normalize(vec3(uv.x*1.6, -uv.y, -1.5));
    vec4 p = raymarch(org, dir);
    float glow = p.w;
    half4 col = mix(half4(1.,.5,.1,1.), half4(0.1,.5,1.,1.), p.y*.02+.4);
    return half4(mix(half4(0.), col, pow(glow*2.,4.)));
}
```

### Flat colour

1. Delete the default `n0` uniform. To do this, right click on the attribute and choose **Delete Selected Attribute**.
2. Use the `+` button to add a **Color (half4)** uniform.
3. Paste the code below into the **Shader Code** input:

```jsx
    half4 main(float2 fragCoord) {
    return n0;
    }
```

4. Adjust the color values on the uniform.

### Cycling colour

1. Rename the existing **n0** uniform to `time`. To do this, right click on the attribute and choose **Rename...**.
2. Paste the code below into the **Shader Code** input:

```jsx
    vec3 colorA = vec3(0.149,0.141,0.912);
    vec3 colorB = vec3(1.000,0.833,0.224);
    half4 main(vec2 fragCoord) {
    vec3 color = vec3(0.0);
    float percent = abs(sin(time*.01)); // Mix uses percent (a value from 0–1) to...
    color = mix(colorA, colorB, percent);
    return half4(color,1.0);
    }
```

3. Scrub the **time** uniform.

### Pixels

1. Rename the existing **n0** uniform to `scale`. To do this, right click on the attribute and choose **Rename...**.
2. Paste the code below into the **Shader Code** input:

```jsx
    float random (vec2 uv) {
    return fract(sin(dot(uv.xy , vec2(12.9898,78.233))) * 43758.5453);
    }
    half4 main(vec2 fragCoord) {
    vec2 uv = fragCoord / resolution.xy;
    uv *= max(1.0, scale);
    vec2 ipos = floor(uv);
    vec2 fpos = fract(uv);
    vec3 color = vec3(random(ipos));
    return half4(color,1.0);
    }
```

3. Increase the uniform's values.

### Fractal Brownian motion

```jsx
    float random (vec2 uv) {
        return fract(sin(dot(uv.xy, vec2(12.9898,78.233))) * 43758.5453123);
    }
    float noise (vec2 uv) {
        vec2 i = floor(uv);
        vec2 f = fract(uv);
        float a = random(i);
        float b = random(i + vec2(1.0, 0.0));
        float c = random(i + vec2(0.0, 1.0));
        float d = random(i + vec2(1.0, 1.0));
        vec2 u = (f * f * (3.0 - 2.0 * f));
        return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
    }
    float fbm (vec2 uv) {
        float v = 0.0;
        float a = 0.5;
        vec2 shift = vec2(100.0);
        float2x2 rot = float2x2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50));
        for (int i = 0; i < 5; ++i) {
            v += a * noise(uv);
            uv = rot * uv * 2.0 + shift;
            a *= 0.5;
        }
        return v;
    }
    half4 main(vec2 fragCoord) {
        float2 uv = fragCoord.xy/resolution.xy*3.;
        vec3 color = vec3(0.0);vec2 q = vec2(0.);
        q.x = fbm( uv + 0.00*time);
        q.y = fbm( uv + vec2(1.0));vec2 r = vec2(0.);
        r.x = fbm( uv + 1.0*q + vec2(1.7,9.2)+ 0.15*time );
        r.y = fbm( uv + 1.0*q + vec2(8.3,2.8)+ 0.126*time);
        float f = fbm(uv+r);
        color = mix(vec3(0.101961,0.619608,0.666667), vec3(0.666667,0.666667,0.498039), clamp((f*f)*4.0,0.0,1.0));
        color = mix(color, vec3(0,0,0.164706), clamp(length(q),0.0,1.0));
        color = mix(color, vec3(0.666667,1,1), clamp(length(r.x),0.0,1.0));
        return half4((f*f*f+.6*f*f+.5*f)*color,1.);
    }
```

3. Increase the uniform's values.
