Week 2 Homework

screen-shot-2021-02-23-at-12-11-23-amscreen-shot-2021-02-23-at-12-11-40-am


// Author: Francisco
// Title: Assignment 2 - Part 1

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

#define PI 3.1415926535

float drawRectangle(vec2 st, vec2 pos, vec2 size){

float result = 1.0;

vec2 border = (1.0-size)/2.;

st = st - pos + vec2(0.5);

result = step(border.x, st.x);
result *= step(border.x, 1.0-st.x);
result *= step(border.y, st.y);
result *= step(border.y, 1.0-st.y);

return result;
}

float drawCircle(vec2 st, vec2 pos, float size){

float result = distance(st, pos);

result = 1.0-step(size, result);
//result = smoothstep(0.7, 0.6, size);

return result;
}

void main() {

vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;

vec3 hsb;
hsb.r = st.x; // animate hue with time
hsb.g = 1.; // saturation
hsb.b = 1.; // brightness

vec3 color = vec3(0.860,0.509,0.111);
color = vec3(-st.x*1., st.y*1., cos(sin(u_time)));

float c1 = drawCircle(st, vec2(0.5, 0.5), 0.3);
float c2 = drawCircle(st, vec2(0.75, 0.75), 0.5);
float c3 = drawCircle(st, vec2(0.25, 0.75), 0.5);
float c4 = drawCircle(st, vec2(0.25, 0.25), 0.5);
float c5 = drawCircle(st, vec2(0.75, 0.25), 0.5);
float c6 = drawCircle(st, vec2(0.5, 0.5), 0.5);
float c7 = drawCircle(st, vec2(0.75, 0.5), 0.5);

float r1 = drawRectangle(st, vec2(0.5), vec2(0.21));
float r2 = drawRectangle(st, vec2(0.5), vec2(0.43));
float r3 = drawRectangle(st, vec2(0.5), vec2(0.6));
float r4 = drawRectangle(st, vec2(0.5), vec2(0.8));
float r5 = drawRectangle(st, vec2(0.5), vec2(1.0));

float d = distance(st, vec2(0.5,0.5))*1.489;
c6, c7 = d;
r1, r2, r3, r4, r5 = d;

c6 = sin(u_time*PI*0.+d);
c7 = sin(u_time*PI*1.+d);
r1, r2, r3, r4, r5 = sin(u_time*PI*1.+d);

color = mix(color, vec3(3., 0.8, 0.7), c1 * 0.09);
color = mix(color, vec3(3., 0.8, 0.7), c2 * 0.09);
color = mix(color, vec3(3., 0., 0.7), c3 * 0.09);
color = mix(color, vec3(3., 0.8, 0.7), c4 * 0.09);
color = mix(color, vec3(3., 3., 0.7), c5 * 0.03);
color = mix(color, vec3(3., 1., 0.7), c6 * 0.5);
color = mix(color, vec3(3., 0.8, 0.7), c7 * 0.4);

color = mix(color, vec3(0., 0., 1.), r1 * 0.1);
color = mix(color, vec3(0., 0., 1.), r2 * 0.1);
color = mix(color, vec3(0., 0., 1.), r3 * 0.1);
color = mix(color, vec3(0., 0., 1.), r4 * 0.1);
color = mix(color, vec3(0., 0., 1.), r5 * 0.1);

gl_FragColor = vec4(color,0.9);
}

screen-shot-2021-02-23-at-12-12-58-am


// Author: Francisco Samayoa
// Title: Assignment 2 - Part 2

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

#define PI 3.14159265358979323846

vec2 createGrid( in vec2 st, in vec2 grid, out vec2 indices) {

st *= grid;

indices = floor(st);
st = fract(st);

return st;
}

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

float drawRectangle(vec2 st, vec2 pos, vec2 size) {
float result = 1.0;
vec2 border = (1.0 - size) / 2.0;

result = step(border.x, st.x);
result *= step(border.x, 1.0 - st.x);
result *= step(border.y, st.y);
result *= step(border.y, 1.0 -st.y);
return result;
}

float drawCircle(vec2 st, vec2 pos, float size) {
float result = distance(st, vec2(pos));
// blurry
result = 1.0 - smoothstep(size - 0.3, size + 0.676, result);
return result;
}

void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;

vec2 st0 = st;
vec2 indices;

st = createGrid( st, vec2(6.), indices);

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

vec3 color = vec3(0);

if( mod(indices.x, 2.) == 0.0 && mod(indices.y, 2.) == 0.){

// lower left cell

color = vec3(0.955,0.750,0.002);

color = mix(color, vec3(0.933,1.000,0.493), pct/pct2);

} else if( mod(indices.x, 2.) == 1.0 && mod(indices.y, 2.) == 0.){

// lower right cell

st = rotate2D(st, PI * 0.25);

color = vec3(0.975,0.525,0.355);

color = mix( color, vec3(1., 0., 0), (1.-pct)/(-pct2));


} else if( mod(indices.x, 2.) == 0.0 && mod(indices.y, 2.) == 1.){

// upper left

color = vec3(0.745,0.348,0.062);

color = mix( color, vec3(0.737,1.000,0.648), (pct)/(1.-pct2));

} else {

// upper right

color = vec3(0.800,0.365,0.155);

color = mix( color, vec3(0.794,0.866,1.000), (1.-pct)/(1.-pct2));
}

gl_FragColor = vec4(color,1.0);
}

Week 1 Homework

screen-shot-2021-02-23-at-12-04-50-am


// Author: Francisco Samayoa
// Title: Week 1 - Experiment 1

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;

vec3 colorA = vec3(0.930,0.373,0.248);
vec3 colorB = vec3(0.960,0.651,0.138);
vec3 colorC = vec3(0.940,0.244,0.235);
vec3 colorD = vec3(1.000,0.514,0.190);
vec3 mixAB = mix(colorA, colorB, smoothstep(0.25, 0.75, st.y));
vec3 mixCD = mix(colorC, colorD, smoothstep(0.25, 0.75, st.y));
vec3 gradient = mix(mixAB, mixCD, smoothstep(0.25, 0.75, st.x));

//gradient = vec3(st.x,st.y,abs(sin(u_time)));

gl_FragColor = vec4(gradient, 1.0);
}

screen-shot-2021-02-23-at-12-05-29-amscreen-shot-2021-02-23-at-12-05-38-am


// Author: Francisco Samayoa
// Title: Week 1 - Experiment 2

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

#define PI 3.1415926535

// Function from Iñigo Quiles
// https://www.shadertoy.com/view/MsS3Wc

vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix(vec3(1.0), rgb, c.y);
}

void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;

vec3 hsb;
hsb.r = st.x; // animate hue with time
hsb.g = 1.; // saturation
hsb.b = 1.; // brightness

// distanced based hue
float d = distance( st, vec2(0.50,0.500))*0.105;
hsb.r = d;

// animate hue over time
hsb.r = sin(u_time*PI*0.2+d);

vec3 color1 = hsb2rgb( vec3(sin(u_time) *+ d * -4., 4., 1.));
vec3 color2 = color1 * hsb2rgb( vec3(cos(u_time)* st.x * 1., st.y, 1.));
vec3 color3 = color2 * ( vec3(sin(u_time)* st.x * -1., st.y, 1.));

gl_FragColor = vec4(color3,1.0);
}

screen-shot-2021-02-23-at-12-06-08-amscreen-shot-2021-02-23-at-12-05-54-am


// Author: Francisco Samayoa
// Title: Week 1 - Experiment 3

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

// Function from Iñigo Quiles
// https://www.shadertoy.com/view/MsS3Wc

vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix( vec3(1.0), rgb, c.y);
}

void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;

vec3 hsb = vec3(1., 1., 1.);
vec3 hsb2 = vec3(-1., 1., 1.);

vec2 origin = vec2(sin(u_time), cos(u_resolution));
float d = distance(st/2.0, origin)*0.5;
d = d + pow(st.x, st.y);
hsb.r = d;

vec2 origin2 = vec2(cos(u_time)+1., sin(u_time)-1.);
float d2 = distance(st/3.384, origin)*2.;
d2 = d2 + pow(st.y, st.x);
hsb.r = d2;
//color = vec3(st.x,st.y,abs(sin(u_time)));

vec4 color = vec4(hsb2rgb(hsb), 1.0);
vec4 color2 = vec4(hsb2rgb(hsb2), 1.0);
gl_FragColor = mix(color, mix(color, color2, origin.y), origin.x);
}

Week 5

I worked with Nicole Vella for this week’s homework.

This one which resembles a diffractive glass wall (or kind of like tiny glass brick) is achieved by creating a large grid (with tiny units) where each grid unit has its webcam image shifted slightly to focus on the part where it lies in the greater grid. A brownian noise was added on top by Nicole and then I also added an interactive “clear” spot that can be moved by the mouse. View on p5 here

screenshot-2021-02-22-054756

precision mediump float;

// lets grab texcoords just for fun
varying vec2 vTexCoord;

// our texture coming from p5
uniform sampler2D tex0;
uniform float time;
uniform vec2 uMousePos;

vec3 permute(vec3 x){return mod(((x*34.)+1.)*x,289.);}

float snoise(vec2 v){
const vec4 C=vec4(.211324865405187,.366025403784439,
-.577350269189626,.024390243902439);
vec2 i=floor(v+dot(v,C.yy));
vec2 x0=v-i+dot(i,C.xx);
vec2 i1;
i1=(x0.x>x0.y)?vec2(1.,0.):vec2(0.,1.);
vec4 x12=x0.xyxy+C.xxzz;
x12.xy-=i1;
i=mod(i,289.);
vec3 p=permute(permute(i.y+vec3(0.,i1.y,1.))
+i.x+vec3(0.,i1.x,1.));
vec3 m=max(.5-vec3(dot(x0,x0),dot(x12.xy,x12.xy),
dot(x12.zw,x12.zw)),0.);
m=m*m;
m=m*m;
vec3 x=2.*fract(p*C.www)-1.;
vec3 h=abs(x)-.5;
vec3 ox=floor(x+.5);
vec3 a0=x-ox;
m*=1.79284291400159-.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.*dot(m,g);
}

float drawCircle( vec2 st, vec2 pos, float size ){

float result = distance( st, pos);
result = smoothstep( result, result + 0.1 * (sin(time* 2.) * 0.5 + 0.5), 0.15);

return result;
}

vec2 createGrid( in vec2 st, in vec2 grid, out vec2 indices) {

st *= grid;

indices = floor(st);
st = fract(st);

return st;
}

void main() {

vec2 uv = vTexCoord;
// the texture is loaded upside down and backwards by default so lets flip it
uv = 1.0 - uv;
vec2 st = uv;
vec2 test = uv;
vec2 indices;
st = createGrid(st, vec2(100.), indices);

float n=snoise(vTexCoord+time*0.3)*.5+.5;

// add the distortion to our texture coordinates
vec4 tex = texture2D(tex0, uv + st / 9. * n);
float c = drawCircle(test, uMousePos, 0.05);

vec2 toCenter = vec2(0.5)-st;
float angle = atan(toCenter.y,toCenter.x);
float radius = length(toCenter)*2.0;
float z = radius * 10.*sin(time/1.+ atan(st.y, st.x));

vec4 originalTex = texture2D(tex0, test);
tex = mix(tex, originalTex, c);

gl_FragColor = tex;
}

The second randomly samples a gridded colour palette to create multiple moving shapes which are then mixed using brownian motion.
The grid size of the palette needs to be specified, and it will generate a different result every time. View on p5 here

screenshot-2021-02-17-220830
palette

screenshot-2021-02-22-055437

precision mediump float;

// lets grab texcoords just for fun
varying vec2 vTexCoord;

// our texture coming from p5
uniform sampler2D u_tex0;
uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
uniform vec2 randCoord1;
uniform vec2 randCoord2;
uniform vec2 randCoord3;
uniform vec2 randCoord4;
uniform vec2 randCoord5;
uniform vec2 randCoord6;
uniform vec2 randCoord7;
uniform float gridSize;

float random (in vec2 st) {
return fract(sin(dot(st.xy,
vec2(12.9898,78.233)))*
43758.5453123);
}

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

vec2 u = f * f * (3.0 - 2.0 * f);

return mix(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}

#define OCTAVES 6
float fbm (in vec2 st) {
// Initial values
float value = 0.0;
float amplitude = .5;
float frequency = 0.;
//
// Loop of octaves
for (int i = 0; i < OCTAVES; i++) {
value += amplitude * noise(st);
st *= 2.;
amplitude *= .5;
}
return value;
}

float drawCircle(in vec2 st, in float radius, vec2 pos){
vec2 dist = st-vec2(pos);
return 1.-smoothstep(radius-(radius*0.01),
radius+(radius*0.01),
dot(dist,dist)*4.0);
}

float drawBlurryCircle(in vec2 st, in float radius, vec2 pos){
vec2 dist = st-vec2(pos);
return 1.-smoothstep(radius-(radius*0.3),
radius+(radius*0.1),
dot(dist,dist)*4.0);
}

vec4 sampleRandomColour(vec2 randCoord, vec2 uv) {
// set up uv fields to sample colours from the image grid. divide by the cells per side so that it 'zooms' up on one colour
vec2 colourField = uv / gridSize;
// the coords provided need to be normalized
// to shift the canvas the right amount
// to focus on a single random colour
colourField += randCoord / gridSize;
// sample the colour from the image texture
return texture2D(u_tex0, colourField);
}

void main() {

vec2 uv = vTexCoord;

// flip because it's backwards
uv.y = 1.0 - uv.y;

vec4 colour;

vec4 colour1 = sampleRandomColour(randCoord1, uv);
vec4 colour2 = sampleRandomColour(randCoord2, uv);
vec4 colour3 = sampleRandomColour(randCoord3, uv);
vec4 colour4 = sampleRandomColour(randCoord4, uv);
vec4 colour5 = sampleRandomColour(randCoord5, uv);
vec4 colour6 = sampleRandomColour(randCoord6, uv);
vec4 colour7 = sampleRandomColour(randCoord7, uv);

uv += fbm(uv * 3.0);
uv -= 0.3;
uv /= 2.;

vec2 circleField = uv;
circleField.y += sin(sin(u_time) * uv.x * 20.) * 0.1;

float c = drawBlurryCircle(circleField, 0.3, vec2(0.3 + (sin(u_time) *0.5 + 0.5) * 0.2, 0.4));

vec2 circleField2 = uv;
circleField2.x *= 2.0;
circleField2.x += cos(sin(u_time / 4.) * uv.x * 100.) * 0.1;
float c2 = drawBlurryCircle(circleField2, 0.3, vec2(0.5 + (sin(u_time) *0.5 + 0.5) * 0.2, 0.6));

vec2 circleField3 = uv;
circleField3.x *= 3.0;
circleField3.y += sin(sin(u_time / 6.) * uv.x * 50.) * 0.1;
float c3 = drawBlurryCircle(circleField3, 0.7, vec2(0.1 + (sin(u_time) *0.5 + 0.5), 0.8 - (sin(u_time)*0.5 + 0.5)));

vec2 circleField4 = uv;
circleField4.y *= 5.0;
circleField4.x += sin(cos(u_time / 6.) * uv.x * 50.) * 0.1;
float c4 = drawBlurryCircle(circleField4, 0.2, vec2(0.3 + (sin(u_time) *0.5 + 0.5), 0.7 + (sin(u_time)*0.5 + 0.5)));

vec2 circleField5 = uv;
circleField5.y *= 5.0;
circleField5.x += sin(cos(u_time / 3.) * uv.x * 50.) * 0.1;
float c5 = drawCircle(circleField5, 0.4, u_mouse + vec2(0.0, 1.0));

colour = mix(colour1, colour2, dot(uv.x * 2., uv.y * 2.));
colour = mix(colour, colour3, c3);
colour = mix(colour, colour4, c);
colour = mix(colour, colour5, c2);
colour = mix(colour, colour6, c4);
colour = mix(colour, colour7, c5);

gl_FragColor = colour;
}

Week 5 Homework

I worked with Sara Boo. We each worked on our own ideas and then discussed and added to each others through chats.

I wanted to take two images and blend/distort/animate them together as blobs using noise. I really didn’t want one image to overlap with another, I wanted them to look like separate blobs, but as much as I tried, there is still a bit of an overlap. It was pretty tricky, but using a combination of -= or += and white, grey, or black as an overlaying color on the image, I could sort of “mask” out certain areas of each image. I’m very happy with the end result.

Some screenshots:

screenshot-2021-02-20-221308

screenshot-2021-02-20-221324

View it on p5 here

Using two shaders might fix the slight overlap issue. In this exercise I really started to grasp the position vs the color of things and how the two can be used to mask or create effects.

Shader code:

#ifdef GL_ES
precision lowp float;
#endif
  
uniform vec2 u_resolution;

uniform sampler2D u_tex0;
uniform sampler2D u_tex1;
uniform float u_time;
  
varying vec2 v_texcoord;

vec3 permute(vec3 x){return mod(((x*34.)+1.)*x,289.);}

float snoise(vec2 v){
    const vec4 C=vec4(.211324865405187,.366025403784439,
    -.577350269189626,.024390243902439);
    vec2 i=floor(v+dot(v,C.yy));
    vec2 x0=v-i+dot(i,C.xx);
    vec2 i1;
    i1=(x0.x>x0.y)?vec2(1.,0.):vec2(0.,1.);
    vec4 x12=x0.xyxy+C.xxzz;
    x12.xy-=i1;
    i=mod(i,289.);
    vec3 p=permute(permute(i.y+vec3(0.,i1.y,1.))
    +i.x+vec3(0.,i1.x,1.));
    vec3 m=max(.5-vec3(dot(x0,x0),dot(x12.xy,x12.xy),
    dot(x12.zw,x12.zw)),0.);
    m=m*m;
    m=m*m;
    vec3 x=2.*fract(p*C.www)-1.;
    vec3 h=abs(x)-.5;
    vec3 ox=floor(x+.5);
    vec3 a0=x-ox;
    m*=1.79284291400159-.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.*dot(m,g);
}

#define drawCircle(st,pos,size)smoothstep(0.,1./u_resolution.y,size-length(pos-st))

void main() {
  float n = snoise((v_texcoord)-u_time*0.2);
  vec2 uv = vec2(-v_texcoord.x*n, -v_texcoord.y);
  vec4 canvas = vec4(1.);
  
  vec4 color0 = texture2D(u_tex0, fract(uv*3.));
  vec4 color1 = texture2D(u_tex1, fract(uv*3.));
  
  vec4 grey=vec4(vec3(0.5),1.);
  vec4 white=vec4(vec3(1.0),1.);
  vec4 black=vec4(vec3(0.0),1.);

  float circ0=drawCircle(uv,vec2(cos(u_time*0.33)*n,n),.75);

// by using -= and then += with white and black overlays we can effectively mirror blending modes in photoshop
  color1-=mix(color0,white,circ0);
  color0+=mix(color1,black,circ0);
// so that when mixing the two layers, we can use grey as a neutral color which masks the lays from one another
  canvas= mix(color0,grey,color1); 
  
  gl_FragColor = vec4(canvas);
}

For my palette generator, since Sara had done one which uses an input image to generate a palette, I made one which takes some input or random colour and generates a triadic palette based off of the input color.

It then uses noise and blending to generate the blobs I love so much.

Some screenshots:

screen-shot-2021-02-24-at-11-30-26-am

screen-shot-2021-02-24-at-11-30-36-am

screen-shot-2021-02-24-at-11-31-22-am

View it on p5 here

Script.js

let randomImage,
    myShader,
    url,
    m,
    s,
    startPos,
    baseColor,
    triadic1,
    triadic2;

let w = 300;
let h = 300;
let keywords = "palm tree";

function MyColor (h, s, b) {
    this.h = h;
    this.s = s;
    this.b = b;
}

function preload() {
  myShader = loadShader('displayTexture.vert', 'displayTexture.frag');
}

function setup() {
  colorMode(HSB,360,100,100);
  
  baseColor = new MyColor(random(360), random(30,60), 100);
  triadic1 = new MyColor((baseColor.h+120)%360, baseColor.s, baseColor.b);
  triadic2 = new MyColor((baseColor.h+240)%360, baseColor.s, baseColor.b);
  
  startPos=random(1000);

  createCanvas(windowWidth, windowHeight, WEBGL);
  
  // url = "https://source.unsplash.com/random/" + width + "x" + height + "/?" + keywords;
  // randomImage = loadImage(url, "png");
  // baseColor = randomImage.get(random(randomImage.width),random(randomImage.height));
}

function draw() {
  shader(myShader);

  // if (frameCount % 600 == 0) {
  // url = "https://source.unsplash.com/random/" + w + "x" + h;
  // randomImage = loadImage(url, "png");
  // myShader.setUniform("uTexture0", randomImage);
  //   console.log('switch');
  // }

  myShader.setUniform("uTexture0", randomImage);
  myShader.setUniform("uResolution", [width, height]);
  myShader.setUniform("uTime", millis() / 1000);
  myShader.setUniform("uStartPos", startPos);
  myShader.setUniform("uColorBase", [baseColor.h/360,baseColor.s/100,baseColor.b/100]);
  myShader.setUniform("uColorTri1", [triadic1.h/360,triadic1.s/100,triadic1.b/100]);
  myShader.setUniform("uColorTri2", [triadic2.h/360,triadic2.s/100,triadic2.b/100]);

  rect(0, 0, width, height);
}

GLSL Code:

#ifdef GL_ES
precision mediump float;
#endif
  
uniform vec2 uResolution;
uniform sampler2D uTexture0;
uniform float uTime;
uniform float uStartPos;

uniform vec3 uColorBase;
uniform vec3 uColorTri1;
uniform vec3 uColorTri2;
  
varying vec2 vTexCoord;

#define drawCircle(vTexCoord,pos,size,blur)smoothstep(0.,blur/uResolution.y,size-length(pos-vTexCoord));

float drawRectangle(vec2 st,vec2 pos,vec2 size){
    float result=1.;
    vec2 border=(1.-size)/2.200;  
    st=st-pos+vec2(.5);  
    result=step(border.x,st.x);
    result*=step(border.x,1.-st.x);
    result*=step(border.y,st.y);
    result*=step(border.y,1.-st.y);  
    return result;
}

// simplex 2D noise
vec3 permute(vec3 x){return mod(((x*34.)+1.)*x,289.);}
float snoise(vec2 v){
    const vec4 C=vec4(.211324865405187,.366025403784439,
    -.577350269189626,.024390243902439);
    vec2 i=floor(v+dot(v,C.yy));
    vec2 x0=v-i+dot(i,C.xx);
    vec2 i1;
    i1=(x0.x>x0.y)?vec2(1.,0.):vec2(0.,1.);
    vec4 x12=x0.xyxy+C.xxzz;
    x12.xy-=i1;
    i=mod(i,289.);
    vec3 p=permute(permute(i.y+vec3(0.,i1.y,1.))
    +i.x+vec3(0.,i1.x,1.));
    vec3 m=max(.5-vec3(dot(x0,x0),dot(x12.xy,x12.xy),
    dot(x12.zw,x12.zw)),0.);
    m=m*m;
    m=m*m;
    vec3 x=2.*fract(p*C.www)-1.;
    vec3 h=abs(x)-.5;
    vec3 ox=floor(x+.5);
    vec3 a0=x-ox;
    m*=1.79284291400159-.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.*dot(m,g);
}

//brownian motion noise
float fbm(vec2 x) {
	float v = 0.0;
	float a = 0.5;
	vec2 shift = vec2(100);
	// Rotate to reduce axial bias
    mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50));
	for (int i = 0; i < 5; ++i) {
		v += a * snoise(x);
		x = rot * x * 2.0 + shift;
		a *= 0.5;
	}
	return v;
}

float map(float value, float min1, float max1, float min2, float max2) {
 return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}

vec3 hsb2rgb( in vec3 c ){
    vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
                             6.0)-3.0)-1.0,
                     0.0,
                     1.0 );
    rgb = rgb*rgb*(3.0-2.0*rgb);
    return c.z * mix(vec3(1.0), rgb, c.y);
}

void main() {
  
  vec4 color = vec4(1.0);
  float circSize=.5;

  float n = snoise(vec2(vTexCoord+uStartPos+uTime*.1))*.5+.5;
  float b = fbm(vec2(vTexCoord.x,vTexCoord.y+uTime*.1))*0.35;
  
  float rect=drawRectangle(vTexCoord*b,vec2(0.),vec2(0.25));

  float circleC1=drawCircle(vTexCoord,vec2(cos(uTime*0.22)*n+.8,n),circSize,500.*n);
  float circleC2=drawCircle(vTexCoord,vec2(cos(uTime*0.66)*n,n*0.5),circSize,500.*n);

  color=mix(color,vec4(hsb2rgb(vec3(uColorBase)),1.),rect);
  color=mix(color,vec4(hsb2rgb(vec3(uColorTri1)),1.),circleC1*20.);
  color=mix(color,vec4(hsb2rgb(vec3(uColorTri2)),1.),circleC2*10.);
 
  gl_FragColor = vec4(color);
}

Week 3 HW

For this week, I expanded upon my week 2 shader by adding noise and distorting it.

ripple

I first started by adding noise to the colour of my circles, and I experimented with the effects using different values would give me. I also applied noise to the entire canvas by using st.x, distorting the entire sketch.

 


#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

vec2 createGrid( in vec2 st, in vec2 grid, out vec2 indices ){

// multiply by the number of cells
// [0,1] range => [0,10] (for example)
st *= grid;

// get the cell indices
// for example, in a grid of 10x10:
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
indices = floor(st);

// use fract to get the fractional amount of st
// 9.5 => 0.5
// shows the xy coordinate in each cell
st = fract(st);

return st;
}

float drawCircle (vec2 st, vec2 pos, float size){
float result = distance (st, pos);
result=1.-step(size,result);


return result;
}

float random (vec2 st) {
return fract(sin(dot(st.xy,
vec2(12.9898,78.233)))*
43758.5453123);
}
vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }

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 > 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() {

vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;

st.x += snoise(st*0.4);
// good practice to take a copy of the original st
// before you change it
vec2 st0 = st;

vec2 indices;

// This divides the result of the sin function, changing the final size of the circle
float size = 3.;

// This changes the period of the sin function, changing the speed at which the circles animate
float speed = 3.;

vec3 color;

color.r = snoise(st*2. + vec2(0., u_time*.5)) * 0.5+0.5;
color.g = snoise(st*2. + vec2(100., u_time*.5)) * 0.5+0.5;
color.b = snoise(st*2. + vec2(200., u_time*.5)) * 0.5+0.5;
// Create grid for circles
st = createGrid( st, vec2(5., 5.), indices);

// Set bg colour
// Change the colour and sin function of each column
if(indices.x == 0.){
float r = drawCircle(st, vec2(0.5), sin(u_time*speed)/size);
vec3 circleC;

circleC.r = snoise(st*2. + vec2(0., u_time*2.)) * 0.5+0.5;
circleC.g = snoise(st*2. + vec2(100., u_time*2.)) * 0.5+0.5;
circleC.b = snoise(st*2. + vec2(200., u_time*2.)) * 0.5+0.5;
color = mix( color, circleC, r);

}else if(indices.x == 1.){
float r = drawCircle(st, vec2(0.5), sin(u_time*speed+1.)/size);
vec3 circleC;

circleC.r = snoise(st*2. + vec2(0., u_time*2.)) * 0.5+0.5;
circleC.g = snoise(st*2. + vec2(100., u_time*2.)) * 0.5+0.5;
circleC.b = snoise(st*2. + vec2(200., u_time*2.)) * 0.5+0.5;
color = mix( color, circleC, r);
}
else if(indices.x == 2.){
float r = drawCircle(st, vec2(0.5), sin(u_time*speed+2.)/size);
vec3 circleC;

circleC.r = snoise(st*2. + vec2(0., u_time*2.)) * 0.5+0.5;
circleC.g = snoise(st*2. + vec2(100., u_time*2.)) * 0.5+0.5;
circleC.b = snoise(st*2. + vec2(200., u_time*2.)) * 0.5+0.5;
color = mix( color, circleC, r);
}
else if(indices.x == 3.){
float r = drawCircle(st, vec2(0.5), sin(u_time*speed+3.)/size);
vec3 circleC;

circleC.r = snoise(st*2. + vec2(0., u_time*2.)) * 0.5+0.5;
circleC.g = snoise(st*2. + vec2(100., u_time*2.)) * 0.5+0.5;
circleC.b = snoise(st*2. + vec2(200., u_time*2.)) * 0.5+0.5;
color = mix( color, circleC, r);
}
else if(indices.x == 4.){
float r = drawCircle(st, vec2(0.5), sin(u_time*speed+4.)/size);
vec3 circleC;

circleC.r = snoise(st*2. + vec2(0., u_time*2.)) * 0.5+0.5;
circleC.g = snoise(st*2. + vec2(100., u_time*2.)) * 0.5+0.5;
circleC.b = snoise(st*2. + vec2(200., u_time*2.)) * 0.5+0.5;
color = mix( color, circleC, r);
}

gl_FragColor = vec4(color,1.0);
}

Assignment 3

For this assignment I worked on applying last week’s course content to my sketch. I added a grid as well as used noise to alter the trapezoids sides. I used the clamp function to limit the distortion of the noise and sine waves to distort the various lines in the grid.

download-4

vec2 createGrid(in vec2 st, in vec2 grid, out vec2 indices){
 st*= grid;
 indices = floor(st);
 st= fract(st);
 return(st);
}

// Funtion to check the grid and give each cell a different pattern
bool gridCheck(in float gridName, in float check, in float div){
 bool res;
 if(mod(gridName, div)==check){
 res= true;
 }else{
 res=false;
 }
 return(res);
}

//Noise Function referenced from The Book of Shaders
vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }
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 > 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);
}

// Function fot trapezoid
float rect(vec2 st, vec2 size, vec2 loc,float skew, float stretch, vec2 wh){
 
 float result = 1.0;
 
 vec2 border = (1.0-size)/2.000;

 result = step( border.x, mix (st.x,st.y,skew)+-loc.x);
 result *= step( border.x, wh.x-mix (st.x,st.y,(skew))+loc.x);
 result *= step( border.y, mix (st.x,st.y,stretch)+-loc.y);
 result *= step( border.y, wh.y-mix (st.x,st.y,stretch)+loc.y);
 
 return result;
}

// Main code
void main() {

 //Variables
 vec2 st = gl_FragCoord.xy/u_resolution.xy;
 st.x *= u_resolution.x/u_resolution.y;
 
 float g = clamp((snoise( vec2(1.5, st.y + u_time * 0.904)) ),0.1,0.3);
 float g1 = snoise( vec2(0., st.y + u_time * 0.904));
 float g2 = clamp((snoise( vec2(0.5, st.y + u_time * 0.512)) ),0.1,0.9);
 
 vec2 indices;
 float grid= 10.;
 
createGrid(st, vec2(2), indices);
 float row= indices.x;
 float col=indices.y;
 vec3 colour = vec3(0.610,0.700,0.642);
 

//Upper Right grid
if( gridCheck(row,1.,2.) && gridCheck(col,1.,2.) ){
 
 st= createGrid(st, vec2(10.), indices);
 
 } 
//Left cube face
 //Variables
 vec2 wH1= vec2(0.9,1.22); // Width and height varible to make the layers uniform
 vec2 loc1= vec2 (-0.132,-0.204); //Location varible to make the layers uniform
 
 //Colour mixing to get the right colour
 
 vec3 colourA1 = vec3(0.537,0.251,0.725); 
 colourA1.r = rect(st, vec2 (0.472),loc1,-g,1.434, vec2(wH1));
 colourA1.g = rect(st, vec2 (0.400),loc1,g,1.434, vec2(wH1));
 
 vec3 colourA2 = vec3(0.831,0.885,0.812);
 
 //Bottom Left Grid
 if( gridCheck(row,0.,4.) && gridCheck(col,0.,2.) ){
 
 st= createGrid(st+g2, vec2(10.), indices);
 
 }
 
 vec3 colourA = mix(colourA1,colourA2,0.460);
 
//Right cube face
 //Variables
 vec2 wH2= vec2(0.98,0.97);
 vec2 loc2= vec2 (0.172,-0.052);
 float z= sin((st.y+u_time)*(6.28*0.276));
 
 //Colour mixing to get the right colour
 
 vec3 colourB1= vec3(0.128,0.485,0.580);
 colourB1.r = rect(st, vec2 (0.448),vec2 (0.228,-0.044),-g,0.858, vec2(0.95,0.97));
 colourB1.g = rect(st, vec2 (0.400),loc2,g,0.858, vec2(wH2));
 
 vec3 colourB2= vec3(0.795,0.192,0.503);
 
 vec3 colourB = mix(colourB1,colourB2,0.156);
 
//Upper right sub grid
 if( gridCheck(row,1.,2.) && gridCheck(col,1.,2.) ){
 
 st= createGrid(st+z, vec2(5.), indices);
 
 } 
//Upper Right Grid
 if( gridCheck(row,0.,2.) && gridCheck(col,1.,2.) ){
 
 st= createGrid(st+z, vec2(5.), indices);
 
 } 
//Upper Left grid
 if( gridCheck(row,1.,2.) && gridCheck(col,0.,2.) ){
 
 st= createGrid(st+z, vec2(5.), indices);
 
 } 
 
// mixing the faces and animation
float amt= sin((st.x+u_time)*(6.28*0.276)+-0.028)*cos((st.x+u_time)*(6.28*0.276)+0.5);
colour= mix(colourA, colourB,amt);

 

Assignment 2

For this assignment I wanted to try to make 3D figures using what we learned. I edited the code so that I can have diagonal lines, in doing that I made a trapezoid. I used 2 of the shapes to create each of the faces and overlayed another effect so that there is a red outline. I used a sin function to animate it and try to make it look like there is light circling the object but it did not seem to work.

download-6download-7

// Function for trapezoid
float rect(vec2 st, vec2 size, vec2 loc,float skew, float stretch, vec2 wh){
 
 float result = 1.0;
 
 vec2 border = (1.0-size)/2.000;

result = step( border.x, mix (st.x,st.y,skew)+-loc.x);
 result *= step( border.x, wh.x-mix (st.x,st.y,(skew))+loc.x);
 result *= step( border.y, mix (st.x,st.y,stretch)+-loc.y);
 result *= step( border.y, wh.y-mix (st.x,st.y,stretch)+loc.y);
 
 return result;
}
void main() {
 
 vec2 st = gl_FragCoord.xy/u_resolution.xy;
 st.x *= u_resolution.x/u_resolution.y;
 
//Left cube face
 //Variables
 vec2 wH1= vec2(0.9,1.22); // Width and height varible to make the layers uniform
 vec2 loc1= vec2 (-0.132,-0.204); //Location varible to make the layers uniform
 
 //Colour mixing to get the right colour
 
 vec3 colourA1 = vec3(0.554,1.000,0.673); 
 colourA1.r = rect(st, vec2 (0.472),loc1,0.,1.434, vec2(wH1));
 colourA1.g = rect(st, vec2 (0.400),loc1,0.,1.434, vec2(wH1));
 
 vec3 colourA2 = vec3(0.554,1.000,0.673);
 colourA2.r = rect(st, vec2 (0.400),loc1,0.,1.434, vec2(wH1));
 
 vec3 colourA = mix(colourA1,colourA2,0.460);
 
//Left cube face
 //Variables
 vec2 wH2= vec2(0.98,0.97);
 vec2 loc2= vec2 (0.172,-0.052);
 
 //Colour mixing to get the right colour
 
 vec3 colourB1= vec3(0.767,0.785,0.595);
 colourB1.r = rect(st, vec2 (0.448),vec2 (0.228,-0.044),0.,0.858, vec2(0.95,0.97));
 colourB1.g = rect(st, vec2 (0.400),loc2,0.,0.858, vec2(wH2));
 
 vec3 colourB2= vec3(0.990,0.985,0.995);
 colourB2.r = rect(st, vec2 (0.400),loc2,0.,0.858, vec2(wH2));
 
 vec3 colourB = mix(colourB1,colourB2,-0.172);
 
// mixing the faces and animation
float amt= sin((st.x+u_time)*(6.28*0.276)+0.5)*cos((st.x+u_time)*(6.28*0.276)+0.5);
vec3 colour= mix(colourA, colourB,amt);
 result;
}

Week 5 Homework


precision mediump float;
uniform vec2 uResolution;
uniform vec2 uMousePosition;
// lets grab texcoords just for fun
varying vec2 vTexCoord;

// our texture coming from p5
uniform sampler2D tex0;
uniform sampler2D tex1;

void main() {

vec2 uv = vTexCoord;
// the texture is loaded upside down and backwards by default so lets flip it
uv = 1.0 - uv;

// to pixelate an image we need to alter our uvs so that instead of being a smooth gradient it steps from one color to the next
// in order to do this we will use the floor function
// floor will round a float down to the nearest int, so 4.98 would become 4.0, and -37.2 would become -37.0
// first the uv's are multipled times a tiles variable
float tiles = (uMousePosition.x/3.0+5.0);
uv = uv * tiles;

// second the uvs are rounded down to the nearest int
uv = (floor(uv));

// lastly we divide by tiles again so that uvs is between 0.0 - 1.0
uv = uv / tiles;

// often times in glsl you will see programmers combining many operation onto one line.
// the previous three steps could have also been written as uv = floor( uv * tiles ) / tiles

// get the webcam as a vec4 using texture2D and plug in our distored uv's
vec4 color0 = texture2D(tex0, uv);
vec4 color1 = texture2D(tex1, uv);

float blend = clamp(uMousePosition.y / uResolution.x, 0., 1.0);

// use blend to cross-fade with mix()
vec4 color = mix( color1, color0, blend);

gl_FragColor = vec4(color);

// if you'd like a debug view of what the uv's look like try running this line
// gl_FragColor = vec4(uv.x, uv.y, 0.0, 1.0);
}

I took a look at Adam Ferriss’ pixel sketch and merged it with the texture blend example from class. I added interaction using mouse X and mouse Y so that when the mouse is moved horizontally the image output becomes pixelated and when the mouse is moved vertically the camera output and image are blended. Figuring out these interactions took quite a while because I’ve never looked at GLSL with P5 but I was glad to get this little sketch functioning!

screen-recorder-thu-feb-18-2021-18-01-33screen-recorder-thu-feb-18-2021-18-02-04

 

Shaders week 5

wolfshaderwolf1

For this first shader I took inspiration from the webcam displacement example and instead used two images together. I took a picture of a wolf’s head and a picture of water from the internet and added the sin() function to create a murky, watery effect. I used millis() in x position for the set.Uniform statement (myShader.setUniform(“uDisplacement”, map(millis()/50, 0, width, 0, 5));) to produce a u_time effect like in GLSL. In a way, the water image is being animated to displace the wolf image.


#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 uMousePosition;
uniform vec2 uResolution;

uniform sampler2D uTexture0; //wolf
uniform sampler2D uTexture1; //water
uniform float uTime;
uniform float uDisplacement;

varying vec2 vTexCoord;

//takes rbg of a pixel and calculates luminosity
float rgb_to_luma( vec3 color ){
return 0.2126*color.r + 0.7152*color.g + 0.0722*color.b;
}

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, 1.0, 1.0, 0.0);

vec2 offset = vec2(0.0, 0.0);

offset = texture2D(uTexture0, vec2(vTexCoord.x, 1.0-vTexCoord.y)).gb;
offset *= 1.0;

//colours to luminosity
float c = rgb_to_luma(texture2D(uTexture0, vec2(vTexCoord.x, 1.0-vTexCoord.y)).rgb);

offset = vec2(c, c) + uDisplacement;

vec2 uv = vec2(vTexCoord.x, 1.0-vTexCoord.y) + offset;
//vec2 uv = vec2(uTime(vTexCoord.x), 1.0-vTexCoord.y) + offset;
//using sin() to distort the image
color = texture2D(uTexture1, sin(uv) * 0.5);

gl_FragColor = vec4(color);
}

Week 5 Shader Explorations

download-31download-26download-24download-34download-36download-35

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