#ifdef SKINNING

	#version 120
	#extension EXT_gpu_shader4 : enable          

#endif

#ifdef SKINNING

	uniform mat3 	boneMatrices[100];
	//	uniform samplerBuffer 	boneMatrices;
	//attribute vec4  weights;
	//attribute vec4  matrixIndices;

#endif

#ifdef PSYSTEM

	uniform	vec4 	pparams[100]; 	

	vec4			tpos;
	uniform vec4	data;

	//attribute vec4	index;
	varying float 	life;
	uniform vec3 	particleScale;
	
	//varying vec4 	posDir;
	
#else
	
/*	varying vec3	w0,
					w1,
					w2;*/
	varying mat3	TBN;

//	attribute vec3 	normal;
	attribute vec4	binormal; 
	varying vec3	viewDir;
	uniform mat4	prevWTM/*,
					WTM*/;
	varying vec4 	vpos;

#endif

varying vec2 	texcoord;
varying vec2 	texcoord1;

uniform vec2	tscale0;
uniform vec2	tscale1;

uniform vec2	tofs0;		// cambiare in uniform
uniform vec2	tofs1;		// cambiare in uniform

#ifdef BUMP2

	uniform vec2	tscale2;
	varying vec2 	texcoord2;
	uniform vec2	tofs2;

#endif

varying vec4 	pos;
uniform vec2	NF;
varying vec4	eyepos;

uniform vec3	campos;
uniform float	extintion;
//varying vec4	fog;
uniform vec3  	SUN; 	// = colore del sole
uniform	vec3  	C0; 	// = cBr+cBm;	
uniform vec3  	C1; 	// = 1.0/(cBr+cBm);
uniform vec3  	cBr; 	// = RayLeigh
uniform float 	C2;	// = log(e)

uniform vec3 	fogColor;
uniform vec3 	inScatterColor;
uniform vec3 	sundir;
		
varying vec3 	Fex;
varying vec3 	Lin;

uniform float cHeightFallof;//=0.0005;	// inserire dall'esterno
float cVolFogHeightDensityAtViewer=exp( cHeightFallof * -campos.y);
////////////////////////////

float ComputeVolumetricFog( vec3 cameraToWorldPos )
{
	// cVolFogHeightDensityAtViewer= exp( -cHeightFalloff* cViewPos.z);
	float fogInt = length( cameraToWorldPos ) * cVolFogHeightDensityAtViewer;
	
	if( abs( cameraToWorldPos.y) > 0.01)
	{
		float t = cHeightFallof * cameraToWorldPos.y;
		fogInt*= ( 1.0-exp( -t ) ) / t;
		
	}
	return fogInt; //exp( -extintion*0.001 * fogInt);
}
		
vec2 ComputeFrame(float dt, vec2 nf)
{
	vec2 ofs=vec2(1.0,1.0)/nf;
	float frame=floor(dt*nf.x*nf.y);
	float row=floor(frame/nf.x);
	float col=floor(frame-nf.x*row);
	
	return vec2(ofs.x*col, 1.0-(ofs.y*row)-ofs.y);
}

void main()
{  
	#ifdef SKINNING

		vec4 index  		= gl_SecondaryColor;//matrixIndices;
		vec4 weight 		= gl_Color;//weights;
		vec4 position   	= vec4( 0.0, 0.0, 0.0, 0.0 );
		
		mat4 TM=mat4(	0.0,0.0,0.0,0.0,
						0.0,0.0,0.0,0.0,
						0.0,0.0,0.0,0.0,
						0.0,0.0,0.0,1.0);
		int j;
		for( int i = 0; i < 4; i++ )
		{
				// Apply influence of bone i
				
				j=int(index[i]);
				TM[0].xyz=boneMatrices[j][0];
				TM[1].xyz=boneMatrices[j][1];
				TM[2].xyz=cross(TM[0].xyz,TM[1].xyz);
				TM[3].xyz=boneMatrices[j][2];

				position = position + (TM * gl_Vertex) *weight[i];
			
		//	TM=boneMatrices[int(index[i])];
			//	position = position + (TM * gl_Vertex) *weight[i];
		}
		gl_Position = gl_ModelViewProjectionMatrix * position;
		eyepos = gl_ModelViewMatrix * position;
		
	#else

		#ifdef PSYSTEM

			vec4 ppos=pparams[int(/*index.x*/gl_Color.x)];
			life=ppos.w;
			float invlife=clamp(1.0-life,0.0,1.0);
			
			if(data.w==0.0)
			{
				float scale=data.x + (data.y*invlife);
				scale=clamp(scale,0.0,abs(scale))*0.5;
				scale+=scale*/*index.y*/gl_Color.y;	
				ppos.w=1.0;

				float angle=(/*index.y*/gl_Color.y*6.28)+(data.z*invlife*6.28);

				float cosa=cos(angle);
				float sina=sin(angle);

				tpos=gl_ModelViewMatrix * ppos;	

				vec3 tv=gl_Vertex.xyz;
				tv.x=(gl_Vertex.x*cosa)-(gl_Vertex.y*sina);
				tv.y=(gl_Vertex.x*sina)+(gl_Vertex.y*cosa);
				tpos.xyz=(tv.xyz*particleScale*scale + tpos.xyz);

			//	posDir.xyz=normalize(tpos.xyz-posDir.xyz);
			}
			else
			{
				vec4 prevpos=prevPParams[int(/*index.x*/gl_Color.x)];
				prevpos.w=1.0;
							
				mat3 rTM,eTM;
				
				vec3 vel=ppos.xyz-prevpos.xyz;
				vec3 dir;
				vec3 vdir=normalize(vel);
				vec3 rgt;
				
				rgt=normalize(cross(vdir,camdir)/*rdot*/);
				dir=normalize(cross(vdir,rgt));
				
				rTM[2]=dir;
				rTM[0]=rgt;
				rTM[1]=vdir;
				
				float scale=length(vel);
				vec4 rpos;
				rpos.xyz=gl_Vertex.xyz*data.x;
				rpos.y+=(gl_Vertex.y*scale*particleScale.y);
			//	posDir.xyz=normalize(rpos.xyz);
				rpos.xyz=(rTM*rpos.xyz) + ppos.xyz;
				rpos.w=1.0;
				tpos=gl_ModelViewMatrix*rpos;
			//	posDir=gl_ModelViewMatrix*vec4(posDir.xyz,0.0);
			}
			
			eyepos=tpos;
			gl_Position=gl_ProjectionMatrix*tpos;
				
		#else
				
			vec4 normal4   	= vec4( gl_Normal.xyz, 0.0 );
			vec4 binormal4  = vec4( binormal.xyz, 0.0 );
			vec4 tangent4   = vec4(cross(binormal4.xyz,normal4.xyz),0.0);
			binormal4.xyz*=binormal.w;

			vec4 	outTangent,
					outNormal,
					outBinormal;
				
			outNormal=/*normalize(*/prevWTM*normal4/*)*/;
			outTangent=/*normalize(*/prevWTM*tangent4/*)*/;
			outBinormal=/*normalize(*/prevWTM*binormal4/*)*/;

			/*w0=vec3(outTangent.x,outBinormal.x,outNormal.x);
			w1=vec3(outTangent.y,outBinormal.y,outNormal.y);
			w2=vec3(outTangent.z,outBinormal.z,outNormal.z);*/
			TBN[0]=outTangent.xyz;
			TBN[1]=outBinormal.xyz;
			TBN[2]=outNormal.xyz;

			// transform to world space
			vpos=prevWTM*gl_Vertex;
			
			// compute view direction
			viewDir=campos-vpos.xyz;

			gl_Position = (gl_ModelViewProjectionMatrix)*gl_Vertex;//ftransform();
			eyepos = gl_ModelViewMatrix * gl_Vertex;
			
			// compute fog ///////////////////////////////////////////////////
			//float distance=length(eyepos.xyz);
			vec3 vdir=normalize(eyepos.xyz);
			float cos=/*clamp(*/dot(-sundir,vdir);//,-1.0,0.0);
			float F1=(1.0 + cos*cos*0.5);
			vec3 Br = cBr*F1*0.9;
		
			float delta=/*1.0-*/ComputeVolumetricFog(-viewDir);
			//delta *= distance;
			Fex=exp(-C0*extintion*delta);
			Lin=Br*C1*(1.0-Fex)*inScatterColor*fogColor;
				
			/*fog.a=ComputeVolumetricFog(-viewDir);
			vec3 LinMul=C1*SUN*(1.0-exp(-C0*min(distance,10000.0)));
			vec3 fogLin = Br*0.9*LinMul;
			fog.rgb=fogLin*inScatterColor+fogColor;*/
					
		#endif

	#endif

	texcoord = gl_MultiTexCoord0.st*tscale0 + tofs0;
	texcoord1 = gl_MultiTexCoord0.st*tscale1 + tofs1;
	
	#ifdef BUMP2

		texcoord2 = gl_MultiTexCoord0.st*tscale2 + tofs2;

	#endif
	
	pos=gl_Position;

}