The Code Therapy

Cartoony Landscape

Just a few layered textures and a blocky FBM sky for the sake of exercising blending static layers with random patterns and trying to achieve a minimally consistent look.

Created by marcogomez on Wed, 04 Nov 2020 00:49:03 GMT.


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

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

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 prgm2 = texture2D(prgm2Texture, uv);
  gl_FragColor = prgm2;
}

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

uniform sampler2D noiseTexture;
uniform sampler2D eTexture1; // https://i.imgur.com/qphZiTU.png
uniform sampler2D eTexture2; // https://i.imgur.com/HXZDmxY.png
uniform sampler2D eTexture3; // https://i.imgur.com/XZ6zMFp.png
uniform sampler2D eTexture4; // https://i.imgur.com/Yknw9gp.png
uniform sampler2D eTexture5; // https://i.imgur.com/rWxEG0X.png
uniform sampler2D eTexture6; // https://i.imgur.com/LxrrG4M.png

uniform	vec2 resolution;
uniform	float time;
uniform float fft;

const float PI = acos(-1.0); // π or acos(-1.0) or 180°
const float TAU = PI * 2.0; //  τ = π * 2 or 360°
const mat2 m2 = mat2(0.80, -0.60, 0.60, 0.80);

float gaussian(float z, float u, float o) {
  return (
    1.0 / (o * sqrt(TAU))
  ) * exp(-(((z - u) * (z - u)) / (2.0 * (o * o))));
}

vec3 gaussGrain(float t) {
  vec2 ps = vec2(1.0) / resolution.xy;
  vec2 uv = gl_FragCoord.xy * ps;
  float seed = dot(uv, vec2(12.9898, 78.233));
  float noise = fract(sin(seed) * 43758.5453 + t);
  noise = gaussian(noise, 0.0, 0.5);
  return vec3(noise);
}

float noise(vec2 x) {
  vec2 p = floor(x);
  vec2 f = fract(x);
  f = f * f * (3.0 - 2.0 * f);
  float a = texture2D(noiseTexture, (p + vec2(0.5, 0.5 + fft * 0.25)) / 256.0, 0.0).x;
  float b = texture2D(noiseTexture, (p + vec2(1.5, 0.5 + fft * 0.25)) / 256.0, 0.0).x;
  float c = texture2D(noiseTexture, (p + vec2(0.5, 1.5 + fft * 0.25)) / 256.0, 0.0).x;
  float d = texture2D(noiseTexture, (p + vec2(1.5, 1.5 + fft * 0.25)) / 256.0, 0.0).x;
  return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}

float fbm (vec2 uv) {
  float f = 0.0;
  f += 0.5000 * noise(uv); uv = m2 * uv * 2.02;
  f += 0.2500 * noise(uv); uv = m2 * uv * 2.03;
  f += 0.1250 * noise(uv); uv = m2 * uv * 2.01;
  f += 0.0625 * noise(uv);
  return f / 0.9375;
}

vec3 clouds(vec2 uv) {
  vec3 color;
  vec2 q = vec2( 0.0 ), r = vec2( 0.0 );
  q.x = fbm(uv + time * 0.25);
  q.y = fbm(uv + vec2(1.0));
  r.x = fbm(uv + q + vec2(1.7, 9.2) + 0.31 * time * 0.25);
  r.y = fbm(uv + q + vec2(8.3, 2.8) + 0.21 * time * 0.25);
  float f = fbm(uv + r);
  color = mix(vec3(1.0, 1.0, 1.0), vec3(0.3, 1.6, 1.6), clamp((f * f) * 2.0, 0.0, 1.0) + fft * 0.5);
  color = mix(color, vec3(0.4, 0.2, 0.16), clamp(length(q) + fft * 0.33, 0.0, 1.0));
  color = mix(color, vec3(0.4, 0.7, 3.00), clamp(length(r.x) + fft * 0.33, 0.0, 1.0));
  return color * color * 2.0;
}

vec2 curve(vec2 uv) {
  uv *= 1.1;
  uv.x *= 1.0 + pow((abs(uv.y) / 5.0), 2.0);
  uv.y *= 1.0 + pow((abs(uv.x) / 5.0), 2.0);
  uv = (uv / 2.0) + 0.5;
  uv = uv * 0.92 + 0.08;
  return uv;
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.y;
  uv.y *= max(resolution.x, resolution.y) / min(resolution.x, resolution.y) * -.0625 - 1.0;
  vec2 tuv = uv;
  vec2 p = -1.0 + 2.0 * uv;
  p.x += time * 0.125;
  vec2 pixelsRes = vec2(80.0, 25.0);
  tuv = floor(tuv * (pixelsRes * 6.0)) / (pixelsRes * 6.0);
  p = floor(p * pixelsRes) / pixelsRes;
  vec3 col = clouds(p * 3.0);
  vec3 oCol = col;
  vec3 g = gaussGrain(time) * 0.15;
  col += g;
  float gs = 2.0;
  float grid = (
    (mod(floor((uv.x) * resolution.x / gs), 2.0) == 0.0 ? 1.0 : 0.0) *
    (mod(floor((uv.y) * resolution.y / gs), 2.0) == 0.0 ? 1.0 : 0.0)
  );
  vec4 color = vec4(col, 1.0);
  vec4 layer1 = texture2D(eTexture1, vec2(tuv.x + time * 0.01, tuv.y));
  vec4 layer2 = texture2D(eTexture2, vec2(tuv.x + time * 0.02, tuv.y));
  vec4 layer3 = texture2D(eTexture3, vec2(tuv.x + time * 0.03, tuv.y));
  vec4 layer4 = texture2D(eTexture4, vec2(tuv.x + time * 0.05, tuv.y));
  tuv.x += 0.01 + sin(time + tuv.y * 15.0) * 0.003;
  tuv.y += 0.01 + sin(time + tuv.x * 25.0) * 0.003;
  vec4 layer5 = texture2D(eTexture5, vec2(tuv.x + time * 0.06, tuv.y));
  vec4 layer6 = texture2D(eTexture6, vec2(tuv.x + time * 0.06, tuv.y));
  color = mix(color, layer1, layer1.a);
  color = mix(color, layer2, layer2.a);
  color = mix(color, layer3, layer3.a);
  color = mix(color, layer4, layer4.a);
  color = mix(color, layer6, layer6.a);
  color = mix(color, layer5, layer5.a);
  color.x = float(int((color.x * 8.0) + 0.5)) * 0.125;
  color.y = float(int((color.y * 8.0) + 0.5)) * 0.125;
  color.z = float(int((color.z * 8.0) + 0.5)) * 0.125;
  color = clamp(color * color - grid * 0.1, 0.0, 1.0);
  color.xyz -= g * 0.5;
  gl_FragColor = color;
}

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

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

const float amount = 1.0;
const float saturation = 0.8;
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) {
  float reinhardAmount = 0.5 + fft * 0.6;
  float contrast = 0.7 + fft * 0.25;
  float brightness = 1.5 + fft;

  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 prgm1 = texture2D(prgm1Texture, uv);
  vec3 reinhard = filmicReinhard(prgm1.rgb);
  vec3 color = prgm1.rgb;
  color = mix(prgm1.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(prgm1.xyz, color, amount);
  color = clamp(color, 0.0, 1.0);
  gl_FragColor = vec4(color, 1.0);
}