Chroma and Image Distortion

Wrote this shader for processing a while back. It adds a sort of drunken vibe when applied to images. 

Fragment Shader

precision highp float;

uniform sampler2D texture;
uniform float noiseOffset;
uniform float noiseMultipler;
uniform float noiseAddMultipler;
uniform float colorOffset;
uniform float colorOffsetMod;
uniform float positionMixAlpha;

varying vec4 vertColor;
varying vec4 vertTexCoord;
varying vec4 pos;

//https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
float rand(vec2 n) { 
    return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}

float noise(vec2 p){
    vec2 ip = floor(p);
    vec2 u = fract(p);
    u = u*u*(3.0-2.0*u);

    float res = mix(
        mix(rand(ip),rand(ip+vec2(1.0,0.0)),u.x),
        mix(rand(ip+vec2(0.0,1.0)),rand(ip+vec2(1.0,1.0)),u.x),u.y);
    return res*res;
}

//  https://www.shadertoy.com/view/MdX3Rr
//  by inigo quilez
//
const mat2 m2 = mat2(0.8,-0.6,0.6,0.8);
float fbm( in vec2 p ){
    float f = 0.0;
    f += 0.5000*noise( p ); p = m2*p*2.02;
    f += 0.2500*noise( p ); p = m2*p*2.03;
    f += 0.1250*noise( p ); p = m2*p*2.01;
    f += 0.0625*noise( p );

    return f/0.9375;
}


void main() {
	vec2 p = vertTexCoord.xy;
    vec2 modNoiseP = (p*noiseMultipler + noiseOffset);//2
    float noiseF = (fbm(modNoiseP) + fbm(modNoiseP + noiseAddMultipler* fbm(modNoiseP)));
    float cMod = noiseF * colorOffsetMod;//3
    vec4 red = texture2D(texture,  mix(p, vec2(noiseF) - vec2(colorOffset * cMod,0.), positionMixAlpha));
    vec4 blue = texture2D(texture, mix(p, vec2(noiseF) + vec2(colorOffset * cMod,0.), positionMixAlpha));
    vec4 green = texture2D(texture, mix(p, vec2(noiseF), positionMixAlpha));
	gl_FragColor = vec4(red.r, green.g, blue.b, 1.);
}

Vertex Shader

#define PROCESSING_TEXTURE_SHADER

uniform mat4 transform;
uniform mat4 texMatrix;

attribute vec4 vertex;
attribute vec4 color;
attribute vec2 texCoord;

varying vec4 vertColor;
varying vec4 vertTexCoord;
varying vec4 pos;

void main() {
    gl_Position = transform * vertex;
    pos = transform * vertex;
    vertColor = color;
    vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
}

Kaleidoscope

The above pictures were created using a shader in processing. The shader tiles a triangular slice of the images to create a kaleidoscope effect.

PShader shaderK;
PGraphics backgroundG;
//number of slices
int viewAngleMod = 10;
//size of the slice to use for the kaleidoscope
float viewAngle =  TWO_PI/viewAngleMod;
//rotation of kaleidoscope
float rotation =  0;

void setup() {
  size(960, 640, P3D);
  //load shader
  shaderK = loadShader("shaderFrag.glsl");
  backgroundG = createGraphics(width, height, P3D);
  drawBackground();
}

void draw() {
  background(0);
  shader(shaderK);
  //set shader uniforms
  shaderK.set("viewAngle", viewAngle);
  shaderK.set("rotation", rotation);
  //apply shader to backgroundG
  image(backgroundG, 0, 0);
  
  //rotate kaleidoscope
  rotation+= QUARTER_PI/100;
  if (rotation >= TWO_PI) 
    rotation = 0;
}

//create random background
void drawBackground() {
  backgroundG.beginDraw(); 
  backgroundG.background(255);
  backgroundG.noStroke();
  for (int i = 0; i < 500; i++) {
    backgroundG.fill(random(255),random(255),random(255),random(255));
    backgroundG.ellipse(random(width), random(height), random(300), random(300));
  }
  backgroundG.endDraw();
}

public void keyReleased() {
  if (key == 'p')
    saveFrame("snapShot-####.png");
  if (key == 'r')
    drawBackground();
  if (key == '=')
    viewAngleMod++;
  if (key == '-') {
    viewAngleMod--;
    if (viewAngleMod <0)
      viewAngleMod = 0;
  }
  viewAngle =  TWO_PI/viewAngleMod;
}

Fragment Shader

precision highp float;

uniform sampler2D texture;
uniform float viewAngle;
uniform float rotation;

varying vec4 vertColor;
varying vec4 vertTexCoord;
varying vec4 pos;

void main() {
	//shift center of the vertTex to the bottom left corner
	vec2 newPos = vertTexCoord.xy - vec2(0.5);
    
	//find the distance of newPos from the bottom left corner
	float distance = length(newPos.xy);
	//find the angle of newPos in relation to the bottom left corner
	float angle = atan(newPos.y, newPos.x);
	
	//map every viewAngle in angle to viewAngle/2, 0 and viewAngle/2
	//e.g. viewAngle = 90 degrees, angle = 0 -> angle = 45, angle = 45 -> angle = 0, angle = 90 -> angle = 45, angle = 135 -> angle = 0, angle = 180 -> angle = 45
	angle = abs(mod(angle, viewAngle) - viewAngle/2.0);
	//add rotation of kaleidoscope to angle
	angle += rotation;
	//set newPos to the position of the new angle
	newPos = distance * vec2(cos(angle), sin(angle));
	//move center of newPos to the center of the screen
	newPos += vec2(0.5);
	//set gl_FragColor to color of the pixel at newPos 
    gl_FragColor = texture2D(texture, newPos) * vertColor;
}

Mandelbrot Set Shader

The Mandelbrot set is a fractal. Fractals are mathematical sets that have a repeating pattern at every scale. For more information look at the bottom of this post.

Due to the intensive native of computing the Mandelbrot set, computing it with the CPU is not fast enough to do more than just render an image to the screen. However using the GPU you can render it much faster and at higher resolutions. The following code was written in processing and GLSL to render the fractal to the screen and allow you to move around in real time.

PShader fractal;
float xC = 0;
float yC = 0;
float zoom = 1;
boolean[] keyDown = new boolean[8];
float zoomSpeed = 0.01;
float movementSpeed = 0.1;
float heightF;
float widthF;

void setup() {
  size(960, 640, P3D);
  fractal = loadShader("shaderFrag.glsl", "defaultVert.glsl");
  heightF = height;
  widthF = width;
  //set shader variables
  fractal.set("windowSize", widthF, heightF);
  fractal.set("cameraPos", xC, yC);
  fractal.set("zoom", zoom);
}

void draw() {
  background(0);
  //set which shader
  shader(fractal);
  //render blank box to use the shader on
  rect(0,0,width,height);
  //handle movement
  movement();
  
  //set shader variables
  fractal.set("windowSize", widthF, heightF);
  fractal.set("cameraPos", xC, yC);
  fractal.set("zoom", zoom);
}


 private void movement() {
  if (keyDown[0] == true) {
    yC += movementSpeed * zoom;
  }
  if (keyDown[1] == true) {
    yC -= movementSpeed * zoom;
  }
  if (keyDown[2] == true) { 
    xC -= movementSpeed * zoom;
  }
  if (keyDown[3] == true) { 
    xC += movementSpeed * zoom;
  }
  if (keyDown[4] == true) { 
    zoom -= zoomSpeed * zoom;
  }
  if (keyDown[5] == true) { 
    zoom += zoomSpeed * zoom;
  }
}

public void keyPressed() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = true;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = true;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = true;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = true;
  }
  if (key == '=') {
    keyDown[4] = true;
  }
  if (key == '-') {
    keyDown[5] = true;
  }
}

public void keyReleased() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = false;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = false;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = false;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = false;
  }
  if (key == '=') {
    keyDown[4] = false;
  }
  if (key == '-') {
    keyDown[5] = false;
  }
}

Fragment Shader (where Mandelbrot is rendered)

precision highp float;

uniform sampler2D texture;
uniform vec2 windowSize;
uniform vec2 cameraPos;
uniform float zoom;

varying vec4 vertColor;
varying vec4 vertTexCoord;
varying vec4 pos;

vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main() {
    vec3 color = vec3(0,0,0);
	vec2 pixel = (pos.xy / windowSize) * zoom; 
    double x0 = ((3.5 * pixel.x)) + (cameraPos.x);
    double y0 = ((2.0 * pixel.y)) + (cameraPos.y);
    double x = 0.0;
    double y = 0.0;
    int iteration = 0;
    int max_iteration = 250;
	double xtemp = 0.0;
    while (x * x + y * y < 4  &&  iteration < max_iteration) {
         xtemp = x*x - y*y + x0;
         y = 2.0 * x*y + y0;
         x = xtemp;
         iteration = iteration + 1;
    }
    if (iteration != max_iteration) {
		  float tmp = float(iteration) / float(max_iteration);
		  color = hsv2rgb(vec3(tmp * 10, 1.0, 1.0));
    }
    gl_FragColor = vec4(color.r, color.g, color.b, 1.0);
}

Vertex Shader

#define PROCESSING_COLOR_SHADER

uniform mat4 transform;
uniform mat4 texMatrix;

attribute vec4 vertex;
attribute vec4 color;
attribute vec2 texCoord;

varying vec4 vertColor;
varying vec4 vertTexCoord;
varying vec4 pos;

void main() {
    gl_Position = transform * vertex;
    pos = transform * vertex;
    vertColor = color;
    vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
}

Fractal: Click Here

Mandelbrot Set: Click Here 

Processing Shaders: Click Here