#define TAU (6.283185307179586)
// https://shadertoyunofficial.wordpress.com/2019/01/02/programming-tricks-in-shadertoy-glsl/
#define cmod(Z)     length(Z)
#define carg(Z)     atan( (Z).y, (Z).x )
#define csqu(Z)     vec2( (Z).x*(Z).x-(Z).y*(Z).y, -2.0*(Z).x*(Z).y)
#define cmul(A,B) ( mat2( A, -(A).y, (A).x ) * (B) )  // by deMoivre formula
#define cinv(Z)   ( vec2( (Z).x, -(Z).y ) / dot(Z,Z) ) 
#define cdiv(A,B)   cmul( A, cinv(B) )
#define cpow(Z,v)   pol2cart( vec2( pow(cmod(Z),v) , (v) * carg(Z) ) )
#define cexp(Z)     pol2cart( vec2( exp((Z).x), (Z).y ) )
#define clog(Z)     vec2( log(cmod(Z)), carg(Z) )
#define cis(t)      vec2( cos(t), sin(t))

// Smooth frac
#define sf(x)     smoothstep( .1, .9-step(.4,abs(x-.5)) , x-step(.9,x))
#define sfract(x) sf(fract(x))
// Smooth HSV to RGB conversion (See https://www.shadertoy.com/view/MsS3Wc)
vec3 hsv2rgb( in vec3 c )
{
    vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 );
	rgb = rgb*rgb*(3.0-2.0*rgb); // cubic smoothing	
	return c.z * mix( vec3(1.0), rgb, c.y);
}
vec4 imagineColor(vec2 z){
    // Let's grab the angle and magnitude for the number
    float arg = atan(z.y, z.x);
    float mag = length(z);
    
    // We can base the Hue on the angle of the number,
    // and use a nice light Saturation. Full Value, so
    // we can be sure to see it nice and bright.
    vec3 hsv = vec3(arg/TAU,0.6,1.0);
    
    // But actually... it would be nice to know
    // where some special values are. You know, the 
    // integer Real, integer Imaginary; nice Magnitudes...
    // We'll carve out Blocks and Rings for those numbers
    // by multiplying our hsv by 0s.
    
    
    // First, figure out where the magnitude is a power of 2.
    // fract(x) ramps up from 0 to 1 repeatedly -- it's 
    // the same as mod(x,1), or the "fractional part" of
    // the number.
    float rings = fract(log2(mag));
    // ... but that's a bit too harsh of a ramp, so
    // we smooth it out. And then smooth it out again.
    	  rings = smoothstep(0.,0.4*2.,1.-abs(2.*rings-1.));
    	  rings = smoothstep(0.,0.8,rings);
    // c.f. https://www.desmos.com/calculator/xs5xqge9hj
    
    // I want my rings to be white, so I'll multiply
    // into the 'saturation' component of hsv.
    hsv.y *= rings;
    
    // To draw my blocks, I'll peak at the fractional 
    // part of each component. If I scale up by 2, I can
    // draw on the half-integer marks.
    vec2 blocks = fract(z*2.0);
    // Again, too wide a transition, so we'll compress it down.
    	 blocks = smoothstep(0.,0.05*2.,1.-abs(2.*blocks-1.));
    
    // The blocks will be black, so we'll multiply against
    // the 'value' component of hsv.
    hsv.z *= blocks.x*blocks.y;
    
    return vec4(hsv2rgb(hsv), 1.0);
}

// What function should we use?
vec2 myFun( in vec2 z){ // z^3 + 1 - c
    
    // Here's a simple constant to shift the function around.
    vec2 c = vec2(0.2, 0.1);
    // Vary with time for extra wow factor.
    c += vec2(0.4*cos(iTime), 0.6*sin(1.2*iTime));
    
    float a = z.x;
    float b = z.y;
    
    // (a+bi)*(a+bi)*(a+bi) = (a^3 + 3a^2*b+3a(b^2)+b^3
    return vec2(
        a*a*a-3.*a*b*b+1.-c.x,
        3.*a*a*b-b*b*b+c.y
        );
    // I did paste some helpful complex functions into "Common".
    // But this function was simple enough I didn't need them.
}


// The core of the program! For each pixel in fragCoord,
// we need to tell it how to compute a color by outputing
// to fragColor. The magic of shaders is that these computations
// will be done in parallel. Hooray for speed!
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Pick a math viewport.
    vec4 bounds = vec4(-1.5, 1.5,  //x min, x max
                       -1., 1.); //y min, y max
    vec2 brange = vec2(bounds.y-bounds.x, bounds.w-bounds.z);
    
    // Remap pixel coordinates to math viewport.
    vec2 uv = bounds.xz+brange*fragCoord/iResolution.xy;
    
    // Plug it in a color it.
    vec2 wz = myFun(uv);
    vec4 colInput = imagineColor(uv);
    vec4 colOutput = imagineColor(wz);
    //fragColor = (fragCoord.x < iMouse.x)? colInput : colOutput;
    fragColor = colOutput;
}
