attribute vec4 pos;
attribute vec2 tex; 

varying vec2 tc;
varying float visibility; 
varying vec4 color; 
varying float unique; 

uniform vec3 eyePos; 
uniform mat4 viewproj; 
uniform mat4 view; 
uniform mat4 tview;
uniform mat4 world;
uniform vec3 dynLightPos;

uniform float time; 
uniform int flip=0; 

float rand( vec2 n ) {
   return fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
}

vec2 rotZ(vec2 p, float rad)
{
   mat2 r; 
   r[0] = vec2(cos(rad), -sin(rad));
   r[1] = vec2(sin(rad), cos(rad));
   return p*r;
}   

float farPlane = 120.0;
float focalPoint = 00.0;
float exponent = 1.0; 

float d(vec3 p) {
	float l = (abs(length(p-eyePos)-focalPoint))/farPlane;
	return clamp(1.0, 0.0, pow(l, exponent));
}

float fog_mul = 1.0;
float fogf(vec3 p) {
	float l = (abs(length(p-eyePos)))/farPlane;
	return clamp(1.0, 0.0, fog_mul*(1.0-.3*pow(l, exponent)));
}


void main()
{	
	/* Calculate Billboard */
	vec4 center = vec4((pos.xy-.50)*2.0, 0.0, 1.0); 
	vec4 bboard = 30.0*(center.x*tview[0]+center.y*tview[1]);
	bboard = 40.0*vec4(center.xy, 0.0, 1.0);


	/* Compute Position */
	float s = pos.z;  										// unique identifier
	float x = 3000.0*rand(vec2(s, s))-1500;
	x = 0;
	float y = 250.0;//40+400*rand(vec2(s, s*232.3+3.2));
	float z = rand(vec2(s+2.32, 43.3))+time;
	z = s/10.0+time*.25;

	y =  0.0;//200.0;
	float adjZ = z-floor(z);
	adjZ = (adjZ-.5f)*4000.0;
	vec4 uPos = vec4(x,y,adjZ, 1.0);

	vec4 particlePos = uPos+bboard;
	gl_Position = viewproj*world*vec4(particlePos.xyz, 1.0);

	/* Compute TexCoords */ 
	tc = tex;
	//float type = (pos.z/4.0-floor(pos.z/4.0))*4.0;
	//tc = vec2(tex.x, tex.y/4.0+type*.25);

	/* Fog */
	float fog = 1.0-min(1.0, pow(length(uPos-eyePos)/2500.0, .5275));
	float verticalGrad = min(1.0, pow(uPos.y/100.0, 1.20));
	float blinc = .5+.5*sin(s+time*4.0);
	visibility	= blinc*fog*verticalGrad*1.0*rand(vec2(s, s)); 
	//visibility = rand(vec2(s*23.32+2.3, s));

	color = vec4(fog);
	unique = pos.z*.01;
	//unique = 1.0;
}	

//FRAGMENT
uniform float time; 

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

float crand(float r, float seed)
{
	return .5+.5*sin(seed*r*r*23.23242+seed*seed+seed);
}
vec2 kmod(float x, float y) 
{
    float ix = fract(x*y); 
    float iy = floor(y*x);
    return vec2(ix,iy); 
}

// Ciruclar Object 
float generateObject(vec2 uv, float u, float t)
{
	// Globals
	vec2 localUV = uv-.5;              // set 0 in center
	float radius = length(localUV);

	// Create Radial Layers
	float nLayers = 8.0+4.0*crand(u, 23.4);;  
    float layerGrad = fract(radius*nLayers);
    float layerID = crand(radius*nLayers-layerGrad, u);

 	float radialLayerWidth = 1.0+8.0*layerID;
    float radialLayers = pow(abs(0.5-layerGrad)*radialLayerWidth, 50.0);
  	radialLayers = clamp(radialLayers*(.3+crand(layerID, u)), 0.0, 1.0); 

    // Generate Angluar Slices
  	float theta = atan(localUV.x, localUV.y); 
    float nBigSlice = 10.0*crand(layerID,3.0);
    nBigSlice = nBigSlice-fract(nBigSlice);
    float bigCuts = clamp( 200.0*(.55+.65*sin(nBigSlice*theta+sin(layerID*9.4)*time*4.0+sin(layerID*200.0))), 0.0, 1.0);
    
    float iradius = 1.0-radius; 
    float nSmallSlice = 1.0+layerID*100.0*iradius*crand(layerID*layerID,3.0);
 	nSmallSlice = nSmallSlice-fract(nSmallSlice);
    float smallCuts = clamp( 200.0*(.55+.65*sin(nSmallSlice*theta+sin(u*10.0)*time*7.0+layerID*20.0)), 0.0, 1.0);
    smallCuts *= crand(layerID, u); 

    // Create Limits 
    float limits = 1.0;
    if (radius>sqrt(.225) || radius < .07)
        limits*=0.0;

    return clamp(smallCuts*bigCuts*radialLayers*limits, 0.0, 1.0);
}

void main()
{  
	gl_FragColor = vec4(generateObject(tc, unique, time));
	//gl_FragColor *= pow(color.g, 1.9)+color.g*.4;
	gl_FragColor *= 2.0*color.r;

	//gl_FragColor = 2.0*color.r;
	//gl_FragColor = vec4(2,0,0,1);
}

 