// Public domain or CC0.

// This is a version of the parametric rose shader.
// This one uses the polar form, which could give you the
// distance to the outer shape, but you still need to sample
// points to see the entire curve, which is why this is slow.

#define PI acos(-1.)

vec2 toPolar(vec2 uv)
{
  // phi, r
  return vec2(atan(uv.y, uv.x), length(uv));
}

vec2 fromPolar(vec2 uv)
{
  return vec2(uv.y*cos(uv.x), uv.y*sin(uv.x));
}

float pRose(float a, float k, float theta)
{
  return a*sin(k*theta);
  // return a*cos(k*theta);
}

vec3 drawRose(vec3 color,vec2 uv,float a,float k,float t,vec3 pColor)
{
  float theta=PI*t; // 0<>12pi
  float d=pRose(a,k,theta); // rose
  vec2 pq=fromPolar(vec2(theta,d));

  if (length(vec2(uv.x-pq.y,uv.y-pq.x))<.02) // sphere
    color=+pColor; // combine colors

  return color;
}

void mainImage(out vec4 fragColor,in vec2 fragCoord)
{
  vec2 uv=(2.*fragCoord-iResolution.xy)/iResolution.y; // -1<>1
  uv*=1.2; // scale a bit

  vec3 r=vec3(1.,0.,0.);
  vec3 g=vec3(0.,1.,0.);
  vec3 b=vec3(0.,0.,1.);
  vec3 color=r;

  float a=1.;
  float eps=.005; // sampling
  float n=mod(iTime*.01,7.); // petals
  float d=9.-mod(iTime*.01,9.);
  float k=n/d;

  // sample a bunch of fixed points
  for (float t=0.;t<24.;t+=eps) {
    color+=drawRose(color,uv,a,k,t,b)-r;
  }

  // animate a rotating point
  {
    float t=mod(iTime*.2,24.);
    color+=drawRose(color,uv,a,k,t,g)-r;
  }

  fragColor=vec4(color,1.);
}
