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); }