The above four images show is a sequence of animated shader stills from left to right and top to bottom.

For this week’s homework shader explorations I decided to integrate my first shader, a Piet Mondrian inspired shader (created when I was exploring rectangle placement and layering effects for the *Book of Shaders’* “recreate a Piet Mondrian painting” exercise), as I felt the design would make for a cool tile effect. The original colours followed Mondrian’s primary colour scheme (similar to the last still, but the small rectangle was yellow), but I felt that it needed to be more dynamic so I decided to animate a colour shifting gradient using u_time and smoothstep.

I still felt like I needed to add more variety of shapes, as I took the effort to make functions based on all of the shape exercises, so I decided on adding a polar shape. I found experimenting with the different parameters of polar shapes extremely fun, therefore I created a polar shape function that allowed me to control everything from position to length and width of spokes. Although I could have gone for a more complicated shape, I decided against it because the tiling pattern was also complex. It was an awesome moment when I realized I was able to layer the tile pattern over the polar design and see the solar shapes through the gap made with one of the rectangles.

Overall, I had a lot of fun learning about shapes and creating my own functions for them.

// Author: Madelaine Fischer-Bernhut
// Title: Animated Piet Mondrian Pattern v2
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
#define PI 3.14159265358979323846
//rotation and tile functions from the Book of Shaders "Patterns"
vec2 rotate2D(vec2 st, float angle){
st -= 0.5;
st = mat2(cos(angle), -sin(angle),
sin(angle), cos(angle))*st;
st += 0.5;
return st;
}
vec2 tile(vec2 st, float zoom){
//scale up space
st *= zoom;
//wrap around 1.0
return fract(st);
}
vec2 rotateTilePattern(vec2 st){
//scale coordinate system by 2x2
st *= 2.0;
//give each cell and index number according to its position
float i = 0.0;
i += step(1.0, mod(st.x,2.0));
i += step(1.0, mod(st.y,2.0))*2.0;
//each cell between 0.0 -1.0
st = fract(st);
//rotate each cell according to index
//use matrix to rotate the space
if(i == 1.0){
st = rotate2D(st, PI*-0.5);
} else if (i == 2.0){
st = rotate2D(st, PI*0.5);
} else if (i == 3.0){
st = rotate2D(st, PI*2.0);
} else if (i== 0.0){
st = rotate2D(st, PI);
}
return st;
}
float drawRect(vec2 st, vec2 size, vec2 pos){
float result = 1.0;
//invert size so the size variables will controle the size based on the white dimensions
vec2 border = (1.0-size)/2.0;
result = step(border.x + pos.x, st.x);
result *= step(border.x - pos.x, 1.0-st.x);
result *= step(border.y + pos.y, st.y);
result *= step(border.y - pos.y, 1.0-st.y);
return result;
}
float createPolShape(vec2 st, float size, float spokesNum, vec2 spokeSize, vec2 pos, float rot, float blur){
float result = 1.0;
//control the position of the shape
pos -= st;
//control the size of the shape
float r = length(pos)*size;
float a = atan(pos.y, pos.x);
//control the number of "spokes" and their shape
//rotate and animate the shape by adding or subtracting from the "a" in cos or sin
float f = cos(a*spokesNum + rot)*spokeSize.y+spokeSize.x;
f = abs(cos(a*spokesNum+rot)*sin(a*spokesNum+rot))*spokeSize.y+spokeSize.x;
// f = smoothstep(-.5,1.0, cos(a*spokesNum+rot))*spokeSize.y+spokeSize.x;
//changing f+value effects focus of shape (blurred)
result = 1.0-smoothstep(f,f+blur,r);
return result;
}
void main() {
//st are texture coordinates, s is along the horizontal axis and t along the vertical axis (surface)
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
float outline = 0.05;
//for testing: centre of polar shape position is based on mouse
vec2 pos = u_mouse/u_resolution;
pos = vec2(0.5);
vec3 color = vec3(0.0);
//polar shape will appear underneath Piet Mondrian pattern
color = vec3(createPolShape(st, 2.15, 10.0, vec2(0.350,0.860), pos, u_time*2.0, -0.260));
//divide space by value
st = tile(st, 1.0);
//first rotate entire space by 90 deg
st += rotate2D(st,PI*0.5);
//then rotate title patterns based on index/location
st = rotateTilePattern(st);
//create bordered rectangles
//white rectangles
//adding the initial rectangle layer instead of multiplying results in the Piet Mondrian Pattern being masked by the polar shape
// color += vec3(drawRect(st, vec2(0.360,0.590) - vec2(outline), vec2(-0.320,0.210)));
//multiplying a rectangle layer in with the other two added results in that rectangle becoming "transparent"
color *= vec3(drawRect(st, vec2(0.360,0.590) - vec2(outline), vec2(-0.320,0.210)));
color += vec3(drawRect(st, vec2(0.480,0.585) - vec2(outline), vec2(0.259,-0.067)));
color += vec3(drawRect(st, vec2(1.0,0.165) - vec2(outline), vec2(0.000,-0.417)));
//coloured rectangles (with animated gradient overlay effect using smoothstep to control placement, and offsetting those colour gradients by overlaying sin & cos time animations)
color.r += drawRect(st, vec2(0.540,0.300) - vec2(outline), vec2(0.105,0.350)) * smoothstep(sin(u_time*0.4)*0.9,1.1,st.x) ;
color.g += drawRect(st, vec2(0.540,0.300) - vec2(outline), vec2(0.105,0.350)) * smoothstep(cos(u_time*0.4)*0.9,1.1,st.x) ;
color.r += drawRect(st, vec2(0.150,0.3) - vec2(outline), vec2(0.425,0.35))* smoothstep(cos(u_time*0.4)*0.9,1.5, st.y);
color.g += drawRect(st, vec2(0.150,0.3) - vec2(outline), vec2(0.425,0.35))* smoothstep(sin(u_time*0.4)*0.9,1.5, st.y);
color.b += drawRect(st, vec2(0.540,0.300) - vec2(outline), vec2(-0.230,-0.210)) * smoothstep(sin(u_time*0.4)*0.95,1.2, 1.0-st.x);
color.g += drawRect(st, vec2(0.540,0.300) - vec2(outline), vec2(-0.230,-0.210)) * smoothstep(cos(u_time*0.4)*0.95,1.2, 1.0-st.x);
gl_FragColor = vec4(color,1.0);
}