# SkSL Shader

{% hint style="info" %}
Beta Feature. To enable, check **Show Beta Features** in [Preferences](https://scenegroup.gitbook.io/cavalry/user-interface/menus/window-menu/preferences).
{% endhint %}

{% hint style="warning" %}
The [Material Sampler](https://scenegroup.gitbook.io/cavalry/nodes/behaviours/material-sampler) does not currently support **SkSL Shaders**.
{% endhint %}

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/> 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/master/src/sksl/README).

{% hint style="warning" %}
Note - our SkSL shader currently only takes float uniforms. We will be expanding this functionality soon.
{% endhint %}

### UI

**Blend Mode** - see [Blend Modes](https://scenegroup.gitbook.io/cavalry/user-interface/general/blend-modes).

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

**Inputs** - click the `+ Add` button to to add a uniform.

### Examples

Have a play with a selection of example .cv files. :point\_down:&#x20;

{% file src="<https://1676825895-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LT2-S1m8aSPAI_Gg3Q1%2F-MXbnZi4lKkH7-C-I77V%2F-MXfN1cNa0SN1eeFYzUB%2FSkSL%20Shader%20Examples.zip?alt=media&token=b3715448-50f7-44b9-9bbb-98b118bc3bac>" %}

Original source code:

Stars: <https://www.shadertoy.com/view/XlfGRj>\
Solar Wind: <https://www.shadertoy.com/view/4lf3Rj>\
Clouds: <https://www.shadertoy.com/view/4tdSWr>\
Simple: <https://www.shadertoy.com/view/XsXXDn>

{% hint style="info" %}
Example usage:

1. Create a Rectangle
2. In the [Attribute Editor](https://scenegroup.gitbook.io/cavalry/user-interface/menus/window-menu/attribute-editor), open the **Fill** tab.
3. On the **Shaders** attribute, right click > Add Shader > SkSL Shader.
4. Double click the **SkSL Shader** to load its Attribute Editor UI.
5. Copy and paste the example code below into the **Shader Code** attribute.
6. Rename the existing uniform **n0** to **Time**. To do this, right click on the attribute and choose **Rename**.
7. Click the `+` button to create a new uniform. Choose **Add Double 2 (float2)**.
8. Rename it **Resolution.**
9. Ensure all values are > 0.

You should see a blue flame appear on the Rectangle. You can now start to play with connecting Behaviours (Noise, Sound etc) into each of the inputs. Try connecting a [Frame Behaviour](https://scenegroup.gitbook.io/cavalry/nodes/behaviours/frame) to the Time uniform.:sunglasses:&#x20;
{% endhint %}

```
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 = 2.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** box.
4. Adjust the color values on the uniform.

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

#### **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** box.
3. Scrub the **Time** uniform.

![](https://miro.medium.com/max/512/1*RdEj0Yy_19Rzx3hz9ypn0g.png)

```
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
 // mix the two colors
 color = mix(colorA, colorB, percent);
 
 return half4(color,1.0);
}
```

#### **Pixels**

1. Rename the existing **n0** uniform to **Time**. To do this, right click on the attribute and choose **Rename**.
2. Use the `+` button and choose **Add Double 2 (float2)** to add a new uniform.
3. Rename the uniform to **Resolution.**
4. Paste the code below into the **Shader Code** box.
5. Increase the uniform's values.&#x20;

![](https://miro.medium.com/max/512/1*JU8ZmaLwBFN0Bj1QbUvPOg.png)

```
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, Time); // Scale the coordinate system by 10
 vec2 ipos = floor(uv); // get the integer coords
 vec2 fpos = fract(uv); // get the fractional coords// Assign a random value based on the integer coord
 vec3 color = vec3(random(ipos));
 
 return half4(color,1.0);
}
```

#### Fractal Brownian motion

1. Rename the existing **n0** uniform to **Time**. To do this, right click on the attribute and choose **Rename**.
2. Use the `+` button and choose **Add Double 2 (float2)** to add a new uniform.
3. Rename the uniform to **Resolution.**
4. Paste the code below into the **Shader Code** box.
5. Increase the uniform's values.&#x20;

<img src="https://miro.medium.com/max/512/1*Z-zcPfhz_wnnuWWUIXJm2Q.png" alt="" data-size="original">

```
float random (vec2 uv) {
    return fract(sin(dot(uv.xy, vec2(12.9898,78.233))) * 43758.5453123);
}

// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd

float noise (vec2 uv) {
    vec2 i = floor(uv);
    // Four corners in 2D of a tile
    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);
    // Rotate to reduce axial bias
    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.;
    // uv += uv * abs(sin(Time*0.1)*3.0);
    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.);
}
```
