version 7
const float gain = .5;
const int   noctaves = 5;
const float cumulus =1.5;
uniform vec4  campos;
uniform vec4  sunDir;   // .w=color
uniform vec4  clas;    //  cloudness,lacunarity,alpha,size
uniform vec4  hcloud; //  relative clouds_height , clouds_thickness, clouds_height ,xnorm
#define   xnorm            hcloud.w
#define   clouds_thickness hcloud.y
#define   nlayers          campos.w
#define   lacunarity       clas.y   // 2.0;3.2
#define   csize            clas.w  //  90.0e-6
#define   color            sunDir.w

in  vec2 worldP;
flat in vec3 ssColor;
out vec4 fragcolor;

float noise(vec3 x)
{
  vec3 f = fract(x);
  vec3 p = floor(x);

	f = f*f*(3.0-2.0*f);
  vec2 uv = vec2(37.0,17.0)*p.z + f.xy + p.xy;
  vec2 rg = texture( noiseSampler,uv/256.0).yx;
	return mix( rg.x, rg.y, f.z );
}

vec4 cloudColor(vec2 v,float inv_cloudness)
{
 vec3 scale = vec3(vec2(csize),0.92e-4); //  scale.z = 1.99e-4 for Cumulus clouds, 4.99e-4 for Spindrift clouds
 vec3 dir  = normalize(vec3(v.xy,hcloud.x));
 dir      *= 1.0/max(abs(dir.z),0.01);
 vec3   vx = vec3(v.xy,hcloud.z) + dir*clouds_thickness;
 vx.xy    += campos.xy;
 vx       *=scale;
 float clouds_step =  clouds_thickness/nlayers;
 vec3 step = dir*(-clouds_step*scale);
 float   L = 0.0,T = 0.0;
 for (float j = 0.0; j<nlayers; j++,vx+=step)
 {
  vec3  st=vx;
  float  r=0.0,g = 1.0;
  for (int i = 0; i < noctaves; i++ )
  {
   float n =  noise(st);
   r    -= g * (inv_cloudness * n - 1.0);
   g    *= gain;
   st   *= lacunarity;
  }
  r      =clamp(r, 0.0, 1.0);
  T     +=r;
  L      =mix(L,r,r);
 }
 vec3 extinction;
 vec3 inscatter = inScattering(vec3(0.0,0.0,campos.z + earthPos.z), vec3(0.0,0.0,hcloud.z + earthRadius), sunDir.xyz, extinction);
 return vec4(clamp(L, 0.0, 1.0) * ssColor * extinction + inscatter, clamp(T*(cumulus*xnorm/nlayers),0.0,1.0));
}


void main()
{
 vec4    col = cloudColor(worldP,4.0-clas.x*2.0);
 float    aa = min(1.0,col.a*clas.z);
 if (aa<0.005) discard;
 fragcolor= vec4(hdr(col.rgb) * color,aa);
}




