
float hash(vec2 uv) {
  // added terms till it looked okay
  vec3 p3  = mod(uv.xyx * vec3(345.23,234.1,465.745),vec3(2,3,5));
  p3 += dot(p3, p3.yzx + 34.19);
  return fract((p3.x + p3.y) * p3.z);
}

float n2(vec2 st) {
  	vec2 i=floor(st-.5);
    vec2 f=fract(st-.5);
    f = f*f*f*(f*(f*6.0-15.0)+10.0);
    float rt=mix(hash(i),hash(i+vec2(1.,0.)),f.x);
    float rb=mix(hash(i+vec2(0.,1.)),hash(i+vec2(1.,1.)),f.x);
    return mix(rt,rb,f.y);
}

float sky(vec2 uv) {
  //return length(rd.xy);
  //vec2 uv=rd.xz*0.1;
  float val=0.;
  
  float amp=0.75;
  
  for (float i=1.; i < 13.; ++i) {
    val += n2(vec2(0.4,0.1)*iTime*i/20.+ uv * 20. / i) / 2. * pow(i,0.25)*amp;
    amp *= 0.5;
    uv *= -4.5;
    uv += vec2(0.3,0.4)*0.15*(iTime*amp);
  }
  return val;
}

float map(vec3 p) {
  float erf=length(p)-93.;
  return min(100.-length(p),erf);
}

vec3 moonpos=vec3(450.,520.,2750.);

float moonmap(vec3 ro, vec3 rd, out vec3 normal) {
  float t = dot(moonpos-ro,rd);
  float r = 50.;
  vec3 p = ro + rd * t;
  float y = length(moonpos-p);
  float x = sqrt(r*r-y*y);
  normal = normalize(p-rd*x-moonpos);
  return y - r;
}

vec3 gn(vec3 p) {
  vec2 e=vec2(0.001,0.);
  return normalize(map(p) - vec3(map(p-e.xyy),map(p-e.yxy),map(p-e.yyx)));
}

void addRain(inout vec3 col, vec3 ro, vec3 rd) {
  for (int i=1; i < 5; ++i ) {
    if (rd.y<-1.+float(i)/5.) continue;
    vec2 uv = (ro+rd*float(i)*10.).xy;
    uv.x-=iTime*0.3;
    uv.y+=iTime*3.;
    float strength = 0.2;
    
    float rain = n2( vec2(uv.x*20.1, uv.y*40.1+uv.x*400.1-20.*strength ));
    float rain2 = n2( vec2(uv.x*45.+iTime*0.5, uv.y*30.1+uv.x*200.1 ));	
    rain = strength-rain;
    rain+=rain2*(sin(strength)-0.4)*2.;
    rain = clamp(rain, 0.,0.5)*0.5;
    col += rain*0.2;
  }
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 uv = (fragCoord.xy - 0.5*iResolution.xy) / iResolution.y;
	vec3 rd=normalize(vec3(uv,3));
  
  vec3 ro=vec3(0,93,-30.);
  float d,t=0.;
  
  for (int i=0; i<100; ++i) {
    d = map(ro+rd*t);
    if (d <0.01) break;
    t += d;
  }
  vec3 fogcol=vec3(0.1,0.1,0.13)*0.021;
  vec3 col =fogcol;
  
  
    vec3 p=ro+rd*t;
  
  vec3 ld=normalize(vec3(1.,3.,-15.));
  float lightningamount = pow(smoothstep(0.3,0.67,sky(vec2(iTime*0.1))),1.)*10. ;
  fogcol += 0.001*lightningamount;
  
  if (d <0.01) {
      if (length(p) > 96.) {
      float u= atan(p.x,p.t);
      float v= atan(p.y,p.z);
      //u *=10;
      //v *=10;
      
      //float val=mod(floor(u)+floor(v),2);
      vec2 skyuv = vec2(u,v);
      float val=sky(skyuv*2.1)*sky(skyuv*1.4);
      vec3 moonn;
      float mwn = moonmap(ro,rd, moonn);
      float mwncol = 0.;
      float mwnglo = smoothstep(120.,0.,pow(mwn,1.))*4.;
      if (mwn<0.) {
        vec3 sund = normalize(vec3(-60.,0.,99.));
        mwncol = clamp(smoothstep(0.1,0.,mwn)*dot(moonn,sund),0.,1.)*5.;
      }
      mwnglo += 1.;
      col=mwnglo*val*vec3(0.5,0.5,0.969)*smoothstep(0.,1.,clamp(uv.y,0.,1.))*val*3.6+ vec3(0.01,0.04,0.23)*.2;
      col += mwncol;
      //col += mwnglo*0.2;
        
      float lightning = pow(sky(skyuv*vec2(1.2,1.2)),6.);
      lightning *= lightningamount;
      col *=0.5+4.*lightning;
    }
    else {
      col = vec3(0.01,.4,0.1)*0.1;
      col *= 0.1 + 0.1*dot(ld,gn(p));
    }
  }
  float dp = p.z;
  
  addRain(col,ro,rd);
  
  col=mix(fogcol+col,col,exp(-0.0001*t*t*t));
  col = pow(col,vec3(0.4545));
	fragColor = vec4(col, 1.);
}