top of page

GLSL Shaders

Updated: Jan 14, 2021

What's so cool about shaders?


What is amazing about shaders, is that they aren't just useful for graphics programming, they are used in all kinds of data processing, including the

most advanced forms of AI and Machine Learning.






Work 1

Try to modify the colours of the fragment shader by using the time uniform and a mathematical function.


< basic GLSL setup:

The GLSL Code I need change

======================================================================

precision mediump float;

uniform vec2 u_resolution;

uniform float u_time;


void main() {

vec2 colour = gl_FragCoord.xy/u_resolution.xy;

gl_FragColor=vec4(abs(sin(u_time)),0.5,0.5,0.1);

}

======================================================================




Work 2

-1 Uncomment the line which uses the distance field to form a circle. How does it

work?

-2 Try to use the 'smoothstep' function to make the edges of the circle smooth.

-3 Now try to change the position of the circle by multiplying the centre of the circle by

the mouse position.

-4 Can you change the colour of the circle based on the y dimension? Make a note of

the effect this has.


< basic GLSL setup:

-1

The GLSL Code I need change

======================================================================

float cooler = distance(gl_FragCoord.xy, pos/1.8);

colour *= 0.02;

if ( color > 1.0 ) ;

// colour = step( color , 1.0 )

======================================================================


-2


The GLSL Code I need change

======================================================================

vect2 pos = gl_FragCoord.xy - resolution.y / 2.0;


float dist_squared = dot(pos, pos);

float colour = smoothstep( 650. , 750. , diet_squared );

======================================================================


-3
















The GLSL Code I need change

======================================================================

void main(){

vec2 normCoord = gl_FragCoord.xy/resolution.y;

vec2 pos = vec2(0.5)-normCoord;

// the radius is the length of the hypotenuse

float radius = length(pos)*2.0;

// the angle is the inverse tangent of y/x

float angle = atan(pos.y,pos.x);

// cosine of the angle for complex rose

float petals = cos(angle*1.0*mouse.y*10 *radius); // change this value with mouse.x maybe?

vec3 colour = vec3(step(petals,radius) );

gl_FragColor = vec4(vec3(colour),1.0);

}

======================================================================


-4

The GLSL Code I need change

======================================================================

precision mediump float;

//These uniforms need to be set up in your management code

uniform vec2 resolution;

uniform vec2 mouse;

uniform float time;

// This is the main loop

void main(void)

{

vec2 pos = gl_FragCoord.xy-resolution.xy/3.0;

float dist_squared = dot(pos,pos);

float colour =0.;

colour = smoothstep(dist_squared,dist_squared*1.0,1000.);


gl_FragColor = vec4(vec3(colour),1.0);

}

======================================================================




Work 3

The method instead

-1 What is the main difference? Does it matter?

-2 Uncomment the line which contains the modulo function. Comment out the other

pos2 line as indicated in the code. What is going on here?


< basic GLSL setup:


-1

Step and Smoothstep

The step() interpolation receives two parameters. The first one is the limit or threshold, while the second one is the value we want to check or pass. Any value under the limit will return 0.0 while everything above the limit will return 1.0.

eg:

// Step will return 0.0 unless the value is over 0.5,

// in that case it will return 1.0

float y = step(0.5,st.x);


The other unique function is known as smoothstep(). Given a range of two numbers and a value, this function will interpolate the value between the defined range. The two first parameters are for the beginning and end of the transition, while the third is for the value to interpolate.

eg:

// Smooth interpolation between 0.1 and 0.9

float y = smoothstep(0.1,0.9,st.x);


-2

The GLSL Code I need change

======================================================================

// vec2 pos = gl_FragCoord.xy - resolution.y / 2.0;

vec2 pos = mod( gl_FragCoord.xy , vec2( 100.0 ) ) - vec2( 20.0 )

======================================================================




Work 4

Here you can see a series of functions for creating squares and circles (Remember we're just working on the fragshader code)

You should notice that the square functions create squares, not rectangles.


-1 Create a new called rectangle function that lets you specify the length of the sides

independently.


< basic example:

The GLSL Code I need change

======================================================================

precision highp float;

uniform float time;

uniform vec2 resolution;


void main(void) {


vec2 st = (gl_FragCoord.xy / resolution.yy);

vec2 pos = vec2(0.5)-st.xy;

float size = abs(cos(time))/4. ;

float colour = 1.0;

if (length(pos.x) < size && length(pos.y) < size) colour = 0.2;

// if (distance(st,vec2(0.5))) < size && distance(st,vec2(0.5)) < size) colour =1.;

// I try to use distance function to see whether the result is same with length function, but I failed.

gl_FragColor = vec4(vec3(colour), 1.0);

}

======================================================================


-2 Now try to create a simple picture with lots of rectangles, squares or circles of

different colours. Remember you can add, subtract or multiply the outputs of

functions. Make notes about the kinds of effects this can have.


< basic example:

The GLSL Code I need change

======================================================================

precision mediump float;


uniform vec2 resolution;

uniform vec2 mouse;

uniform highp float time;

float square(vec2 pos, float size) {

vec2 normCoords = gl_FragCoord.xx/resolution;

float aspect = resolution.x/resolution.y;

size*=0.2;

if (length((normCoords.x-pos.x) * aspect)< size && length(normCoords.y-pos.y) < size) {

return 2.0;

}

else {

return 0.;

}

}

float line(vec2 pos, float funct) {

return step(funct,pos.y)-step(funct,pos.y-0.01);

}

float circle(vec2 pos, float size) {

size = 1.*size;

size*=10.;


float aspect = resolution.x/resolution.y;


vec2 normCoord = vec2(gl_FragCoord.x/(resolution.x) * aspect,gl_FragCoord.y/resolution.y);

float colour = distance(normCoord,pos);

return smoothstep(colour * size, colour * size+0.02

,1.0);

}


void main(){

//vec2 pos = gl_FragCoord.xy/resolution;

float rect = square(vec2(0.05,0.08),0.8);

float rect2 = square(vec2(0.25,0.35),0.9);

float rect3 = square(vec2(0.42,0.67),1.0);

float circleOne = circle(vec2(1.1,0.5),0.8);

vec3 squareOne = vec3(0.1,0.22,0.5*mouse.x) * rect;

vec3 squareTwo = vec3(0.3*mouse.x,0.0,0.1) * rect2;

vec3 squareThree = vec3(0.1,0.0,0.8*mouse.x) * rect3;

//vec3 square = vec3(0.0);

//float pct = abs(sin(u_time));


gl_FragColor = vec4(squareOne + squareTwo + squareThree + circleOne,1.0);

}

======================================================================


-3 Now, use a mat2 matrix to skew the sides of the square, or to rotate it. You can copy

the rotation matrix from this code:

< basic example:

The GLSL Code I need change

======================================================================

precision mediump float;

//These uniforms need to be set up in your management code

uniform vec2 resolution;

uniform vec2 mouse;

uniform float time;

#define M_PI 3.14159265358979323846


//Here's how you rotate around the centre of the screen

void main(void)

{

float angle = M_PI * mouse.x;


mat2 rotation = mat2( cos(angle), sin(angle),-sin(angle), cos(angle));

mat2 rotation2 = mat2( cos(angle), sin(angle),-sin(angle), tan(angle));

mat2 scale = mat2(3.,1.,1.,3.);

mat2 scale2 = mat2(2.,0.,0.,2.);

vec2 translate = vec2(resolution.x/6.,resolution.y/6.);

vec2 pos = mod(rotation * (gl_FragCoord.xy - translate), vec2(30.0)) - vec2(20.0);

vec2 pos2 = mod(rotation * (gl_FragCoord.xy - translate), vec2(20.0)) - vec2(10.0);

//dot product is very useful

float dist_squared = dot(pos, pos);

float dist_squared2 = dot(pos2, pos2);

float colour = smoothstep(50.,70., dist_squared);

float colour2 = smoothstep(70.,120., dist_squared2);

gl_FragColor = vec4(vec3(colour) + vec3(colour2), 1.0);

}

======================================================================


-4 It shows you how to create lines.

Do a complex line drawing using a sequence of lines that carry out specific

functions.

Try to create expressions with combinations of sin, cos, tan, atan, pow etc. Look up

the functions on shaderific for some inspiration.

Experiment adding and subtracting the lines together. Remember that when you

combine functions together, every pixel can be affected.

< basic example:

sin x

x to the 5th power

Useful function reference


My practice

The GLSL Code I need change

======================================================================

precision mediump float;

#define PI 3.14159265359

uniform vec2 resolution;

uniform vec2 mouse;

uniform highp float time;

float line(vec2 pos, float i) {

return smoothstep(i-8.0,i,pos.y)-smoothstep(i,i+4.0,pos.y-0.1);

//return step(i,pos.y)-step(i,pos.y-0.01);

}

float line2 (vec2 pos, float i) {

// return smoothstep(i-0.06,i,pos.y)-smoothstep(i,i+0.04,pos.y);

return step(i,pos.y)-step(i,pos.y-3.);

}

void main() {

//vec2 pos = gl_FragCoord.xy/resolution;

vec2 pos = mod(gl_FragCoord.xy, vec2(50.0)) - vec2(20.0);

float y = pow(pos.x * mouse.x ,1.2);

//float y2 = fract( sin(pos.x * mouse.x )); ???

vec3 color = vec3(y*0.1);


// Plot a line

float i = line(pos,y)+line2(pos,y);

color = vec3(i,2.0,0.9);

gl_FragColor = vec4(color,1.0);

}

======================================================================


Comments


bottom of page