aboutsummaryrefslogtreecommitdiff
path: root/src/main/resources/shaders/kaleidos.glsl
blob: 689d80696055df02016feb2721623b51b547049c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#version 430
layout(local_size_x = 1, local_size_y = 1) in;

#include <utils>
#include <sdf>
#include <noise>

uniform float seconds = 0;
layout(rgba8) uniform writeonly image2D output_image;

uniform float antialiasing = 0.28;
uniform bool enable_antialiasing = false;

int sections = 6;

float noisepattern(vec2 p, float t) {
  return fbm(vec3(p + fbm(p * fbm(p / 5)), t), 3) - 0.30;
}

vec3 bg_color = srgb(0.17, 0.17, 0.19);
vec3 patbg_color = srgb(0.15, 0.20, 0.22);
vec3 pat1_color = patbg_color;
vec3 pat2_color = srgb(0.10, 0.29, 0.29);
vec3 pat3_color = srgb(0.35, 0.16, 0.23);
vec3 hexhighlight_color = srgb(0.2, 0.3, 0.2);

void kaleidos(in vec2 p, inout vec3 color) {
  float tilt = PI / sections;
  vec2 pp1 = p * mat2x2(cos(tilt), -sin(tilt), sin(tilt), cos(tilt));
  vec2 pp2 = p * mat2x2(cos(-tilt), -sin(-tilt), sin(-tilt), cos(-tilt));
  float cutoff = 1 - step(min(-pp2.y, pp1.y), 0);

  float lines = min(pp1.y, -pp2.y);
  color = mix(color, bg_color, step(abs(lines) - 0.002, 0));

  if (cutoff <= 0.) return;

  { // background pat
    float speed = 0.25;
    float dur = 20.;
    float t = mod(seconds, dur);
    int dir = int((t / dur) * 2.);
    t = (dir == 0 ? t : dur - t) * speed;
    vec2 patp = (p - vec2(0.2)) * 20;
    float pat = sin(patp.x * patp.x) - sin(patp.y * patp.y) - cos(t * patp.x * patp.y) * sin(patp.y);
    color = mix(color, patbg_color, step(pat, 0));
  }
  { // specs
    float t = seconds / 2.2;
    color = mix(color, pat1_color, step(noisepattern(p * 60 + 100, t), 0));
    float pat2 = noisepattern(p * 40 + 11, t + 1.1) - 0.04;
    color = mix(color, pat2_color, step(pat2, 0));
    color = mix(color, mix(pat2_color, vec3(0), 0.2), step(pat2, -0.1));
    float pat3 = noisepattern(p * 20, t);
    color = mix(color, pat3_color, step(pat3, 0));
    color = mix(color, mix(pat3_color, vec3(0), 0.1), step(pat3, -0.05));
  }
}

vec3 image(in vec2 uv) {
  vec3 color = bg_color;

  vec2 p = uv;

  float del = 2. * PI / sections;
  float theta = atan(p.y, p.x);
  float id1 = floor(theta / del);
  float id2 = id1 + 1.;
  vec2 p1 = mat2(cos(del * id1), -sin(del * id1), sin(del * id1), cos(del * id1)) * p;
  vec2 p2 = mat2(cos(del * id2), -sin(del * id2), sin(del * id2), cos(del * id2)) * p;
  bool inverted = int(id1) % 2 == 0;
  if (inverted)
    p1.y = -p1.y;
  else
    p2.y = -p2.y;

  kaleidos(p1, color);
  kaleidos(p2, color);

  return color;
}

vec3 antialiased_image(in vec2 uv) {
  vec2 resolution = vec2(imageSize(output_image).xy);
  float s = antialiasing / max(resolution.x, resolution.y);
  vec3 sum = vec3(0);
  int count = 0;
  for (int i = -2; i < 2; i++)
    for (int j = -2; j < 2; j++, count++)
      sum += image(uv + vec2(i, j) * s);
  return sum / count;
}

void main() {
  vec2 resolution = vec2(imageSize(output_image).xy);
  float aspect_ratio = resolution.y / resolution.x;
  vec2 uv = (gl_GlobalInvocationID.xy - resolution / 2) * vec2(1.0, aspect_ratio) / resolution;

  float t = seconds / 3;
  vec2 offset = vec2(mod(t * sin(t * 8), 0.02), 0);

  float tilt = 0, scale = 1.0;
  float div1 = mod(t * 10, 17);
  int s1 = 7, s2 = 15;
  bool gshake = int(div1) == s1 || int(div1) == s2;
  tilt = mix(tilt, PI / 3, ease_in_out_quart(smoothstep(s1 + 1, s1 + 2, div1)));
  scale = mix(scale, 1.3, ease_in_out_quart(smoothstep(s1 + 1, s1 + 1.5, div1)));
  scale = mix(scale, 1, ease_in_out_quart(smoothstep(s1 + 1.5, s1 + 2, div1)));
  tilt = mix(tilt, PI / 2, step(div1, s2 + 2) * smoothstep(s1 + 1, 30, div1));
  tilt = mix(tilt, 0, ease_in_out_quart(smoothstep(s2 + 1, s2 + 2, div1)));
  scale = mix(scale, 1.3, ease_in_out_quart(smoothstep(s2 + 1, s2 + 1.5, div1)));
  scale = mix(scale, 1, ease_in_out_quart(smoothstep(s2 + 1.5, s2 + 2, div1)));

  float saturate = smoothstep(s1 + 2, s2, div1);

  uv *= mat2x2(cos(tilt), -sin(tilt), sin(tilt), cos(tilt));
  uv *= scale;

  vec3 color = enable_antialiasing ? antialiased_image(uv) : image(uv);

  if (int(t * 5) % 20 == 5) {
    color.r = (color.r + image(uv + offset).r / 2 + image(uv - offset).r / 2) / 2.;
    color.b = (color.b + image(uv + vec2(offset.y, offset.x)).b + image(uv - offset).b) / 3.;
  } else if (gshake) {
    color.g = (color.g + image(uv + offset).g / 2 + image(uv - offset).g / 2) / 2.;
  }
  color.r *= (0.7 + saturate);

  imageStore(output_image, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1));
}