Skip to content

SKSL guide

SKSL is a shading language developed by Google for use in their Skia graphics library, which is the foundation for rendering in many applications, including PixiEditor. It allows developers to write custom shaders that can manipulate images and graphics at a low level.

SKSL was modeled on GLSL ES 1.00 and shares most of its syntax and limitations. This page gives an outline of SKSL for those who are at least a bit familiar with GLSL and shader programming.

PixiEditor uses SKSL in the Node Graph’s Shader node, allowing you to create custom shader effects by writing SKSL code directly.

For a more comprehensive understanding of SKSL, you can refer to the following resources:

To effectively use SKSL, you should have a basic understanding of programming concepts and optimally some familiarity with graphics programming.

Knowledge of vector mathematics, color spaces, and how shaders work will be beneficial.

A basic SKSL shader consists of a main function that takes in a vector2 with image coordinates and produces an output color. The main function is the entry point for the shader.

half4 main(vec2 coords) { // coords are not normalized
return half4(1.0, 0.0, 0.0, 1.0); // Returns a red color
}

The types in SKSL are named differently from GLSL:

TypeDescription
floatHigh precision floating-point number
halfMedium precision floating-point number
intHigh precision signed integer
uintHigh precision unsigned integer
shortMedium precision signed integer
ushortMedium precision unsigned integer
boolBoolean, true or false
float2, float3, float4 (vec2, vec3, vec4)Float vectors. vec2 and float2 are interchangable, same for others
half2, half3, half4Medium precision float vectors
int2, int3, int4Integer vectors
uint2, uint3, uint4Unsigned integer vectors
short2, short3, short4Medium precision integer vectors
ushort2, ushort3, ushort4Medium precision unsigned integer vectors
bool2, bool3, bool4Boolean vectors
float2x2, float3x3, float4x4 (mat2x2, mat3x3, mat4x4)Matrices of floats
half2x2, half3x3, half4x4Matrices of medium precision floats
shaderSkSL shader object for runtime composition

Uniforms allow you to pass arbitrary data to the shader from the CPU. They are declared at the top of the shader code and can be of various types, such as float, vec2, half4, etc.

uniform vec2 iResolution;
uniform double someValue;

Skia automatically handles color spaces and color conversion, but passing half4 uniform as a color is not enough. Skia doesn’t know your half4 is a color, so you need to specify it explicitly using layout(color).

layout(color) uniform half4 iColor;

iColor will be automatically converted to the correct color space and will be recognized as a color by PixiEditor as well.

One of the main differences between SKSL and other shading languages is how textures are sampled. In SKSL, you use the eval function on shader variable type.

Sampling is done in local coordinates. For more information about coordinate spaces in Skia, check out the Skia documentation.

uniform shader iImage;
half4 main(vec2 coords) {
return iImage.eval(coords);
}

The general creation syntax is:

half4 color = half4(0.5, 0.5, 0.5, 1.0);
vec3 rgb = vec3(1.0); // each component is set to 1.0
vec4 translucent = vec4(rgb, 0.5); // the rgb vector provides the first three components

Vectors support swizzling, which means that you can extract their components into a new vector by listing them after a dot:

half4 color = half4(0.5, 0.5, 0.5, 1.0);
half3 rgb = half3(color.rgb); // .rgb is used to extract first 3 components
vec4 mixed = vec4(rgb.br, color.gr); // the resulting vector contains (rgb.b, rgb.r, color.g, color.r)

You can also use constants 0 and 1 as swizzle components:

half4 color = half4(0.5, 0.5, 0.5, 1.0);
half4 newColor = color.1gb0; // (1.0, 0.5, 0.5, 0.0)

Vector components can be accessed by xyzw, rgba, or stpq. In other words, each component has multiple names, for example first one can be accessed by x, r, or s:

vec4 vect = vec4(1, 2, 3, 4);
float red = vect.r; // 1
float xcoord = vect.x; // still 1
float scoord = vect.s; // still 1
vec2 yz = vect.yz; // (2, 3)
vec2 greenblue = vect.gb; // (2, 3)
PrecedenceDescriptionOperatorsAssociativity
1 (highest)parenthetical grouping( )NA
2array subscript
function call and constructor structure
field selector, swizzler
postfix increment and decrement
[ ]
( )
.
++ --
Left to Right
3prefix increment and decrement
unary
++ --
+ - ~ !
Right to Left
4multiplicative* / %Left to Right
5additive+ -Left to Right
6bit-wise shift<< >>Left to Right
7relational< > <= >=Left to Right
8equality== !=Left to Right
9bit-wise and&Left to Right
10bit-wise exclusive or^Left to Right
11bit-wise inclusive or|Left to Right
12logical and&&Left to Right
13logical exclusive or^^Left to Right
14logical inclusive or||Left to Right
15selection? :Right to Left
16assignment
arithmetic assignments
=
+= -=
*= /=
%= <<= >>=
&= ^= |=
Right to Left
17 (lowest)sequence,Left to Right

genType in the tables below refers to regular and vector floating point number types, e.g. int, short2, float4… . When used with vector types, the functions are applied component-wise, except for geometric functions. This info is adapted from the GLSL ES 1.00 spec. The list of functions provided here is (likely) not exhaustive.

SyntaxDescription
genType abs(genType x)Returns x if x >= 0, otherwise it returns –x.
genType sign(genType x)Returns 1.0 if x > 0, 0.0 if x = 0, or –1.0 if x < 0
genType floor(genType x)Returns a value equal to the nearest integer that is less than or equal to x
genType ceil(genType x)Returns a value equal to the nearest integer that is greater than or equal to x
genType fract(genType x)Returns x – floor(x)
genType mod(genType x, genType y)
genType mod(genType x, float y)
Modulus (modulo). Returns x – y ∗ floor (x/y)
genType min(genType x, genType y)
genType min(genType x, float y)
Returns y if y < x, otherwise it returns x
genType max(genType x, genType y)
genType max(genType x, float y)
Returns y if x < y, otherwise it returns x.
genType clamp(genType x, genType minVal, genType maxVal)
genType clamp(genType x, float minVal, float maxVal)
Returns min(max(x, minVal), maxVal). Results are undefined if minVal > maxVal.
genType mix(genType x, genType y, genType a)
genType mix(genType x, genType y, float a)
Linear interpolation (lerp). Returns the linear blend of x and y, i.e. x*(1-a)+y*a.
genType step(genType edge, genType x)
genType step(float edge, genType x)
Returns 0.0 if x < edge, otherwise it returns 1.0
genType smoothstep(genType edge0, genType edge1, genType x)
genType smoothstep(float edge0, float edge1, genType x)
Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth Hermite interpolation between 0 and 1 when edge0 < x < edge1.
SyntaxDescription
genType radians(genType degrees)Converts degrees to radians
genType degrees(genType radians)Converts radians to degrees
genType sin(genType angle)Sine
genType cos(genType angle)Cosine
genType tan(genType angle)Tangent
genType asin(genType x)Arc sine. Returns an angle whose sine is x, from -π/2 to π/2.
genType acos(genType x)Arc cosine. Returns an angle whose cosine is x, from 0 to π.
genType atan(genType y, genType x)Atan2. Returns the angle of the vector with coordinates x and y.
genType atan(genType y_over_x)Arc tangent. Returns an angle whose tangent is y_over_x, from -π/2 to π/2.
SyntaxDescription
genType pow(genType x, genType y)Returns x raised to the power y
genType exp(genType x)Natural exponentiation
genType log(genType x)Natural logarithm
genType exp2(genType x)Returns 2 raised to the x power
genType log2(genType x)Returns the base 2 logarithm of x
genType sqrt(genType x)Square root
genType inversesqrt(genType x)Returns 1/sqrt(x)

These operate on vectors as vectors, not component-wise

SyntaxDescription
float length(genType x)Returns the eucledian length of the vector x
float distance(genType p0, genType p1)Returns the eucledian distance between two points
float dot(genType x, genType y)Returns the dot product of x and y
vec3 cross(vec3 x, vec3 y)
half3 cross(half3 x, half3 y)
Returns the cross product of x and y
genType normalize(genType x)Returns a vector in the same direction as x but with a length of 1.
genType faceforward(genType N, genType I, genType Nref)If dot(Nref, I) < 0 return N, otherwise return –N.
genType reflect(genType I, genType N)For the incident vector I and surface normal N, returns the reflection direction: I – 2 ∗ dot(N, I) ∗ N. N must be normalized.
genType refract(genType I, genType N, float eta)For the incident vector I and surface normal N, and the ratio of indices of refraction eta, return the refraction vector. I and N must be normalized.

matType refers to any matrix type.

SyntaxDescription
matType matrixCompMult(matType x, matType y)Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product of x[i][j] and y[i][j].

boolN refers to a boolean vector of any size. vecN refers to a numeric (float, half, int or short) vector of any size.

SyntaxDescription
boolN lessThan(vecN x, vecN y)Returns the component-wise comparison of x < y.
boolN lessThanEqual(vecN x, vecN y)Returns the component-wise comparison of x <= y.
boolN greaterThan(vecN x, vecN y)Returns the component-wise comparison of x > y.
boolN greaterThanEqual(vecN x, vecN y)Returns the component-wise comparison of x >= y.
boolN equal(vecN x, vecN y)
boolN equal(boolN x, boolN y)
Returns the component-wise comparison of x == y.
boolN notEqual(vecN x, vecN y)
boolN notEqual(boolN x, boolN y)
Returns the component-wise comparison of x != y.
bool any(boolN x)Returns true if any component of x is true.
bool all(boolN x)Returns true only if all components of x are true.
boolN not(boolN x)Returns the component-wise logical complement of x.

All of our content is carefully written by hand, no AI was involved during the process.