// Ben Weston 2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
vec4 Noise( in vec2 x )
{
  vec2 p = floor(x);
  vec2 f = fract(x);
  f = f*f*(3.0-2.0*f);
  vec2 uv = p + f;
  vec4 rg = texture2D( iChannel0, (uv+0.5)/256.0);
  return rg;
}

float DistanceField( vec3 pos );

vec3 Normal( vec3 pos )
{
  const vec2 delta = vec2(0,.1);
  vec3 grad;
  grad.x = DistanceField( pos+delta.yxx )-DistanceField( pos-delta.yxx );
  grad.y = DistanceField( pos+delta.xyx )-DistanceField( pos-delta.xyx );
  grad.z = DistanceField( pos+delta.xxy )-DistanceField( pos-delta.xxy );
  return normalize(grad);
}


// ----------------------

float RippleHeight( vec2 pos )
{
  vec2 p = pos+vec2(-1,.2)*iGlobalTime;
  p += vec2(1,0)*Noise(p).y; // more natural looking ripples
  float f = Noise(p).x-.5;
  p *= 2.0;
  p += vec2(0,-.5)*iGlobalTime;
  f += (Noise(p).x-.5)*.2;
  p *= 2.0;
  p += vec2(-3,0)*iGlobalTime;
  f += (Noise(p).x-.5)*.05;
  return f*(1.0-exp2(-abs(pos.x)));
}

float DistanceField( vec3 pos )
{
  return (RippleHeight(pos.xy)-pos.z)*.5;
}

// map a uv space onto a distorted surface
vec2 UVMapping( vec2 target )
{
  // need to march vertically to absorb vertical creases, and horizontally for horizontal ones
  // cheat, by seperating these two
  vec2 uv = vec2(0);
  const int n = 16;
  vec2 d = target/float(n);
  vec2 l;
  l.x = RippleHeight( vec2(0,target.y) );
  l.y = RippleHeight( vec2(target.x,0) );
  for ( int i=0; i < n; i++ )
  {
    vec2 s;
    s.x = RippleHeight( vec2(d.x*float(i),target.y) );
    s.y = RippleHeight( vec2(target.x,d.y*float(i)) );
    uv += sign(d)*sqrt(pow(s-l,vec2(2.0))+d*d);
    l = s;
  }
  return (uv+vec2(0,1))/vec2(3.0,2.0);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
  vec3 ray;
  ray.xy    =  fragCoord.xy - iResolution.xy*.5;
  ray.z     =  iResolution.y;
  ray       =  normalize(ray);
  vec3 pos  =  vec3(1.65,0.0,-2.5);
  float t = 0.0;
  float h = 1.0;
  for ( int i=0; i < 10; i++ )
  {
    if ( h < .01 )
      break;
    float h = DistanceField( pos+t*ray );
    t += h;
  }
  pos += t*ray;
  vec2 uv = UVMapping( pos.xy );
  vec3 col = texture2D( iChannel1, uv ).rgb;
  float a = (1.0-smoothstep(.495,.5,abs(uv.x-.5)))*(1.0-smoothstep(.495,.5,abs(uv.y-.5)));
  vec3 normal = Normal( pos );
  float shade = max(0.1,dot(normal,normalize(vec3(-3,1,-2))))*sunLight;
  col = pow( col * shade, vec3(1./2.2) );
  fragColor = vec4(col,a);
}


