#version 430 layout(local_size_x = 1, local_size_y = 1) in; #include #include #include #define PI 3.14159265358979323 uniform float hours = 0; uniform float minutes = 0; uniform float seconds = 0; uniform float time = 0; layout(rgba8) uniform readonly image2D noise_texture; layout(rgba8) uniform readonly image2D text_texture; layout(rgba8) uniform writeonly image2D output_image; uniform float antialiasing = 0.28; uniform bool enable_antialiasing = false; float sample_noise(in vec2 p) { vec4 noise = imageLoad(noise_texture, ivec2((p + 0.5) * imageSize(noise_texture))); return noise.x; } float blink_easing(in float x) { return x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2; } float digit(in vec2 uv, in int digit, in float size) { vec2 p = uv * 5000 / size; float digitSize = imageSize(text_texture).x / 10.; float digitOffset = digitSize * digit; p.x = clamp(p.x + digitOffset, digitOffset, digitOffset + digitSize); vec4 s = imageLoad(text_texture, ivec2(p)); return s.w; } vec3 image(in vec2 uv) { const vec3 eye_color = srgb(1, 1, 1); const vec3 iris_color = srgb(0.2, 0.1, 0.1); const vec3 pupil_color = srgb(0, 0, 0); const vec3 skin_color = srgb(0.14, 0.03, 0.14); // const vec3 skin_color = mix(srgb(0.94, 0.75, 0.65), vec3(0), 0.9); const vec3 bloodvessel_color = srgb(0.89, 0.12, 0.06); const vec3 clockdigit_color = mix(bloodvessel_color, vec3(0), 0.1); vec3 color = bloodvessel_color; { float eye = sdf_circle(uv, 0.41 * (1 - 0.08 * fbm(100 * uv))); vec3 eyeball_color = eye_color; float veins = sin((uv.y + 1) * 260 * sin((uv.x + 1) * 0.1) * fbm(uv * 20)) + 0.98; eyeball_color = mix(eyeball_color, bloodvessel_color, mix(0, step(veins, 0), clamp(sample_noise(uv) - 0.1, 0, 1))); eyeball_color = mix(eyeball_color, vec3(0), (0.2 - uv.x) * (1.3 - uv.y)); color = mix(color, eyeball_color, step(eye, 0)); } { float iris = sdf_circle(uv, 0.144); color = mix(color, iris_color, step(iris, 0)); float angle = 50 * (atan(uv.y, uv.x)) + 10.0 * fbm(uv * 100); float irispat = max(iris, sin(angle)); color = mix(color, vec3(0), 0.6 * step(irispat, 0)); } { float angle = PI / 2 - hours * PI / 6 - minutes * PI / (12 * 60); vec2 offset = 0.10 * vec2(cos(angle), sin(angle)); float iris_spec = sdf_circle((uv - offset) * vec2(0.8, 1.0), 0.010); color = mix(color, vec3(1), step(iris_spec, 0)); } { float angle = PI / 2 - minutes * PI / 30; vec2 offset = 0.148 * vec2(cos(angle), sin(angle)); float iris_spec = sdf_circle(uv - offset, 0.005); color = mix(color, iris_color, step(iris_spec, 0)); } { float pupil = sdf_circle(uv, 0.04); color = mix(color, pupil_color, step(pupil, 0)); } { // TODO: Switch to domain repetition for (int i = 0; i < 12; i++) { float theta = PI / 6.; float r = 0.17; vec2 digitpos = uv + vec2(0.011, 0.034) - r * vec2(cos(-i * theta + PI / 3), sin(-i * theta + PI / 3)); digitpos *= (1 + 0.8 * fbm(60 * uv)); float digit_size = 1.6; float s = 0; if (i + 1 >= 10) { s = digit(digitpos + vec2(0.01, 0), 1, digit_size); digitpos.x -= 0.01; } s = max(s, digit(digitpos, (i + 1) % 10, digit_size)); color = mix(color, clockdigit_color, s); } } float eye_open_factor = 0.092; float eyehole_factor = 0.136; float eyelid_size = 4; vec2 eyep = uv; { float blinkduration = 0.6; float blink_every = 8; float blinkt = mod(time, blink_every) * 2 / blinkduration; int should_blink = int(mod(time, blink_every) < blinkduration); float blink = blink_easing(mod(blinkt, 1)); blink = mix(1 - blink, blink, clamp(int(blinkt) % 2, 0., 1.)); float a = mix(0, eye_open_factor, mix(1, blink, should_blink)); float eyelid = a * cos(eyelid_size * eyep.x / 2 * PI) - abs(eyep.y) + a; float eyehole = eyehole_factor * cos((eyelid_size / 1.16) * eyep.x / 2 * PI) - abs(eyep.y) + eyehole_factor; vec3 eyelid_color = skin_color; vec3 patterning = mix(srgb(1, 0, 0), srgb(1, 0.46, 0), pow(sin(eyep.x * 16 + 100 * fbm(vec3(uv * 10, time / 20), 3)), 2)); float patnoise = smoothstep(-eyelid, 0, 0.028 * fbm(uv * 100)); eyelid_color = mix(eyelid_color, patterning, 1 - clamp(patnoise, 0, 1)); eyelid_color = mix(eyelid_color, vec3(0), 1 - step(eyelid + 0.004, 0)); color = mix(color, eyelid_color, step(eyelid, 0)); } return color; } vec3 antialiased_image(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; vec3 color = enable_antialiasing ? antialiased_image(uv) : image(uv); imageStore(output_image, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1)); }