uniform vec3 iForeground; const float pi = 3.14159265358979323846; float smoothstep(float a, float b, float x) { float t = clamp((x - a) / (b - a), 0.0, 1.0); return t * t * (3.0 - 2.0 * t); } float atan(float y, float x) { // Constants for the series expansion const float pi_2 = pi / 2.0; // Handle special cases if (x == 0.0) { if (y > 0.0) return pi_2; if (y < 0.0) return -pi_2; return 0.0; // Undefined, but return 0 } float abs_y = abs(y) + 1e-10; // Avoid division by zero // Compute the arctangent of y/x float angle; if (abs(x) > abs_y) { float z = y / x; float zz = z * z; angle = z * (0.999866 + zz * (-0.3302995 + zz * (0.180141 + zz * (-0.085133 + zz * 0.020835)))); if (x < 0.0) { if (y < 0.0) { angle -= pi; } else { angle += pi; } } } else { float z = x / y; float zz = z * z; angle = pi_2 - z * (0.999866 + zz * (-0.3302995 + zz * (0.180141 + zz * (-0.085133 + zz * 0.020835)))); if (y < 0.0) { angle -= pi; } } return angle; } vec4 main(vec2 fragCoord) { float radius = 0.3; float lineWidth = 2.0; // in pixels float glowSize = 3.0; // in pixels float pixelSize = 1.0 / min(iResolution.x, iResolution.y); lineWidth *= pixelSize; glowSize *= pixelSize; glowSize *= 2.0; vec2 uv = (fragCoord.xy / iResolution.xy) - 0.5; uv.x *= iResolution.x / iResolution.y; float len = length(uv); float angle = atan(uv.y, uv.x); float fallOff = fract(-0.5 * (angle / pi) - iTime * 0.5); lineWidth = (lineWidth - pixelSize) * 0.5 * fallOff; float color = smoothstep(pixelSize, 0.0, abs(radius - len) - lineWidth) * fallOff; color += smoothstep(glowSize * fallOff, 0.0, abs(radius - len) - lineWidth) * fallOff * 0.5; return vec4(color) * vec4(iForeground, iAlpha); }