#ifdef _VERSION_CHECK_
	#ifndef MSET

		#ifndef _NOT_INSTANCED_
		
			#version 120
			#extension EXT_gpu_shader4 : enable          

		#endif
			
	#endif
#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 vec2	tofs;			// cambiare in uniform
	uniform vec2	tscale;
	uniform vec3 	particleScale;

#endif

#ifdef ALPHATEST

	varying vec2 texcoords;
	
	#ifdef VEGETATION
		uniform float 	time;
		uniform float 	windStrenght;
		uniform vec2 	meshbox;
		uniform vec2	bendMul;
		uniform vec3 	windVec;
		float 			freq=time;//+time*windStrenght*0.25;
	#endif

#endif

#ifdef MSET

	uniform	mat4 	pparams[64];
	//uniform samplerBuffer 	pparams;
	vec4			tpos;
	//attribute vec3 	index;
	
#endif

varying vec2	depth;
//uniform mat4	WTM;

#ifndef _NOT_INSTANCED_
	
	#ifdef _HEIGHTMAP_
		
		uniform sampler2D	heightmap;
		uniform vec2		invHeightmapSize;
		uniform vec2		tileDim;
		uniform vec3		terrainDim; // width, depth and height of the terrain
		uniform vec3		invTerrainDim;
		uniform vec3		WorldPoses[200];
		
	#else
		uniform samplerBuffer	WorldPoses;
	#endif
	
#else
	uniform mat4	prevWTM;
#endif

vec2 XformWind(vec2 wind, mat4 TM)
{
	mat2 TM2;
	TM2[0]=vec2(TM[0].x,TM[2].x);
	TM2[1]=vec2(TM[0].z,TM[2].z);
	return TM2*wind;
}

void main()
{

#ifdef _HEIGHTMAP_

	// compute position basing on heightmap
	vec4 	position00;
		
	mat4 MTX;
	int index=gl_InstanceID*4;
	vec3 tilepos=WorldPoses[gl_InstanceID];
	vec2 texcoord = ((gl_Vertex.xz + tilepos.xz)*invTerrainDim.xz)+vec2(0.5,0.5)+(invHeightmapSize*0.5);
	position00.y=(texture2D(heightmap,texcoord.st).x-0.5)*terrainDim.y;
	position00.xz=gl_Vertex.xz;

	vec4 position;
	position.xyz=tilepos+position00.xyz;
	position.w=1.0;
	
	// transform position in projection and eye space
	gl_Position = gl_ModelViewProjectionMatrix * position;
	
#else
	
	#ifdef SKINNING

		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;
					
		j=int(gl_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 * gl_Vertex) *gl_Color.x;//weights.x;
					
		j=int(gl_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 * gl_Vertex) *gl_Color.y;//weights.y;
					
		j=int(gl_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 * gl_Vertex) *gl_Color.z;//weights.z;
					
		j=int(gl_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 * gl_Vertex) *gl_Color.w;//weights.w;
				
		/*position = position + ((boneMatrices[int(matrixIndices.x)] * gl_Vertex) * weights.x);
		position = position + ((boneMatrices[int(matrixIndices.y)] * gl_Vertex) * weights.y);
		position = position + ((boneMatrices[int(matrixIndices.z)] * gl_Vertex) * weights.z);
		position = position + ((boneMatrices[int(matrixIndices.w)] * gl_Vertex) * weights.w);*/
		gl_Position = gl_ModelViewProjectionMatrix * position;

	#else

		#ifdef PSYSTEM

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

			float angle=(/*index.y*/gl_Color.y*6.28)+(data.z*(1.0-life)*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);

			gl_Position=gl_ProjectionMatrix*tpos;
			
		#else

			#ifdef MSET

				mat4 mtx=pparams[int(/*index.x*/gl_Color.w)];
				float bendScale=mtx[3].w;
				mtx[3].w=1.0;
				vec4 newpos=gl_Vertex;
				
				#ifdef VEGETATION
					
					vec2 dBend=gl_Color.gb*windStrenght*bendMul.y;
					float phase=dot(mtx[3].xyz,vec3(1.0,1.0,1.0));
					float phase2=phase+gl_Color.r;
					float phase3=phase2+dot(gl_Vertex.xyz,vec3(1.0,1.0,1.0));
					phase2*=3.14;
					phase3*=3.14;
					phase+=freq;
					
					vec4 	waves=sin( vec4( (freq*8.2)+phase3,	(freq*4.0)+phase2, ((freq*13.5)+2.0*phase3)+1.570796, 	((freq*10.0)+phase2*3.0)+1.570796)	);				
					vec2 	windMul=sin( vec2(phase, ((phase+1.0)*5.0)+1.570796) );
							
					newpos.xz+=gl_Normal.xy*(waves.x*2.0 + waves.z)*dBend.x;
					newpos.y+=(waves.y + waves.w)*dBend.y;
					
					float vlen=length(gl_Vertex.xyz);
					float bend;
					bend=gl_Vertex.y*bendScale;
					bend += 1.0;
					bend = (bend * bend - bend) * bendMul.x * windStrenght;
					
					vec2 windVector=windVec.xz;//vec2(mtx[1].w,mtx[2].w);
					mtx[1].w=0.0;
					mtx[2].w=0.0;
						
					newpos.xz+=( XformWind(windVector,mtx)/*vec2(mtx[1].w,mtx[2].w)*/*((windMul.x+windMul.y)*10.0+30.0)*bend );
					newpos.xyz=normalize(newpos.xyz)*vlen;
					//////////////////////////////////////
				#else
					mtx[1].w=0.0;
					mtx[2].w=0.0;
				#endif
							
				newpos=mtx*newpos;
				tpos=gl_ModelViewMatrix * newpos;	
				gl_Position=gl_ProjectionMatrix*tpos;	
					
			#else
			
				#ifndef _NOT_INSTANCED_
					//vec4 pos=WorldPoses[gl_InstanceID]*gl_Vertex;
					mat4 MTX;
					int index=gl_InstanceID*4;
					MTX[0]=texelFetchBuffer(WorldPoses,index);
					MTX[1]=texelFetchBuffer(WorldPoses,index+1);
					MTX[2]=texelFetchBuffer(WorldPoses,index+2);
					MTX[3]=texelFetchBuffer(WorldPoses,index+3);
					
					vec4 newpos=gl_Vertex;
					#ifdef VEGETATION
						////////////////////////////////////////////
						vec2 dBend=gl_Color.gb*windStrenght*bendMul.y;
						float phase=dot(MTX[3].xyz,vec3(1.0,1.0,1.0));
						float phase2=phase+gl_Color.r;
						float phase3=phase2+dot(gl_Vertex.xyz,vec3(1.0,1.0,1.0));
						phase2*=3.14;
						phase3*=3.14;
						
						vec4 	waves=sin( vec4( (freq*8.2)+phase3,	(freq*4.0)+phase2, ((freq*13.5)+2.0*phase3)+1.570796, 	((freq*10.0)+phase2*3.0)+1.570796)	);
						
						newpos.xz+=gl_Normal.xy*(waves.x*2.0 + waves.z)*dBend.x;
						newpos.y+=(waves.y + waves.w)*dBend.y;
						
						float vlen=length(gl_Vertex.xyz);	
						float bend;
						bend=gl_Vertex.y*meshbox.y;
						bend += 1.0;
						bend = (bend * bend - bend) * bendMul.x * windStrenght;
						
						vec2 windVector=vec2(MTX[1].w,MTX[2].w);
						MTX[1].w=0.0;
						MTX[2].w=0.0;
						newpos.xz+=(XformWind(windVector,MTX)/*vec2(MTX[1].w,MTX[2].w)*/*bend);
						newpos.xyz=normalize(newpos.xyz)*vlen;
						//////////////////////////////////////
					#else
						MTX[1].w=0.0;
						MTX[2].w=0.0;
					#endif			
						
					/*MTX[1].w=0.0;
					MTX[2].w=0.0;*/
					//MTX[3].w=1.0;
					newpos=MTX*newpos;
					gl_Position = (gl_ModelViewProjectionMatrix)*newpos;//pos;//ftransform();
				#else
				
					vec4 newpos=gl_Vertex;
					#ifdef VEGETATION
						
						vec2 dBend=gl_Color.gb*windStrenght*bendMul.y;
						float phase=dot(prevWTM[3].xyz,vec3(1.0,1.0,1.0));
						float phase2=phase+gl_Color.r;
						float phase3=phase2+dot(gl_Vertex.xyz,vec3(1.0,1.0,1.0)/*vec2(phase+phase2)*/);
						phase2*=3.14;
						phase3*=3.14;
						
						vec4 	waves=sin( vec4( (freq*8.2)+phase3,	(freq*4.0)+phase2, ((freq*13.5)+2.0*phase3)+1.570796, 	((freq*10.0)+phase2*3.0)+1.570796)	);
						
						newpos.xz+=gl_Normal.xy*(waves.x*2.0 + waves.z)*dBend.x;
						newpos.y+=(waves.y + waves.w)*dBend.y;
						
						float vlen=length(gl_Vertex.xyz);			
						float bend;
						bend=gl_Vertex.y*meshbox.y;//MTX[1].w;//0.001;//bendScale;
						bend += 1.0;
						bend = (bend * bend - bend) * bendMul.x * windStrenght;
						
						vec2 windVector=windVec.xz;
						newpos.xz+=(XformWind(windVector,prevWTM)*bend);
						newpos.xyz=normalize(newpos.xyz)*vlen;
							
						/*newpos.xz+=(windVec.xz*bend);
						newpos.xyz=normalize(newpos.xyz)*vlen;*/
						//////////////////////////////////////
					#endif
					
					gl_Position = (gl_ModelViewProjectionMatrix)*newpos;//ftransform();
				#endif
				
			#endif
			
		#endif
		
	#endif

#endif

#ifdef ALPHATEST
	texcoords = gl_MultiTexCoord0.st;
#endif

	depth=gl_Position.zw;
}