// https://www.shadertoy.com/view/Xs3fR4
uniform float u_time = 0.0;
uniform float eddy_scale = 50.0;
out vec4 color_out;
// variant of Vorocracks: https://shadertoy.com/view/lsVyRy
// integrated with cracks here: https://www.shadertoy.com/view/Xd3fRN

#define MM 0

#define VARIANT 1         // 1: amplifies Voronoi cell jittering
#if VARIANT
   float ofs = .5;        // jitter Voronoi centers in -ofs ... 1.+ofs
#else
   float ofs = 0.;
#endif

//int FAULT = 1;          // 0: crest 1: fault

float RATIO = 1.,         // stone length/width ratio
/*  STONE_slope = .3,      // 0.  .3  .3  -.3
   STONE_height = 1.,      // 1.  1.  .6   .7
   profile = 1.,         // z = height + slope * dist ^ prof
 */
   CRACK_depth = 3.,
   CRACK_zebra_scale = 1.,  // fractal shape of the fault zebra
   CRACK_zebra_amp = .67,
   CRACK_profile = 1.,     // fault vertical shape  1.  .2
   CRACK_slope = 50.,      //                 10.  1.4
   CRACK_width = .0;


// std int hash, inspired from https://www.shadertoy.com/view/XlXcW4
vec3 hash3( uvec3 x )
{
#   define scramble  x = ( (x>>8U) ^ x.yzx ) * 1103515245U // GLIB-C const
   scramble; scramble; scramble;
   return vec3(x) / float(0xffffffffU) + 1e-30; // <- eps to fix a windows/angle bug
}

// === Voronoi =====================================================
// --- Base Voronoi. inspired by https://www.shadertoy.com/view/MslGD8

#define hash22(p)  fract( 18.5453 * sin( p * mat2(127.1,311.7,269.5,183.3)) )
#define disp(p) ( -ofs + (1.+2.*ofs) * hash22(p) )

vec3 voronoi( vec2 u )  // returns len + id
{
   vec2 iu = floor(u), v;
   float m = 1e9,d;
#if VARIANT
   for( int k=0; k < 25; k++ ) {
      vec2  p = iu + vec2(k%5-2,k/5-2),
#else
   for( int k=0; k < 9; k++ ) {
      vec2  p = iu + vec2(k%3-1,k/3-1),
#endif
         o = disp(p),
         r = p - u + o;
         d = dot(r,r);
      if( d < m ) m = d, v = r;
   }

   return vec3( sqrt(m), v+u );
}

// --- Voronoi distance to borders. inspired by https://www.shadertoy.com/view/ldl3W8
vec3 voronoiB( vec2 u )  // returns len + id
{
   vec2 iu = floor(u), C, P;
   float m = 1e9,d;
#if VARIANT
   for( int k=0; k < 25; k++ ) {
      vec2 p = iu + vec2(k%5-2,k/5-2),
#else
   for( int k=0; k < 9; k++ ) {
      vec2   p = iu + vec2(k%3-1,k/3-1),
#endif
            o = disp(p),
            r = p - u + o;
      d = dot(r,r);
      if( d < m ) m = d, C = p-iu, P = r;
   }

   m = 1e9;

   for( int k=0; k < 25; k++ ) {
      vec2   p = iu+C + vec2(k%5-2,k/5-2),
            o = disp(p),
            r = p-u + o;

      if( dot(P-r,P-r)>1e-5 )
      m = min( m, .5*dot( (P+r), normalize(r-P) ) );
   }

   return vec3( m, P+u );
}

// === pseudo Perlin noise =============================================
#define rot(a) mat2(cos(a),-sin(a),sin(a),cos(a))
int MOD = 1;  // type of Perlin noise

// --- 2D
#define hash21(p) fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453123)
float nnoise2(vec2 p) {
   vec2 i = floor(p);
   vec2 f = fract(p); f = f*f*(3.-2.*f); // smoothstep

   float v= mix( mix(hash21(i+vec2(0,0)),hash21(i+vec2(1,0)),f.x),
      mix(hash21(i+vec2(0,1)),hash21(i+vec2(1,1)),f.x), f.y);
   return MOD==0 ? v
      : MOD==1 ? 2.*v-1.
      : MOD==2 ? abs(2.*v-1.)
      : 1.-abs(2.*v-1.);
}

float fbm2(vec2 p) {
   float v = 0.,  a = .5;
   mat2 R = rot(.37);

   for (int i = 0; i < 9; i++, p*=2.,a/=2.)
      p *= R,
      v += a * nnoise2(p);

   return v;
}
#define nnoise22(p) vec2(nnoise2(p),nnoise2(p+17.7))
vec2 fbm22(vec2 p) {
   vec2 v = vec2(0);
   float a = .5;
   mat2 R = rot(.37);

   for (int i = 0; i < 6; i++, p*=2.,a/=2.)
      p *= R,
      v += a * nnoise22(p);

   return v;
}
vec2 mfbm22(vec2 p) {  // multifractal fbm
   vec2 v = vec2(1);
   float a = .5;
   mat2 R = rot(.37);

   for (int i = 0; i < 6; i++, p*=2.,a/=2.)
      p *= R,
      //v *= 1.+nnoise22(p);
      v += v * a * nnoise22(p);

   return v-1.;
}

/*
// --- 3D
#define hash31(p) fract(sin(dot(p,vec3(127.1,311.7, 74.7)))*43758.5453123)
float noise3(vec3 p) {
   vec3 i = floor(p);
   vec3 f = fract(p); f = f*f*(3.-2.*f); // smoothstep

   float v= mix( mix(
      mix(hash31(i+vec3(0,0,0)),hash31(i+vec3(1,0,0)),f.x),
      mix(hash31(i+vec3(0,1,0)),hash31(i+vec3(1,1,0)),f.x), f.y),
      mix( mix(hash31(i+vec3(0,0,1)),hash31(i+vec3(1,0,1)),f.x),
      mix(hash31(i+vec3(0,1,1)),hash31(i+vec3(1,1,1)),f.x), f.y), f.z);
   return
      MOD==0 ? v
         : MOD==1 ? 2.*v-1.
         : MOD==2 ? abs(2.*v-1.)
            : 1.-abs(2.*v-1.);
}

float fbm3(vec3 p) {
   float v = 0.,  a = .5;
   mat2 R = rot(.37);

   for (int i = 0; i < 9; i++, p*=2.,a/=2.)
      p.xy *= R, p.yz *= R,
      v += a * noise3(p);

   return v;
}
*/

// ======================================================

vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
{
   vec4 O;
   vec2 U;

   U = screen_coords / eddy_scale / 10.;

   //U *= 4./iResolution.y;
   //U.x += iTime;                           // for demo
   U *= 4.;
   U.x += u_time;
   // O = vec4( 1.-voronoiB(U).x,voronoi(U).x, 0,0 );  // for tests
   vec2 I = floor(U/2.);
   bool vert = mod(I.x+I.y,2.)==0.;          //if (vert) U = U.yx;
   vec3 H0;
   O-=O;

   for(float i=0.; i<CRACK_depth ; i++) {
      vec2 V =  U / vec2(RATIO,1),           // voronoi cell shape
         D = CRACK_zebra_amp * fbm22(U/CRACK_zebra_scale) * CRACK_zebra_scale;
      vec3  H = voronoiB( V + D ); if (i==0.) H0=H;
      float d = H.x;                         // distance to cracks
         //  r = voronoi(V).x,               // distance to center
         //  s = STONE_height-STONE_slope*pow(r,profile);// stone interior
                                             // cracks
      d = min( 1., CRACK_slope * pow(max(0.,d-CRACK_width),CRACK_profile) );

      O += vec4(1.-d) / exp2(i);
      U *= 1.5 * rot(.37);
   }
   /*
   O = vec4(
      FAULT==1 ? d * s                       // fault * stone
         : mix(1.,s, d)                      // crest or stone
         ); */
   if (vert) O = 1.-O; O *= vec4(.9,.85,.85,1);   // for demo

#if MM
   O.g = hash3(uvec3(H0.yz,1)).x;
#endif
   return O;
}
