#ifdef _VERSION_CHECK_
	#ifndef _NOT_INSTANCED_

		//#version 120
		#extension GL_EXT_gpu_shader4 : enable          

	#endif
#endif

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

#ifdef _HEIGHTMAP_
	
	uniform sampler2D	heightmap;
//	uniform vec2		invHeightmapSize;
	uniform vec4		tileDim;		//tileDim.zw = invHeightmapSize
	uniform vec4		invTerrainDim;	//invTerrainDim.w = terrainNormOrg, invTerrainDim.y=terrain height
//	uniform float		terrainDim; 	// width, depth and height of the terrain
 	uniform vec3		WorldPoses[512];
	varying vec2 		texcoord2;
	//uniform float		terrainNormOrg;
	
#else
	#ifndef _NOT_INSTANCED_
		uniform samplerBuffer	WorldPoses;
	#endif
#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;

// FOG UNIFORMS
/*uniform vec3  	campos;
varying vec4 	fog;
uniform vec3 	fogColor;
uniform float 	extintion;*/
/////////////////////

varying vec4	eyepos;
varying vec3	worldpos;

// vertex attributes
attribute vec3 			s2_vertex;
attribute vec3			s2_normal;
attribute vec4 			s2_color;
attribute vec4 			s2_secondaryColor;
attribute vec4			s2_texcoords; 

/*float ComputeVolumetricFog( vec3 cameraToWorldPos )
{
	float fogInt;
	fogInt=length( cameraToWorldPos )*0.5;		
	return exp( -extintion * (fogInt) );
}

float ComputeScatter( vec3 wpos, vec3 cameraToWorldPos )
{
	float L=0.0;
	float Y=plane.w-campos.y;
	vec3 dir=vec3(0.0,0.0,0.0);
	
	if(Y <= 0.0)
		Y=0.0;
	
	if(wpos.y>plane.w )
		L=(length( cameraToWorldPos ) * Y) / cameraToWorldPos.y; 
	else
		L=length( cameraToWorldPos );
			
	if(L>0.0)
		dir=normalize(cameraToWorldPos);
		
	return exp( -extintion * Y * 0.1 ) * ( ( exp((dir.y-1.0)*extintion*L) - 1.0 ) / ((dir.y-1.0) * extintion)) * 0.01;
}*/

void main()
{
	vec3 viewDir;
	vec4 normal4 = vec4( s2_normal, 0.0 );
	
#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];
	texcoord = ((s2_vertex.xz + tilepos.xz)*invTerrainDim.xz)+vec2(0.5,0.5)+(tileDim.zw*0.5);
	texcoord2 = texcoord;
	
	position00.y=(texture2D(heightmap,texcoord.st).x-invTerrainDim.w)*invTerrainDim.y;
	position00.xz=s2_vertex.xz;
	position10.y=(texture2D(heightmap,texcoord.st + vec2(tileDim.z,0.0)).x-invTerrainDim.w)*invTerrainDim.y;
	position10.xz=s2_vertex.xz + vec2(tileDim.x,0.0);
	position01.y=(texture2D(heightmap,texcoord.st + vec2(0.0,tileDim.w)).x-invTerrainDim.w)*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
	eyepos = gl_ModelViewMatrix * position;
	gl_Position = gl_ProjectionMatrix * eyepos;
		
	// 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 = diffuseColor*max(dot(ldir,tempNormal.xyz),0.0)*2.0;
	texcoord *= tscale0;
	
	// compute view direction
	worldpos=position.xyz;

#else

	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(s2_secondaryColor.x/*matrixIndices.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(s2_secondaryColor.y/*matrixIndices.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(s2_secondaryColor.z/*matrixIndices.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(s2_secondaryColor.w/*matrixIndices.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 = diffuseColor*max(dot(ldir,vnormal.xyz),0.0)*0.2;
		
		// compute view direction
		worldpos=vert.xyz;;
		/*viewDir=campos-worldpos.xyz;
		fog.a=ComputeVolumetricFog(-viewDir);
		float scatter=ComputeScatter( worldpos.xyz, -viewDir );
		fog.rgb=fogColor*scatter;*/
		
		eyepos=gl_ModelViewMatrix*position;
		
	#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);
			
			TM[1].w=0.0;				
			TM[2].w=0.0;
			TM[3].w=1.0;
			
			vert=TM*vertex;	
			eyepos=gl_ModelViewMatrix*vert;
			gl_Position = gl_ProjectionMatrix*eyepos;
		#else
			mat4 TM=prevWTM;
			eyepos=gl_ModelViewMatrix*vertex;
			gl_Position = (gl_ProjectionMatrix)*eyepos;
			vert=TM*vertex;	
		#endif
		
		vec4 vnormal=TM*normal4;
		diffuse = diffuseColor*max(dot(ldir,vnormal.xyz),0.0)*0.2;
		dist=(vert.y*plane.y)+plane.w;

		// compute view direction
		worldpos=vert.xyz;;
	/*	viewDir=campos-worldpos.xyz;
		fog.a=ComputeVolumetricFog(-viewDir);
		float scatter=ComputeScatter( worldpos.xyz, -viewDir );
		fog.rgb=fogColor*scatter;*/
			
	#endif
	
#endif

}