void blend(inout vec4 base, vec4 overlay) {
base.rgb = mix(base.rgb, overlay.rgb, overlay.a);
}
float circle(vec2 p, vec2 center, float radius) {
return 1.0 - smoothstep(radius - 0.01, radius 0.01, length(p - center));
}
float patternCircle(vec2 p, vec2 center, float radius) {
float d = length(p - center);
// Create alternating rings using distance
float rings = fract(d * 30.0); // frequency of rings
float pattern = step(0.5, rings); // alternate 0/1 pattern
// Mask pattern inside circle radius (inner ring)
float mask = circle(p, center, radius);
float finalPattern = pattern * mask;
return finalPattern;
}
float radialGradient(vec2 p, vec2 center, float radius) {
float d = length(p - center);
return 1.0 - smoothstep(0.0, radius, d);
}
float specular(vec2 p, vec2 center, vec2 lightPos, float intensity) {
vec2 toLight = normalize(lightPos - p);
vec2 toCenter = normalize(center - p);
float spec = max(0.0, dot(toLight, toCenter));
return pow(spec, intensity);
}
float rimLight(vec2 p, vec2 center, float radius, float thickness) {
float d = length(p - center);
float rim = smoothstep(radius - thickness, radius, d) *
smoothstep(radius 0.02, radius, d);
return rim;
}
float diffuse(vec2 p, vec2 center, vec2 lightPos) {
vec2 toLight = normalize(lightPos - p);
vec2 normal = normalize(p - center);
return max(0.3, dot(normal, toLight));
}
vec2 rotate(vec2 p, float angle) {
float c = cos(angle);
float s = sin(angle);
return vec2(c * p.x - s * p.y, s * p.x c * p.y);
}
float tickMark(vec2 p, float angle, float innerRadius, float outerRadius, float width) {
vec2 rp = rotate(p, -angle);
float d = length(rp);
float radialMask = step(innerRadius, d) * step(d, outerRadius);
float angularMask = step(abs(rp.x), width);
return radialMask * angularMask;
}
float allTickMarks(vec2 p, vec2 lightPos) {
float marks = 0.0;
float PI = 3.14159265359;
for(int i = 0; i < 12; i ) {
float angle = float(i) * PI * 2.0 / 12.0;
float tick = tickMark(p, angle, 0.55, 0.68, 0.015);
marks = max(marks, tick);
}
for(int i = 0; i < 60; i ) {
if(mod(float(i), 5.0) != 0.0) {
float angle = float(i) * PI * 2.0 / 60.0;
float tick = tickMark(p, angle, 0.60, 0.68, 0.006);
marks = max(marks, tick);
}
}
return marks;
}
float rectangle(vec2 p, vec2 center, vec2 size) {
vec2 d = abs(p - center) - size * 0.5;
float dist = length(max(d, 0.0)) min(max(d.x, d.y), 0.0);
return 1.0 - smoothstep(-0.005, 0.005, dist);
}
float dropShadow(vec2 p, vec2 center, float radius, vec2 offset, float softness) {
float d = length(p - center - offset);
return 1.0 - smoothstep(radius, radius softness, d);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// [-1, 1]
vec2 uv = (2.0 * fragCoord.xy - iResolution.xy) / iResolution.y;
float speed = 0.5;
float angle = iTime * speed;
vec2 puv = rotate(uv, angle);
vec2 lightPos = vec2(-0.3, 0.4);
float shadow = dropShadow(uv, vec2(0.0), 0.7, vec2(0.02, -0.02), 0.15);
float c1 = circle(puv, vec2(0.0), 1.0 * 0.7);
float c2 = circle(puv, vec2(0.0), 1.0 * 0.5);
float c2Diffuse = diffuse(puv, vec2(0.0), lightPos) * c2;
float c3 = patternCircle(puv, vec2(0.0), 1.0 * 0.5);
float c3Gradient = radialGradient(puv, vec2(0.0), 1.0 * 0.5) * c3;
float disk = circle(puv, vec2(0.0), 1.0 * 0.3);
float diskDiffuse = diffuse(puv, vec2(0.0), lightPos) * disk;
float ticks = allTickMarks(puv, lightPos);
float tickGradient = radialGradient(puv, vec2(0.0), 0.7) * ticks;
float tickSpec = specular(puv, vec2(0.0), lightPos, 40.0) * ticks;
float indicatorDisk = circle(puv, vec2(0.0), 0.08);
float indicatorDiskDiffuse = diffuse(puv, vec2(0.0), lightPos) * indicatorDisk;
float directionRect = rectangle(puv, vec2(0.0, 0.03), vec2(0.02, 0.08));
// basee
fragColor = vec4(1.0, 1.0, 1.0, 1.0);
blend(fragColor, vec4(0.0, 0.0, 0.0, shadow * 0.3));
blend(fragColor, vec4(0.0, 0.0, 0.0, c1));
vec3 tickColor = mix(vec3(0.7, 0.7, 0.75), vec3(0.95, 0.95, 1.0), tickGradient * 0.8);
blend(fragColor, vec4(tickColor, ticks));
blend(fragColor, vec4(1.0, 1.0, 1.0, tickSpec * 0.7));
vec3 c2Color = vec3(0.2, 0.2, 0.2) * c2Diffuse;
blend(fragColor, vec4(c2Color, c2));
vec3 c3Color = mix(vec3(0.25, 0.25, 0.28), vec3(0.45, 0.45, 0.48), c3Gradient);
float c3Spec = specular(puv, vec2(0.0), lightPos, 20.0) * c3;
blend(fragColor, vec4(c3Color, c3));
blend(fragColor, vec4(0.9, 0.9, 1.0, c3Spec * 0.6));
vec3 diskColor = vec3(0.4, 0.4, 0.4) * diskDiffuse;
blend(fragColor, vec4(diskColor, disk));
vec3 indicatorDiskColor = vec3(0.5, 0.5, 0.5) * indicatorDiskDiffuse;
blend(fragColor, vec4(indicatorDiskColor, indicatorDisk));
blend(fragColor, vec4(0.3, 0.3, 0.3, directionRect));
}