#ifdef _VERSION_CHECK_
	#ifndef MSET

		#ifndef _NOT_INSTANCED_
		
			//#version 120
			#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 PSYSTEM

	uniform	vec4 	pparams[100]; 
	
	vec4			tpos;
	uniform vec4	data;
	varying float 	life;

	uniform vec3 	particleScale;

#endif

#ifdef ALPHATEST

	varying vec2 texcoords;

	uniform vec2	tofs;			// cambiare in uniform
	uniform vec2	tscale;
	
	#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[60];
	vec4			tpos;
	
#endif

varying vec2	depth;

#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[512];
		uniform float		terrainNormOrg;
		
	#else
		uniform samplerBuffer	WorldPoses;
	#endif
	
#else
	uniform mat4	prevWTM;
#endif

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

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 = ((s2_vertex.xz + tilepos.xz)*invTerrainDim.xz)+vec2(0.5,0.5)+(invHeightmapSize*0.5);
	position00.y=(texture2D(heightmap,texcoord.st).x-terrainNormOrg)*terrainDim.y;
	position00.xz=s2_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
	
	vec4 vertex=vec4(s2_vertex,1.0);
	
	#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(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) *s2_color.x;//weights.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) *s2_color.y;//weights.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) *s2_color.z;//weights.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) *s2_color.w;//weights.w;
		
		#ifdef BONES_8
			j=int(S2_texcoords3_Array.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) *S2_texcoords2_Array.x;//weights.x;
						
			j=int(S2_texcoords3_Array.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) *S2_texcoords2_Array.y;//weights.y;
						
			j=int(S2_texcoords3_Array.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) *S2_texcoords2_Array.z;//weights.z;
						
			j=int(S2_texcoords3_Array.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) *S2_texcoords2_Array.w;//weights.w;
		#endif
		
		gl_Position = gl_ModelViewProjectionMatrix * position;

	#else

		#ifdef PSYSTEM

			vec4 ppos=pparams[int(/*index.x*/s2_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*/s2_color.y;	
			ppos.w=0.0;

			float angle=(/*index.y*/s2_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=vertex.xyz;
			tv.x=(vertex.x*cosa)-(vertex.y*sina);
			tv.y=(vertex.x*sina)+(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*/s2_color.w)];
				float bendScale=mtx[3].w;
				mtx[3].w=1.0;
				vec4 newpos=vertex;
				
				#ifdef VEGETATION
					
					vec2 dBend=s2_color.gb*windStrenght*bendMul.y;
					float phase=dot(mtx[3].xyz,vec3(1.0,1.0,1.0));
					float phase2=phase+s2_color.r;
					float phase3=phase2+dot(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+=s2_normal.xy*(waves.x*2.0 + waves.z)*dBend.x;
					newpos.y+=(waves.y + waves.w)*dBend.y;
					
					float vlen=length(vertex.xyz);
					float bend;
					bend=vertex.y*bendScale;
					bend += 1.0;
					bend = (bend * bend - bend) * bendMul.x * windStrenght;
					
					vec2 windVector=windVec.xz;
					mtx[0].w=0.0;
					mtx[1].w=0.0;
					mtx[2].w=0.0;
						
					newpos.xz+=( XformWind(windVector,mtx)*((windMul.x+windMul.y)*10.0+30.0)*bend );
					newpos.xyz=normalize(newpos.xyz)*vlen;
					//////////////////////////////////////
				#else
					mtx[0].w=0.0;
					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_
				
					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=vertex;
					#ifdef VEGETATION
						////////////////////////////////////////////
						vec2 dBend=s2_color.gb*windStrenght*bendMul.y;
						float phase=dot(MTX[3].xyz,vec3(1.0,1.0,1.0));
						float phase2=phase+s2_color.r;
						float phase3=phase2+dot(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+=s2_normal.xy*(waves.x*2.0 + waves.z)*dBend.x;
						newpos.y+=(waves.y + waves.w)*dBend.y;
						
						float vlen=length(vertex.xyz);	
						float bend;
						bend=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)*bend);
						newpos.xyz=normalize(newpos.xyz)*vlen;
						//////////////////////////////////////
					#else
						MTX[1].w=0.0;
						MTX[2].w=0.0;
					#endif			
						
					newpos=MTX*newpos;
					gl_Position = (gl_ModelViewProjectionMatrix)*newpos;
				#else
				
					vec4 newpos=vertex;
					#ifdef VEGETATION
						
						vec2 dBend=s2_color.gb*windStrenght*bendMul.y;
						float phase=dot(prevWTM[3].xyz,vec3(1.0,1.0,1.0));
						float phase2=phase+s2_color.r;
						float phase3=phase2+dot(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+=s2_normal.xy*(waves.x*2.0 + waves.z)*dBend.x;
						newpos.y+=(waves.y + waves.w)*dBend.y;
						
						float vlen=length(vertex.xyz);			
						float bend;
						bend=vertex.y*meshbox.y;
						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;
							
						//////////////////////////////////////
					#endif
					
					gl_Position = (gl_ModelViewProjectionMatrix)*newpos;
				#endif
				
			#endif
			
		#endif
		
	#endif

#endif

#ifdef ALPHATEST
	texcoords = s2_texcoords.st*tscale + tofs;
#endif

	depth=gl_Position.zw;
}