// CC0: Longer Cosmic
//  Inspired by Cosmic by Xor: https://www.shadertoy.com/view/msjXRK
//  I am a big fan of high saturated glowin colors.
//  So I really liked Cosmic by Xor.
//  Making short shaders isn't part of my skill set but I was
//  thinking I could maybe remove the need for loop for each ring.

#define TIME        iTime
#define RESOLUTION  iResolution
#define PI          3.141592654
#define PI_2        (0.5*PI)
#define TAU         (2.0*PI)

const float ringDistance= 0.05;
const float noOfRings   = 30.0;
const float glowFactor  = 0.005;

// License: MIT, author: Pascal Gilcher, found: https://www.shadertoy.com/view/flSXRV
float atan_approx(float y, float x) {
  float cosatan2 = x / (abs(x) + abs(y));
  float t = PI_2 - cosatan2 * PI_2;
  return y < 0.0 ? -t : t;
}

// License: CC0, author: Mårten Rånge, found: https://github.com/mrange/glsl-snippets
vec2 toPolar(vec2 p) {
  return vec2(length(p), atan_approx(p.y, p.x));
}

// License: MIT OR CC-BY-NC-4.0, author: mercury, found: https://mercury.sexy/hg_sdf/
float mod1(inout float p, float size) {
  float halfsize = size*0.5;
  float c = floor((p + halfsize)/size);
  p = mod(p + halfsize, size) - halfsize;
  return c;
}

// License: Unknown, author: Unknown, found: don't remember
float hash(float co) {
  return fract(sin(co*12.9898) * 13758.5453);
}

vec3 glow(vec2 pp, float h) {
  float hh = fract(h*8677.0);
  float b = TAU*h+0.5*TIME*(hh > 0.5 ? 1.0 : -1.0);
  float a = pp.y+b;
  float d = max(abs(pp.x)-0.001, 0.00125);
  return smoothstep(0.5*ringDistance, 0.2*ringDistance, d)*smoothstep(0.1, 1.0, cos(a))*(cos(a+b+vec3(0,1,2))+vec3(1.0))*glowFactor/d;
}

vec3 effect(vec2 p) {
  p += -0.1;
  // Didn't really understand how the original Cosmic produced the fake projection.
  // Took part of the code and tinkered
  p = (p*mat2(1,-1, 2, 2));
  p += vec2(0.0, 0.33)*length(p);

  vec2 pp = toPolar(p);
  vec2 pp0 = pp;
  float rn0 = mod1(pp0.x, ringDistance);
  vec2 pp1 = pp;
  pp1.x -= ringDistance*0.5;
  float rn1 = mod1(pp1.x, ringDistance);
  float d0 = abs(pp0.x);
  float d1 = abs(pp1.x);
  vec3 col = vec3(0.0);
  float h0 = hash(rn0*1E5+3.0);
  float h1 = hash(rn1+4.0);
  col += glow(pp0, h0)*step(1.0, rn0)*step(rn0, noOfRings);
  col += glow(pp1, h1)*step(rn1, noOfRings);
  return col;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
  vec2 q = fragCoord/iResolution.xy;;
  vec2 p = -1. + 2. * q;
  p.x *= RESOLUTION.x/RESOLUTION.y;
  vec3 col = vec3(0.0);
  col = effect(p);
  col = sqrt(col);
  fragColor = vec4(col, 1.0);
}
