====== 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.
* [[https://editor.isf.video/|ISF Main Site]]
===== Ressources =====
==== Online Editors ====
* [[https://twigl.app/|TwiGL App]] and [[https://github.com/doxas/twigl|TwiGL GitHub]]
* [[https://editor.isf.video/shaders/new|ISF Editor]]
* [[http://editor.thebookofshaders.com/|Book of Shader's Editor]]
* [[https://www.shadertoy.com/new|ShaderToy's Editor]]
==== Tools ====
* [[https://graphtoy.com/|Graph Toy]] : Display math functions
* [[http://dev.thi.ng/gradients/|Color Palettes]] : Interactive Color Palettes
* [[https://www.desmos.com/|Desmos]] : Great math tools
==== Documentation ====
* [[https://iquilezles.org/articles/|Inigo Quilez's website]]
* [[https://shadertoyunofficial.wordpress.com/|Shadertoy's unofficial WordPress]]