For WEEK 5, I worked with Mahnoor. I was tasked with the initial porting of our Week 3 shaders into p5.js and creating an image distortion shader.

For the image distortion shader, I created a distorter that affects the texture UV coordinates of the image, based on *Simple Texture Distort* by mikiex on Shader Toy. Instead of using a noise texture as mikiex did, I replaced it with generated simplex noise from the Book of Shaders. To create an inverted colour filter for the image, I divided the initial image that I added the distortion value to the UV with a mix of the distorted initial image texture with an altered second version of the image that instead subtracted the distortion from the UV. Mixing the two versions of the distorted image, one that follows the original colour scheme and another that is inverted distorts them in opposite directions. This results in a swipe effect where the value of distortion would become zero in both directions (looped using sin) and will form the original non-distorted image of the flowers for a split second.

The distorted colours and rounded shapes that the noise forms the image into reminds me of the psychedelic closeups of the surface of a soap bubble (caused by a two-beam interference of light).

Overall, I enjoyed the Shader exercises this week and had fun seeing how my partner, Mahnoor, approached shader art. It was also great to have immediate feedback during the process and to support each other and help when we got stuck.

There is not much to say about porting our Week 3 shaders into p5.js, other than every line of setup code counts. It was more complicated than I thought it would be, although fairly straightforward to execute once you are used to the process. I did have fun applying the shaders as textures to some simple (default) shapes (a sphere and box). I added simple interaction to the p5.js sketch to switch between 3D shapes and shaders on mouse click as well allow the viewer to rotate the shapes using mouse coordinates.

//Author: Madelaine Fischer-Bernhut //Title: Image Distortion #ifdef GL_ES precision mediump float; #endif //get texture coordinates from vert shader varying vec2 vTexCoord; uniform vec2 u_resolution; uniform vec2 u_mouse; uniform float u_time; //texture coming from p5.js uniform sampler2D imgtext; //Book of Shaders Simplex Noise (based off Ian McEwan, Ashima Arts) // Some useful functions vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } vec3 permute(vec3 x) { return mod289(((x*34.0)+1.0)*x); } float snoise(vec2 v){ const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439); vec2 i = floor(v + dot(v, C.yy) ); vec2 x0 = v - i + dot(i, C.xx); vec2 i1; i1 = (x0.x &amp;gt; x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; i = mod(i, 289.0); vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 )); vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); m = m*m ; m = m*m ; vec3 x = 2.0 * fract(p * C.www) - 1.0; vec3 h = abs(x) - 0.5; vec3 ox = floor(x + 0.5); vec3 a0 = x - ox; m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); vec3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw; return 130.0 * dot(m, g); } void main() { // position of the pixel divided by resolution, to get normalized positions on the canvas vec2 st = gl_FragCoord.xy/u_resolution.xy; vec2 uv = vTexCoord; //texture is loaded upside down and backwards by default, so flip it uv.y = 1.0 - uv.y; //create a distorter (based off Simple Texture Distort by mikiex, instead of another texture it uses snoise) vec2 pos = vec2(st.x*10.0 - (u_time*0.2), st.y*10.0 + (u_time*0.2)); vec3 dist = vec3(snoise(pos)*0.5+0.5); vec2 distorter = vec2(dist.rg) * vec2(0.1-sin(u_time*0.2)); //zoom in and out of image by multiplying the "UV" value, use fract to tile zoomed out images vec4 imgText = texture2D(imgtext, fract(uv)+distorter); vec4 imgText2 = texture2D(imgtext, fract(uv)-distorter); float grey = (imgText.r + imgText.g + imgText.b)/3.0; vec3 color = vec3(0); //grey filter // color = vec3(grey); //default (full) color color = vec3(imgText.r,imgText.g, imgText.b); //blend in an "inverted" color filter version of the image // color /= mix(color, vec3(1.0), vec3(imgText2.r,imgText2.g, imgText2.b)); color /= mix(color, vec3((sin(u_time*0.1))), vec3(imgText2.r,imgText2.g, imgText2.b)); //direct image color // gl_FragColor = vec4(imgText); //filtered camera feed gl_FragColor = vec4(color, 1.0); }