 //---  Galaxy --- Fabrice NEYRET  august 2013

const float RETICULATION = 3.;  // strenght of dust texture
const float NB_ARMS = 5.;       // number of arms
const float COMPR = .05;         // compression in arms
const float SPEED = .1;
const float GALAXY_R = 1./2.;
const float BULB_R = 1./4.;
const vec3 GALAXY_COL = vec3(.9,.9,1.); //(1.,.8,.5);
const vec3 BULB_COL   = vec3(1.0,.8,.8);
const vec3 SKY_COL    = .5*vec3(.0,.0,.0);

#define Pi 3.1415927
	float t = iGlobalTime;

// --- base noise
float tex(vec2 uv)
{
	return texture2D(iChannel0,uv, 0.).r;
}


// --- perlin turbulent noise + rotation
float noise(vec2 uv)
{
	float v=0.;
	float a=-SPEED*t,	co=cos(a),si=sin(a);
	mat2 M = mat2(co,-si,si,co);
	const int L = 7;
	float s=1.;
	for (int i=0; i<L; i++)
	{
		uv = M*uv;
		float b = tex(uv*s);
		v += 1./s* pow(b,RETICULATION);
		s *= 2.;
	}

    return v/2.;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 uv = fragCoord.xy*2./iResolution.y-vec2(1.,1.);
	vec3 col;

	// spiral stretching with distance
	float rho = length(uv); // polar coords
	float ang = atan(uv.y,uv.x);
	float shear = 2.*log(rho); // logarythmic spiraa11l
	float c = cos(shear), s=sin(shear);
	mat2 R = mat2(c,-s,s,c);

	// galaxy profile
	float r; // disk
	r = rho/GALAXY_R; float dens = exp(-r*r);
	r = rho/BULB_R;	  float bulb = exp(-r*r);
	float phase = NB_ARMS*(ang-shear);
	// arms = spirals compression
	ang = ang-COMPR*cos(phase)+SPEED*t;
	uv = rho*vec2(cos(ang),sin(ang));
	// stretched texture must be darken by d(new_ang)/d(ang)
	float spires = 1.+NB_ARMS*COMPR*sin(phase);
	dens *= .7*spires;

	// gaz texture
	float gaz = noise(.09*1.2*R*uv);
	float gaz_trsp = 1./1.7;

	// stars
	// adapt stars size to display resolution
  float ratio = .4*iResolution.y/textureSize(iChannel0,0).y;
	float stars1 = texture2D(iChannel1,ratio*uv+.5, 0.).r, // M*uv
	      stars2 = texture2D(iChannel0,ratio*uv+.5, 0.).r,
		  stars = pow(1.-(1.-stars1)*(1.-stars2),5.);

	// mix all
	col = mix(SKY_COL,
			  gaz_trsp*(1.7*GALAXY_COL) + 1.2*stars,
			  dens);
	col = mix(col, 1.2*BULB_COL, bulb);

  fragColor.rgb = col.rgb;
  fragColor.a   = dens*4.0;
}
