Week 5 – Image Distortion

screen-shot-2021-03-17-at-2-16-54-am-min screen-shot-2021-03-17-at-2-10-40-am-min screen-shot-2021-03-17-at-2-01-04-am-min

Image Distortion (Noise)

#ifdef GL_ES
precision mediump float;
uniform vec2 uMousePosition;
uniform vec2 uResolution;

uniform sampler2D uTexture0; // image
uniform sampler2D uTexture1; // image2
uniform bool uMousePressed;
uniform float uTime;
uniform float uDisplacement;
varying vec2 vTexCoord;

// 2D Random
float random (in vec2 st) {
 return fract(sin(dot(st.xy,
 * 43758.5453123);

// 2D Noise based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 st) {
 vec2 i = floor(st);
 vec2 f = fract(st);

// Four corners in 2D of a tile
 float a = random(i);
 float b = random(i + vec2(1.0, 0.0));
 float c = random(i + vec2(0.0, 1.0));
 float d = random(i + vec2(1.0, 1.0));

// Smooth Interpolation

// Cubic Hermine Curve. Same as SmoothStep()
 vec2 u = f*f*(3.0-2.0*f);
 // u = smoothstep(0.,1.,f);

// Mix 4 coorners percentages
 return mix(a, b, u.x) +
 (c - a)* u.y * (1.0 - u.x) +
 (d - b) * u.x * u.y;

// calulate luminosity/brightness of pixel from rgb
float rgb_to_luma( vec3 color ){
 return 0.2126*color.r + 0.7152*color.g + 0.0722*color.b;

// map range (just like processing/p5)
float map(float value, float min1, float max1, float min2, float max2) {
 return min2 + (value - min1) * (max2 - min2) / (max1 - min1);

void main() {
 vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
 float br = rgb_to_luma(texture2D(uTexture0, vec2(vTexCoord.x, 1.0-vTexCoord.y)).rgb);
 vec2 uv = vec2(vTexCoord.x, 1.0-vTexCoord.y);
 color = texture2D(uTexture0, fract(uv));

// Use the noise function
 float n = noise(uv);
 float mode = 4.0;
 mode = floor(mode);
 if( mode==4.0){

vec4 color1 = texture2D(uTexture0, vec2(vTexCoord.x, fract(1.0-vTexCoord.y)));
 // get brightness
 // map from 0, 1 => -1, 1
 float br = rgb_to_luma(color1.rgb);
 br = map(br, 0.0, 1., -1., 1.);
 // add brigness to current pixel lookup
 // use fract to repeat values
 color = texture2D(uTexture1, vec2(fract(vTexCoord.x+ br*uDisplacement), fract(1.0-vTexCoord.y+ br*uDisplacement)));
 gl_FragColor = vec4(color);



For my midterm project, I made a a audiovisual experience that is partly randomly generated and partly composed. ToneJS was used to create an audio composition of two main parts. P5 was used to communicate with ToneJS and send data to the shader to use to become audioreactive. This consisted of changing opacity that corresponded with when tones are played, as well as a zoom to scale the shader canvas when transitioning to the second part of the composition.

The shader uses shapes, brownian motion, shaping functions, noise, and gradients to create two distinct compositions. While the elements of the first part are all included in the second, the composition changes drastically because the canvas scaling reveals patterns in the elements that were before not visible beyond the frame of the canvas. As well, new elements are added that respond to new audio elements in the second half.


screenshot-2021-03-14-203949 screenshot-2021-03-14-204308

The audiovisual project can be experienced here -> https://trusting-dijkstra-008c11.netlify.app/

The code can be seen here -> https://github.com/srhboo/shader-music

Week 8 Shader Explorations

minisolarsystem2 minisolarsystem4minisolarsystem10minisolarsystem9

For this week 8’s 3D shader explorations I created a mini solar system. I tried to fit as many of the prompts as I could from the assignment brief into it. I loaded in a planet model and sphere model for the sun (with higher vertex count for smoother displacement) I created in blender and then animated their rotation to mimic a solar system. The camera angles and movement are also animated using sin(), and it creates a simple zoom and tilt effect from a side view to a 2/3 overhead view of the solar system.

For the sun’s shader and texture, in the frag and vert shaders, I animated and distorted a texture (of the surface of the sun) using simplex noise to create a dynamic molten swirling effect with sunspots. To add a bit more interest to the colour of the texture, although not realistic, I blended in a grey variation of the texture based on the vertex model position from the vertex shader. After watching the Bumpmapping tutorial from class, I also displaced the vertices of the sun model based on the brightness of the texture.

Finally, I created a smoothstep() gradient to mimic how sunlight lights up each planet by using the planet’s vertex model position.

p5.js link: https://editor.p5js.org/mzyr18/sketches/G-yABangZ

Week 3 Homework

This week I iterated on last week’s submission by adding rotation to the 6 circles as well as incorporating noise into the background and outer egg.  The process of getting the circles to spin around the central axis while staying aligned with each other was quite a challenge, but after receiving some math help, I learned how PI can be used to offset the starting position of rotation.

This is the result:


seeeedpic seeeedpic2

seedcode seedcode2 seedcode3 seedcode4

Week 8 Shader

For my Shader,  I used Suzanne, and displaced it using a camera feed along normals. I had a separate shader controlling the color. I was not sure why my model “broke apart”, however I ended up finding out it had to do with the smoothing groups of my export from blender. I reexported my model and got the first result – the more or less together mesh torn at UV cuts. I do prefer the look of my other mesh however, so I have included both. monke3 monke4

monke monke2




Mid-Term: Mirror Warp Flow


For my mid-term project, I decided to create a mirror shader that uses Brownian Motion to create a wave-like distortion that mimics water reflection.

To break up the image and to add varying “texture” to the filter, I decided to create shape masks (the 5 rectangles) that filtered the camera feed in different ways. For example, the brightest filter is applied to the rectangle in the middle and the rectangles on either side get darker the closer they are to the edge. Also, the Brownian Motion is only applied to the even-numbered rectangles to create an interesting contrast between distorted and untouched reflections. Still, although the base camera feed of the odd-numbered rectangles is left undistorted, there is some distortion blended in using mix(). To add a soft edge to the rectangle masks as they animate vertically, I used smoothstep()  to create a gradient that flows with the background by applying my Brownian Motion values to the source value for interpolation. The same Brownian Motion is used in most elements of the filter with varying intensities.

Finally, I created a tiled camera feed (50×50) and overlayed it over the background, and due to mixing with the blending techniques of other masks, it also ended up overlaying where the rectangles overlapped. Brownian Motion is also applied to the tile filter and it was interesting to see how the distortion was spread out between all the tiles, so each one was only warped slightly. This allowed for the viewer’s movement to create interesting but discernable patterns and add another level of motion to the background.

The first image was created by placing my hand close to the camera. This interaction can create some cool shifts in colour rather than a distinct reflection.

Finally, The direction of vertical flow can also be controlled using the mouse.

Link to Sketch: https://editor.p5js.org/mzyr18/sketches/Y9JeS_5Ol 

Week 2 Homework

seed seed2

For week 2 I experimented with creating circles and combining them with colours and animation to explore what is called sacred geometry in this glyph commonly referred to as the seed of life.  At first I just wanted to create 7 interlocking circles that all met in the center, but as I brought in the colours and overlapped them in a clockwise fashion, I realized overlapping them with transparent white circles would bring attention to some unique relationships in this shape, so I decided to create a static circle around the inner seed, while using another pulsing circle that expanded close to the perimeter of the shape.  Finally I encapsulated the whole shape in a slowly pulsating egg.  The actual process of getting everything perfect in composition and getting the animation timed the way I wanted was a painstaking and time consuming endeavour, but it was valuable in teaching me what variables within u_time animations would affect the outcome, to either pulse at a certain time or the span of the transformation over time.

seedcode seedcode2

Week 1 Homework


For Week 1 Homework, the first shader I created is an RBG gradient called Seafoam Gradient. I love the range of colour in this one because it reminds me of the view of a horizon looking straight into the sea on a sunny day.


The second I attempted to create 3 different colours using HSB coordinates rather than RGB.  My attempt resulted in what I call Chrome Reflection, as it reminds me of the reflection of light hitting some chrome finish on a sports car.



Finally I decided to explore animation and shaping functions by creating this rudimentary water ripple that moves with u_time.


ripplecode1 ripplecode2

Through the process of creating these three shaders, I learned that a lot of variables can be adjusted from a quintessential line of code, and finding the cornerstone of the code is essential in manipulating the shader. What I found exciting was the use of u_time and all the ways it can be applied in the texture coordinates to produce unique results or animations. I struggled with correctly placing things like U_mouse or u_time in a way that matters or in the way I want them to matter. I also didn’t understand the significance of conditionals in shaders, as there seems to be no condition other than when you put in true, which makes it seem like commenting the code would have the same effect.