Pandora's Fur

A Flow Field to plot a colorful Avatar-like furry painting.

Created by marcogomez on Wed, 06 Oct 2021 23:29:19 GMT.


// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm4Texture;
uniform sampler2D prgm5Texture;
uniform sampler2D prgm6Texture;
uniform vec2 resolution;
uniform float time;

float osc(float s, float e, float t, float ts) {
  return (e - s) / 2.0 + s + sin(t * ts) * (e - s) * 0.5;
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 prgm4 = texture2D(prgm4Texture, uv);
  vec4 prgm5 = texture2D(prgm5Texture, uv);
  vec4 prgm6 = texture2D(prgm6Texture, uv);
  gl_FragColor = mix(
    mix(prgm4, prgm5, osc(0.1, 0.9, time, 1.0)),
    prgm6,
    osc(0.1, 0.6, time, 0.5)
  );
}

// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm2Texture;
uniform sampler2D noiseTexture;
uniform vec2 resolution;
uniform float time;
uniform int frame;

const float PI = acos(-1.0);
const float TAU = PI * 2.0;
const float hashScale = 0.1031;
const float bgWaveSpeed = 1.0;
const float xDistMag = 0.021;
const float yDistMag = 0.012;
const float xSineCycles = TAU;
const float ySineCycles = TAU;


float hash13(vec3 p3) {
  p3  = fract(p3 * hashScale);
  p3 += dot(p3, p3.yzx + 19.19);
  return fract((p3.x + p3.y) * p3.z);
}

float osc(float s, float e, float t, float ts) {
  return (e - s) / 2.0 + s + sin(t * ts) * (e - s) * 0.5;
}

mat2 rot(float a) {
  return mat2(cos(a), -sin(a), sin(a), cos(a));
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  float minRes = min(resolution.x, resolution.y);
  vec2 fc = gl_FragCoord.xy / minRes;
  float wt = time * bgWaveSpeed;
  float xAngle = wt + fc.y * ySineCycles;
  float yAngle = wt + fc.x * xSineCycles;
  bool bxHalf, byHalf;
  vec2 distortOffset = vec2(sin(xAngle), sin(yAngle)) * vec2(xDistMag, yDistMag);
  vec2 p = texture2D(prgm2Texture, uv).xy;
  float hash = hash13(vec3(gl_FragCoord.xy + float(frame), float(frame)));
  if (p == vec2(0.0)) {
    float h = hash;
    if (h > 2e-4) { return; }
    p = gl_FragCoord.xy + hash - 0.5;
  }
  float oA = osc(0.15, 0.65, time, 0.25);
  float oB = osc(17.0, 30.0, time, 0.21);
  vec2 v = 2.0 * texture2D(noiseTexture, 0.03 * (uv * rot(distortOffset.y * oB)) + distortOffset * oA).xy - 1.0;
  gl_FragColor = vec4(clamp(p + v, 0.0, max(resolution.x, resolution.y)), 0.0, 1.0);
}

// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm1Texture;
uniform vec2 resolution;
uniform float time;
uniform int frame;

void main(void) {
  gl_FragColor = vec4(0.0);
  for (int i = -1; i <= 1; i++) {
    for(int j = -1; j <= 1; j++) {
      vec4 c = texture2D(prgm1Texture, (gl_FragCoord.xy + vec2(i, j)) / resolution.xy);
      if (abs(c.x - gl_FragCoord.x) < 0.5 && abs(c.y - gl_FragCoord.y) < 0.5) {
        gl_FragColor = c;
        return;
      }
    }
  }
}

// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm2Texture;
uniform sampler2D prgm3Texture;
uniform sampler2D noiseTexture;
uniform vec2 resolution;
uniform float time;
uniform int frame;

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec2 v = 2.0 * texture2D(noiseTexture, 0.03 * uv).xy - 1.0;
  float r = 0.96 * texture2D(prgm3Texture, uv).x;
  if (texture2D(prgm2Texture, uv).x > 0.0) { r = 1.0; }
  gl_FragColor = vec4(r, r * v.x, r * v.y, 1.0);
}

// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm1Texture;
uniform sampler2D prgm3Texture;
uniform vec2 resolution;
uniform float time;
uniform int frame;

float osc(float s, float e, float t, float ts) {
  return (e - s) / 2.0 + s + sin(t * ts) * (e - s) * 0.5;
}

vec3 hue(vec3 col, float a) {
  const vec3 k = vec3(0.57735, 0.57735, 0.57735);
  float c = cos(a);
  return col * c + cross(k, col) * sin(a) + k * dot(k, col) * (1.0 - c);
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 prgm1 = texture2D(prgm1Texture, uv);
  vec4 prgm3 = texture2D(prgm3Texture, uv);
  float prgm3x = prgm3.x;
  prgm3x = 0.9 - 0.8 * prgm3x;
  vec3 colA = vec3(prgm1.x * 0.75, 0.0, 1.0 - prgm3x);
  vec3 colB = vec3(0.0, 0.5 - prgm3x, prgm3.x * 0.25);
  float m = mix(prgm3.x, 0.5 - prgm3.y, clamp(osc(-1.0, 2.0, 1.0-prgm3.z, 1.0), 0.3, 0.7));
  vec3 col = clamp(mix(colA, colB, m * m * m) * 2.0, 0.03, 0.9);
  col = clamp(mix(col, hue(col, prgm3.y * 3.0), 0.75), 0.0, 1.0);
  col = clamp(mix(col, prgm3.xxx, 0.5), 0.0, 1.0);
  gl_FragColor = vec4(col, 1.0);
}

// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm4Texture;
uniform vec2 resolution;
uniform float time;
uniform float fft;

const float amount = 1.0;
const float reinhardAmount = 1.0;
const float contrast = 0.9;
const float brightness = 1.7;
const float saturation = 1.0;
const vec2 vignetteSize = vec2(0.25, 0.25);
const float vignetteRoundness = 0.12;
const float vignetteMix = 1.0;
const float vignetteSmoothness = 0.42;
const float W = 1.2;
const float T = 7.5;

float filmicReinhardCurve(float x) {
  float q = (T * T + 1.0) * x * x;
  return q / (q + x + T * T);
}

vec3 filmicReinhard(vec3 c) {
  float w = filmicReinhardCurve(W);
  return vec3(
    filmicReinhardCurve(c.r),
    filmicReinhardCurve(c.g),
    filmicReinhardCurve(c.b)
  ) / w;
}

vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con) {
  const float AvgLumR = 0.5;
  const float AvgLumG = 0.5;
  const float AvgLumB = 0.5;
  const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
  vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
  vec3 brtColor = color * brt;
  vec3 intensity = vec3(dot(brtColor, LumCoeff));
  vec3 satColor = mix(intensity, brtColor, sat);
  vec3 conColor = mix(AvgLumin, satColor, con);
  return conColor;
}

float sdSquare(vec2 point, float width) {
  vec2 d = abs(point) - width;
  return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
}

float vignette(vec2 uv, vec2 size, float roundness, float smoothness) {
  uv -= 0.5;
  float minWidth = min(size.x, size.y);
  uv.x = sign(uv.x) * clamp(abs(uv.x) - abs(minWidth - size.x), 0.0, 1.0);
  uv.y = sign(uv.y) * clamp(abs(uv.y) - abs(minWidth - size.y), 0.0, 1.0);
  float boxSize = minWidth * (1.0 - roundness);
  float dist = sdSquare(uv, boxSize) - (minWidth * roundness);
  return 1.0 - smoothstep(0.0, smoothness, dist);
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 prgm4 = texture2D(prgm4Texture, uv);
  vec3 reinhard = filmicReinhard(prgm4.rgb);
  vec3 color = prgm4.rgb;
  color = mix(prgm4.rgb, reinhard, reinhardAmount);
  color = ContrastSaturationBrightness(color, brightness, saturation, contrast);
  float v = vignette(uv, vignetteSize, vignetteRoundness, vignetteSmoothness);
  vec3 vig = color * v;
  color = mix(color, vig, vignetteMix);
  color = mix(prgm4.xyz, color, amount);
  color = clamp(color, 0.0, 1.0);
  gl_FragColor = vec4(color, 1.0);
}

// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm2Texture;
uniform sampler2D prgm5Texture;
uniform vec2 resolution;

void main() {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 color = texture2D(prgm5Texture, uv);
  vec4 prgm2 = texture2D(prgm2Texture, uv);
  float pb = 0.4;
  vec4 lcdColor = vec4(pb, pb, pb, 1.0);
  int px = int(mod(gl_FragCoord.x, 3.0));
  if (px == 1) lcdColor.r = 1.0;
  else if (px == 2) lcdColor.g = 1.0;
  else lcdColor.b = 1.0;
  float sclV = 0.25;
  if (int(mod(gl_FragCoord.y, 3.0)) == 0) lcdColor.rgb = vec3(sclV, sclV, sclV);
  if (
    int(mod(gl_FragCoord.y, 2.0)) == 0 ||
    int(mod(gl_FragCoord.x, 2.0)) == 0
  ) lcdColor = vec4((prgm2.xxx / (prgm2.yyy + 1e-3)), 1.0);
  gl_FragColor = mix(color, color * lcdColor, 0.5);
}