Skip to main content

SkSL Shader

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/ can be converted for use in Cavalry.

For more detail on the differences between GLSL and SkSL see the Skia documentation.

Integer Uniforms

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

UI

Blend Mode - See Blend Modes.

Shader Code - Paste/edit SkSL code here.

Inputs - Click the + button to 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.

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 > Truchet Tiles.

Examples

Demo Scenes

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

Example
  1. Create a Rectangle.
  2. In the Attribute Editor'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 to the time uniform.

// 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:
     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:
     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);
    }
  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:
     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); // Scale the coordinate
    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);
    }
  3. Increase the uniform's values.

Fractal Brownian motion

  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:
     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.);
    }
  3. Increase the uniform's values.