/*	#ifdef SKINNING

		#version 120
		#extension GL_EXT_gpu_shader4 : enable          

	#endif
*/
#ifdef _VERSION_CHECK_
	#ifndef MSET

		#ifndef _NOT_INSTANCED_
		
			#extension GL_EXT_gpu_shader4 : enable     
			
		#endif
		
	#endif
#endif

// TAO ///////////////////////////

/*uniform sampler2D 	heightmap,
					colormap;
uniform vec3 invTerrainDim;
uniform float terrainMaxHeight;
uniform float maxRadius;
uniform float occScale;

varying float TAO;*/

//////

#ifdef SKINNING
	uniform samplerBuffer 	boneMatrices;
	varying mat3	TBN;
	varying vec3	viewDir;
	uniform mat4	prevWTM;
#else

	#ifdef PSYSTEM

		uniform	vec4 	pparams[100]; 	
		uniform vec4	prevPParams[100];

		vec4			tpos;
		uniform vec4	data;

		varying float 	life;
		varying vec2	cosina;
		uniform vec4 	particleScale; //particleScale.w start rotation
		
		uniform vec3	camdir;
		varying vec4 	posDir;
		varying vec4 	pos;
		
	#else
	
		#ifdef BSET

			uniform 		samplerBuffer 	pparams;
			vec4			tpos;
			uniform vec4	data;
			varying vec4	pnormal;
			varying vec4 	pcolor;
				
			uniform vec3	campos;
				
		#else
	
			varying mat3	TBN;
			attribute vec4	binormal; 
			varying vec3	viewDir;
			uniform mat4	prevWTM;

		#endif
	
	#endif
	
#endif

varying vec4 	vpos;

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;
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;

// ---------------------------- EXP FOG
varying vec4 fogScat;
// -----------------------------------

uniform float	fogNear;

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

attribute vec3 			s2_vertex;
attribute vec3			s2_normal;
attribute vec4			s2_binormal;
attribute vec4 			s2_color;
attribute vec4 			s2_secondaryColor;
attribute vec4			s2_texcoords; 

/*float ComputeVolumetricFog( vec3 cameraToWorldPos )
{
	float fogInt = max(length( cameraToWorldPos )-fogNear,0.0) * cVolFogHeightDensityAtViewer;
	
	if( abs( cameraToWorldPos.y ) > 0.01)
	{
		float t = cHeightFallof * cameraToWorldPos.y;
		fogInt*= ( 1.0-exp( -t ) ) / t;
		
	}
	return fogInt; 
}*/

float ComputeVolumetricFog( vec3 cameraToWorldPos )
{
	float distance=max(length( cameraToWorldPos )-fogNear,0.0);
	float fogInt = distance * exp( cHeightFallof * -campos.y);
	
	if( abs(cameraToWorldPos.y) > 0.01)
	{
		float t = cHeightFallof * cameraToWorldPos.y;
		fogInt*= ( 1.0-exp( -t ) ) / t;
	}
	return /*exp( -extintion * fogInt)*/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);
}

/*float ComputeTAO(vec3 wpos)
{
	vec2 heigthmapCoord = (wpos.xz*invTerrainDim.xz)+vec2(0.5,0.5);
	float tHeight=(texture2D(heightmap,heigthmapCoord.st).x-0.5)*terrainMaxHeight;
	float tDistance=wpos.y-tHeight;
	
	// get terrain sky visibility value from terrain
	float skyVisibility=texture2D(colormap,heigthmapCoord.st).a;

	// compute ambient occlusion basing on distance
	float d=clamp(tDistance/maxRadius,0.0,1.0);
	float visibility=mix(skyVisibility,1.0,d*d);	//0 max occlusion, 1 - no occlusion
	
	return min(visibility+occScale,1.0);
}*/

void main()
{  
	vec4 vertex=vec4(s2_vertex,1.0);
	
	#ifdef SKINNING

		vec4 normal4   	= vec4( s2_normal, 0.0 );
		vec4 binormal4  = vec4( s2_binormal.xyz, 0.0 );
		vec4 tangent4   = vec4(cross(binormal4.xyz,normal4.xyz),0.0);
		binormal4.xyz*=s2_binormal.w;
				
		vec4 tempNormal  	= vec4( 0.0, 0.0, 0.0, 0.0 );
		vec4 tempTangent  	= vec4( 0.0, 0.0, 0.0, 0.0 );
		vec4 tempBinormal  	= vec4( 0.0, 0.0, 0.0, 0.0 );
		
		vec4 index  		= s2_secondaryColor;
		vec4 weight 		= s2_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]*4);
				TM[0].xyz=texelFetchBuffer(boneMatrices,j).xyz;
				TM[1].xyz=texelFetchBuffer(boneMatrices,j+1).xyz;
				TM[2].xyz=texelFetchBuffer(boneMatrices,j+2).xyz;
				TM[3].xyz=texelFetchBuffer(boneMatrices,j+3).xyz;
			
				position = position + (TM * vertex) *weight[i];
				
				// Transform normals by bone i
				TM[3]=vec4(0,0,0,1);
				tempNormal = tempNormal + (TM * normal4)*weight[i];
				tempBinormal = tempBinormal + (TM * binormal4)*weight[i];
				tempTangent = tempTangent + (TM * tangent4)*weight[i];
		}
		gl_Position = gl_ModelViewProjectionMatrix * position;
		eyepos = gl_ModelViewMatrix * position;
		
		//texcoord = s2_texcoords.st;
		
		TBN[0]=normalize(gl_ModelViewMatrix*tempTangent).xyz;
		TBN[1]=normalize(gl_ModelViewMatrix*tempBinormal).xyz;
		TBN[2]=normalize(gl_ModelViewMatrix*tempNormal).xyz;
		
		// transform to world space
		vpos=prevWTM*position;
		
		// comute TAO ///
		//TAO=ComputeTAO(vpos.xyz);
		
		// compute fog /////////////////////////////////////////
		viewDir=campos-vpos.xyz;
		float delta=ComputeVolumetricFog(-viewDir);
		fogScat.a=exp(-extintion*delta);
		fogScat.rgb=(1.0-fogScat.a)*inScatterColor*fogColor*0.06;
			
	#else

		#ifdef PSYSTEM

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

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

				cosina.x=cos(angle);
				cosina.y=sin(angle);

				tpos=gl_ModelViewMatrix * ppos;	
				//pEyePos=tpos;
				posDir=tpos;

				vec3 tv=vertex.xyz;
				tv.x=(vertex.x*cosina.x)-(vertex.y*cosina.y);
				tv.y=(vertex.x*cosina.y)+(vertex.y*cosina.x);
				tpos.xyz=(tv.xyz*particleScale.xyz*scale + tpos.xyz);
				posDir.xyz=normalize(tpos.xyz-posDir.xyz);
			}
			else
			{
				vec4 prevpos=prevPParams[int(/*index.x*/s2_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=vertex.xyz*data.x;
				rpos.y+=(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;
				//pEyePos=tpos;
				posDir=gl_ModelViewMatrix*vec4(posDir.xyz,0.0);
			}
			
			eyepos=tpos;
			gl_Position=gl_ProjectionMatrix*tpos;
			pos=gl_Position;
			
			// compute fog ///////////////////////////////////
			vec3 Cam2WorldPos=ppos.xyz-campos.xyz;
			float delta=ComputeVolumetricFog(Cam2WorldPos);
			fogScat.a=exp(-extintion*delta);
			fogScat.rgb=(1.0-fogScat.a)*inScatterColor*fogColor*0.06;
			
			vpos=ppos;
			vec2 texOfs=ComputeFrame(invlife, NF);
			
		#else
		
			#ifdef BSET

				vec4 index=s2_color;
				int i=int(index.x)*3;
				vec4 ppos;
				ppos=texelFetchBuffer(pparams,i);
				pcolor=texelFetchBuffer(pparams,i+1);	
				vec4 newpos=vec4(s2_vertex,1.0);
				
				// comute TAO ////
				//TAO=ComputeTAO(ppos.xyz);
				
				pcolor.w=ppos.w;
				ppos.w=1.0;
				
				normal4=texelFetchBuffer(pparams,i+2);
				float scale=abs(normal4.w)*0.5*index.y;
				
				mat3 PTM;
				PTM[2]=normalize(ppos.xyz-campos);
				PTM[0]=normalize(cross(vec3(0.0,1.0,0.0),PTM[2]));
				PTM[1]=cross(PTM[2],PTM[0]);
				
				vec4 rpos=newpos*scale;
				rpos.xyz=(PTM*rpos.xyz) + ppos.xyz;
				rpos.w=1.0;
				
				tpos=gl_ModelViewMatrix*rpos;
				gl_Position=gl_ProjectionMatrix*tpos;	
				curpos=gl_Position;	
				//pos=tpos;
				vpos=ppos;
				
				// compute prev pos
				tpos=prevMVM*rpos;
				prev=gl_ProjectionMatrix*tpos;
				
				PTM=mat3(gl_ModelViewMatrix[0].xyz,gl_ModelViewMatrix[1].xyz,gl_ModelViewMatrix[2].xyz);
				pnormal.xyz=PTM * normal4.xyz;
				texcoord = s2_texcoords.st;	
				
				// FOG ???????????????? //////////////////
				// compute fog /////////////////////////////////////////
				viewDir=campos-vpos.xyz;
				
				float delta=ComputeVolumetricFog(-viewDir);
				fFex=exp(-extintion*delta);
				fLin=(1.0-fFex)*inScatterColor*fogColor*0.1;
		
			#else
		
				vec4 normal4   	= vec4( s2_normal, 0.0 );
				vec4 binormal4  = vec4( s2_binormal.xyz, 0.0 );
				vec4 tangent4   = vec4(cross(binormal4.xyz,normal4.xyz),0.0);
				binormal4.xyz*=s2_binormal.w;

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

				TBN[0]=outTangent.xyz;
				TBN[1]=outBinormal.xyz;
				TBN[2]=outNormal.xyz;

				// transform to world space
				vpos=prevWTM*vertex;
				
				// comute TAO ///
				//TAO=ComputeTAO(vpos.xyz);

				// compute view direction
				viewDir=campos-vpos.xyz;
				
				gl_Position = (gl_ModelViewProjectionMatrix)*vertex;//ftransform();
				eyepos = gl_ModelViewMatrix * vertex;
				
				// compute fog /////////////////////////////////////////
				float delta=ComputeVolumetricFog(-viewDir);
				fogScat.a=exp(-extintion*delta);
				fogScat.rgb=(1.0-fogScat.a)*inScatterColor*fogColor*0.06;
				
			#endif
				
		#endif

	#endif

	#ifdef PSYSTEM
	
		texcoord = s2_texcoords.st*tscale0 + tofs0 + texOfs;
		
	#else
		
		texcoord = s2_texcoords.st*tscale0 + tofs0;
		texcoord1 = s2_texcoords.st*tscale1 + tofs1;
		
		#ifdef BUMP2

			texcoord2 = s2_texcoords.st*tscale2 + tofs2;

		#endif
	#endif
//	pos=gl_Position;
}