Table of Contents

Shaders

A memo in GLSL programming.

Coding Shaders

Shaders take a coordinate for each pixel on it's canvas and outputs an rgba value for that coordinate.

Normalized input Coordinates

Generally the vec2 uv is used to describe a normalized input coordinates by dividing the coordinate by the current resolution :

Different compilers use different syntax to describe the resolution. Here we'll use Shadertoy's standard.

vec2 uv = fragCoord.xy / iResolution.xy;

Origin

The origin (0.0 ; 0.0) of this normalized vector is the bottom left.

To move the origin to the center of the screen, remove 0.5 to both components :

uv -= 0.5;

Aspect Ratio

To correct the aspect ratio on non-square displays, we multiply one component (generally x) by the Resolution's aspect ratio.

uv.x *= iResolution.x / iResolution.y;

Circle

To draw a circle, define a center point where the circle should be drawn and use a length function to calculate the length of the coordinates to this center.

One simple way is to compare the length to a value and draw a color if it's less and another if it's more :

    float d = length(uv);
    float c = d;
 
    if (d < .3) c = 0.0 ; else c = 1.0;
 
    // Output to screen
    fragColor = vec4(vec3(c),1.0);

However, this is not recommended as it creates a discontinuity of the values where they jump from 0.0 to 1.0 when reaching the radius of the circle.

It's better to use a smoothstep function like this :

    float d = length(uv);
    float r = .3
    float c = 1.-smoothstep(r, r-.02, d);
 
    // Output to screen
    fragColor = vec4(vec3(c), 1.0);

Here in a dedicated function :

float drawCircle(vec2 uv, vec2 p, float r, float b) {
//p for Position, r for Radius, b for edge Blur
 
    float d = length(uv-p); //This draws to the 
    float c = smoothstep(r, r-b, d);
 
    return c;
}

In the main function, draw multiple items by adding or subtracting to the color variable (the one being output in the end).

Drawing multiple circles for example :

    float b = 0.01; // Blur of edges of circles
 
    float c = drawCircle(uv, vec2(0.), 0.4, b);
    c -= drawCircle(uv, vec2(-.13, 0.12), 0.08, b);
    c -= drawCircle(uv, vec2(.13, 0.12), 0.08, b);

Note : when adding or removing regions in this manner, the color value for each RGB component of each pixel can go below 0.0 and above 1.0.

Shaders will automatically clamp the output between 0.0 and 1.0 but during the calculation of the color, the real value must be taken into account.

This behavior can lead to unexpected behaviors and colors in certain regions where multiple subtractions/additions have been applied.

Adding Color

Add color by using a vec3 col (usually named this way) and creating masks (grayscale, with full black where color won't draw and full white where color draws).

Simply multiply color by the mask.

For the circle example above for example, it would look something like this :

   vec3 col = vec3(1., 1., 0.); //Initialize color to full yellow.
 
    float b = 0.01; // Blur of edges of circles
 
    float mask = drawCircle(uv, vec2(0.), 0.4, b);
    mask -= drawCircle(uv, vec2(-.13, 0.12), 0.08, b);
    mask -= drawCircle(uv, vec2(.13, 0.12), 0.08, b);
 
 
    col *= mask;

ISF

ISF stands for Interactive Shader Format and is a file format used to describe GLSL shaders for real-time image filtering and generation.

* ISF Main Site

Ressources

Online Editors

* TwiGL App and TwiGL GitHub

* ISF Editor

* Book of Shader's Editor

* ShaderToy's Editor

Tools

* Graph Toy : Display math functions

* Color Palettes : Interactive Color Palettes

* Desmos : Great math tools

Documentation

* Inigo Quilez's website

* Shadertoy's unofficial WordPress