//#version 120 
			
#ifdef _VERSION_CHECK_
	#ifndef MSET

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


#ifdef SKINNING
	uniform samplerBuffer 	boneMatrices;
	
	#ifdef BONES_8
		attribute vec4			S2_texcoords2_Array;
		attribute vec4			S2_texcoords3_Array;
	#endif
#endif

#ifdef BSET
	uniform 		samplerBuffer 	pparams;
	#ifdef VEGETATION
		uniform			float hueVariation;
	#endif
#endif
	uniform vec4		ambientColor;	// ambient  * material color

#ifdef _HEIGHTMAP_
	
	uniform sampler2D	heightmap;
//	uniform vec2		invHeightmapSize;
	uniform vec4		tileDim;		//tileDim.zw = invHeightmapSize
//	uniform float		terrainDim; // height of the terrain
 	uniform vec3		WorldPoses[512];
	varying vec2 		texcoord2;
	uniform vec4		invTerrainDim;	//invTerrainDim.w = terrainNormOrg, invTerrainDim.y=terrain height
	//uniform float		terrainNormOrg;
	
#else
	#ifndef _NOT_INSTANCED_
		uniform samplerBuffer	WorldPoses;
	#endif
	varying float	alphaFade;
	uniform float 	fade;
#endif
 
varying vec2 	texcoord;
uniform vec2	tscale0;
uniform vec4 	plane;
varying float 	dist;
uniform mat4	prevWTM;
				
uniform vec3	ldir;
uniform vec4 	diffuseColor;	// material color * sun color * sun power
varying vec4	diffuse;
varying vec3 	Wpos;

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

//varying vec4 	fog;
/*varying vec3 	Lin;
varying vec3 	Fex;
*/
uniform vec3 	fogColor;
uniform vec3 	inScatterColor;
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 float 	extintion;
/////////////////////

// vertex attributes
attribute vec3 			s2_vertex;

#ifndef _HEIGHTMAP_
attribute vec3			s2_normal;
attribute vec4 			s2_color;
attribute vec4 			s2_secondaryColor;
attribute vec4			s2_texcoords; 
#endif

float ComputeVolumetricFog( vec3 cameraToWorldPos )
{
	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);
}

void main()
{
	vec3 viewDir;
	vec4 ambient=ambientColor;
	diffuse = diffuseColor;
	
#ifdef _HEIGHTMAP_

	// compute position basing on heightmap
	vec4 	position00 = vec4(s2_vertex,1.0),
			position10 = vec4(s2_vertex,1.0),
			position01 = vec4(s2_vertex,1.0);
	vec4 tempNormal = vec4( 0.0, 0.0, 0.0, 0.0 );
	mat4 TM;
		
	vec3 tilepos=WorldPoses[gl_InstanceID];//MTX[3].xyz;
	texcoord = ((s2_vertex.xz + tilepos.xz)*invTerrainDim.xz)+vec2(0.5,0.5)+(tileDim.zw/*invHeightmapSize*/*0.5);
	texcoord2 = texcoord;
	
	position00.y=(texture2D(heightmap,texcoord.st).x-invTerrainDim.w/*terrainNormOrg*/)*invTerrainDim.y;
	position00.xz=s2_vertex.xz;
	position10.y=(texture2D(heightmap,texcoord.st + vec2(tileDim.z/*invHeightmapSize.x*/,0.0)).x-invTerrainDim.w/*terrainNormOrg*/)*invTerrainDim.y;
	position10.xz=s2_vertex.xz + vec2(tileDim.x,0.0);
	position01.y=(texture2D(heightmap,texcoord.st + vec2(0.0,tileDim.w/*invHeightmapSize.y*/)).x-invTerrainDim.w/*terrainNormOrg*/)*invTerrainDim.y;
	position01.xz=s2_vertex.xz + vec2(0.0,tileDim.y);
	
	vec4 position;
	position.xyz=tilepos+position00.xyz;
	position.w=1.0;
	
	// transform position in projection and eye space
	gl_Position = gl_ModelViewProjectionMatrix * position;
		
	// compute normals (convert heightmap into normalmap
	vec3 t0,t1;
	t0=normalize(position00.xyz-position10.xyz);
	t1=normalize(position00.xyz-position01.xyz);
	tempNormal.xyz=cross(t1,t0);
	
	dist=(position.y*plane.y)-plane.w;
	diffuse.xyz = diffuse.xyz*max(dot(ldir,/*vnormal*/tempNormal.xyz),0.0);
	texcoord *= tscale0;
	
	// compute view direction
	viewDir=campos-position.xyz;
	//float distance=length(viewDir);
	vec3 vdir=normalize(viewDir.xyz);
	/*float cos=dot(-ldir,vdir);
	float F1=(1.0 + cos*cos*0.5);
	vec3 Br = cBr*F1;
	float delta=ComputeVolumetricFog(-viewDir);//)*distance;
	Fex=exp(-C0*extintion*delta);
	Lin=Br*C1*(1.0-Fex)*inScatterColor*fogColor;
*/
	Wpos=position.xyz;
	
#else

	vec4 normal4 = vec4(s2_normal, 0.0);
	texcoord = s2_texcoords.st*tscale0;
	vec4 vertex = vec4(s2_vertex,1.0);
	
	#ifdef SKINNING

		vec4 position = vec4( 0.0, 0.0, 0.0, 0.0 );
		vec4 tempNormal = 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;
				
		j=int(/*matrixIndices.x*/s2_secondaryColor.x)*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) * /*weights.x*/s2_color.x);
		TM[3]=vec4(0,0,0,1);
		tempNormal=tempNormal + ((TM * normal4) * /*weights.x*/s2_color.x);
		
		j=int(/*matrixIndices.y*/s2_secondaryColor.y)*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) * /*weights.y*/s2_color.y);
		TM[3]=vec4(0,0,0,1);
		tempNormal=tempNormal + ((TM * normal4) * /*weights.y*/s2_color.y);
		
		j=int(/*matrixIndices.z*/s2_secondaryColor.z)*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) * /*weights.z*/s2_color.z);
		TM[3]=vec4(0,0,0,1);
		tempNormal=tempNormal + ((TM * normal4) * /*weights.z*/s2_color.z);

		j=int(/*matrixIndices.w*/s2_secondaryColor.w)*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) * /*weights.w*/s2_color.w);
		TM[3]=vec4(0,0,0,1);
		tempNormal=tempNormal + ((TM * normal4) * /*weights.w*/s2_color.w);
		
		#ifdef BONES_8
			j=int(/*matrixIndices.x*/S2_texcoords3_Array.x)*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) * /*weights.x*/S2_texcoords2_Array.x);
			TM[3]=vec4(0,0,0,1);
			tempNormal=tempNormal + ((TM * normal4) * /*weights.x*/S2_texcoords2_Array.x);
			
			j=int(/*matrixIndices.y*/S2_texcoords3_Array.y)*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) * /*weights.y*/S2_texcoords2_Array.y);
			TM[3]=vec4(0,0,0,1);
			tempNormal=tempNormal + ((TM * normal4) * /*weights.y*/S2_texcoords2_Array.y);
			
			j=int(/*matrixIndices.z*/S2_texcoords3_Array.z)*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) * /*weights.z*/S2_texcoords2_Array.z);
			TM[3]=vec4(0,0,0,1);
			tempNormal=tempNormal + ((TM * normal4) * /*weights.z*/S2_texcoords2_Array.z);

			j=int(/*matrixIndices.w*/S2_texcoords3_Array.w)*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) * /*weights.w*/S2_texcoords2_Array.w);
			TM[3]=vec4(0,0,0,1);
			tempNormal=tempNormal + ((TM * normal4) * /*weights.w*/S2_texcoords2_Array.w);
		#endif
		
		gl_Position = gl_ModelViewProjectionMatrix * position;
		
		TM=prevWTM;
		vec4 vert=TM*position;
		dist=(vert.y*plane.y)-plane.w;

		TM[3]=vec4(0,0,0,1);
		vec4 vnormal=TM*tempNormal;
		
		diffuse.xyz = diffuse.xyz*max(dot(ldir,vnormal.xyz),0.0);
		
		Wpos=vert.xyz;
		// compute view direction
		viewDir=campos-vert.xyz;
		//float distance=length(viewDir);
		vec3 vdir=normalize(viewDir.xyz);
		/*float cos=dot(-ldir,vdir);
		float F1=(1.0 + cos*cos*0.5);
		vec3 Br = cBr*F1;
		float delta=ComputeVolumetricFog(-viewDir);
		Fex=exp(-C0*extintion*delta);
		Lin=Br*C1*(1.0-Fex)*inScatterColor*fogColor;
		*/
		
	#else
	
		#ifdef BSET

			int i=int(/*index.x*/s2_color.x)*3;
			vec4 ppos;
			ppos=texelFetchBuffer(pparams,i);
			alphaFade=1.0-ppos.w;
			ppos.w=1.0;
			
			#ifdef VEGETATION
				/* prova hue variation */
				float phase=dot(ppos.xyz,vec3(1.0,1.0,1.0));
				float sinPhase=sin(phase*0.01);
				vec3 vgColor;
				vgColor.r=hueVariation*sinPhase;
				vgColor.g=hueVariation*(1.0-sinPhase);
				vgColor.b=hueVariation*-sinPhase;
				vgColor.rgb=vgColor.rgb*vec3(0.5)+vec3(0.5);
				
				vec3 one=vec3(1.0,1.0,1.0);
				vec3 rmul=diffuse.rgb*vgColor.xyz;
				vec3 rscr=one-((one-vgColor.xyz)*(one-diffuse.rgb));
				diffuse.rgb=diffuse.rgb*rscr+(one-diffuse.rgb)*rmul;
				/* */
			#endif
			
			normal4=texelFetchBuffer(pparams,i+2);
			float scale=abs(normal4.w)*0.5*/*index.y*/s2_color.y;
			
			mat3 PTM;
			viewDir=campos-ppos.xyz;
			vec3 vdir=normalize(viewDir.xyz);
			PTM[2]=-vdir;
			PTM[0]=normalize(cross(vec3(0.0,1.0,0.0),PTM[2]));
			PTM[1]=cross(PTM[2],PTM[0]);
			vec4 vert=vertex*scale;
			vert.xyz=(PTM*vert.xyz) + ppos.xyz;
			vert.w=1.0;
			
			//vec4 vert=gl_ModelViewMatrix*rpos;
			gl_Position=gl_ModelViewProjectionMatrix*vert;
			
			//PTM=mat3(gl_ModelViewMatrix[0].xyz,gl_ModelViewMatrix[1].xyz,gl_ModelViewMatrix[2].xyz);
			vec3 vnormal=vdir;//PTM * normal4.xyz;
			diffuse.xyz = diffuse.xyz*(dot(ldir,vnormal)*0.5+0.5);
			dist=(vert.y*plane.y)-plane.w;
			
			// compute view direction
			/*float distance=length(viewDir);
			float cos=dot(-ldir,vdir);
			float F1=(1.0 + cos*cos*0.5);
			vec3 Br = cBr*F1;
			float delta=ComputeVolumetricFog(-viewDir);//)*distance;
			Fex=exp(-C0*extintion*delta);
			Lin=Br*C1*(1.0-Fex)*inScatterColor*fogColor;
			//ambient*=vec4(2.0);*/
			
			Wpos=vert.xyz;
				
		#else

			vec4 vert;
			#ifndef _NOT_INSTANCED_
				mat4 TM;
				int index=gl_InstanceID*4;
				TM[0]=texelFetchBuffer(WorldPoses,index);
				TM[1]=texelFetchBuffer(WorldPoses,index+1);
				TM[2]=texelFetchBuffer(WorldPoses,index+2);
				TM[3]=texelFetchBuffer(WorldPoses,index+3);
				alphaFade=TM[3].w+0.01;			
				TM[1].w=0.0;				
				TM[2].w=0.0;
				TM[3].w=1.0;
			
				vert=TM*vertex;	
				gl_Position = (gl_ModelViewProjectionMatrix)*vert;//ftransform();
			#else
				mat4 TM=prevWTM;
				gl_Position = (gl_ModelViewProjectionMatrix)*vertex;//ftransform();
				alphaFade=fade;
				vert=TM*vertex;	
			#endif
			
			vec4 vnormal=TM*normal4;
			vnormal.xyz=normalize(vnormal.xyz);
			diffuse.xyz = diffuse.xyz*max(dot(ldir,vnormal.xyz),0.0);
			dist=(vert.y*plane.y)-plane.w;

			// compute view direction
			viewDir=campos-vert.xyz;
			vec3 vdir=normalize(viewDir.xyz);
			Wpos=vert.xyz;
			/*
			float cos=dot(-ldir,vdir);
			float F1=(1.0 + cos*cos*0.5);
			vec3 Br = cBr*F1;
			float delta=ComputeVolumetricFog(-viewDir);
			Fex=exp(-C0*extintion*delta);
			Lin=Br*C1*(1.0-Fex)*inScatterColor*fogColor;
*/
		#endif
			
	#endif
	
#endif

	//diffuse=diffuse+ambient;

}