varying vec2 		texcoord;

uniform sampler2D 	dif0,
					bmp0,
					noisemap;
					
#ifdef _HEIGHTMAP_	
	uniform sampler2D	heightmap;
#else
	uniform sampler2D	thickness;
#endif

uniform vec2		fresnel0,
					spec0;
uniform vec4		dcolor0,
					scolor0;
uniform vec2		dscale0,
					bscale0;
uniform vec2		dofs0,
					bofs0;
uniform float 		scatterlevel;
uniform float 		scatterRed;
uniform float 		backScatter;
uniform float		wFar;

uniform float		matID;

#ifdef VEGETATION
	#ifndef BSET
		#ifndef MSET
			varying vec3	vgColor;
		#endif
	#endif
#endif
	
#ifdef ALPHATEST

	uniform float 		alphalevel;
	varying float		alphaFade;
	
#endif

#ifdef PSYSTEM

	varying float 	life;
	varying float	cosa,
			sina;
					
#else

	#ifdef BSET

		varying vec4 pnormal;
		varying vec4 pcolor;
		
		/////////////////////
		varying mat3	TBN;
		////////////////////
		
	#else
	
		varying mat3	TBN;
		
		#ifdef MSET
		varying vec4 pcolor;
		uniform float terrainColorAmount;
		#else
			varying float occlusion; 
		#endif
		
	#endif
		
#endif				


#ifdef LAYER1

	uniform vec3		maskMul;

	uniform sampler2D 	lmask;
	uniform sampler2D 	dif1,
						bmp1;
	uniform vec2		fresnel1,
						spec1;
	uniform vec4		dcolor1,
						scolor1;
	uniform vec2		dscale1,
						bscale1;
	uniform vec2		dofs1,
						bofs1;
						
	uniform vec3		lParams1;
						
	#ifdef LAYER2
		uniform sampler2D 	dif2,
							bmp2;
		uniform vec2		fresnel2,
							spec2;
		uniform vec4		dcolor2,
							scolor2;
		uniform vec2		dscale2,
							bscale2;
		uniform vec2		dofs2,
					bofs2;		
		uniform vec3		lParams2;							
							
		#ifdef LAYER3
			uniform sampler2D 	dif3,
								bmp3;
			uniform vec2		fresnel3,
								spec3;
			uniform vec4		dcolor3,
								scolor3;
			uniform vec2		dscale3,
								bscale3;
			uniform vec2		dofs3,
								bofs3;
			uniform vec3		lParams3;	
		#endif

	#endif

#endif


#ifdef _HEIGHTMAP_

	uniform sampler2D	baseTex;
	uniform sampler2D	cmask;
	//varying vec3	vColor;
	//varying float	vSlope;
	// uniform vec3		invTerrainDim;
	uniform vec2 		baseFarCoords;
	varying vec2 		baseCoords;
	uniform vec3		baseTexParams;
	//varying vec3		wNormal;
	varying float		NWheight;
	uniform float		baseGloss;
	uniform float 		bumpScale;
	
	uniform vec2		invHeightmapSize;
	
#endif

varying vec4 		curpos,pos,prev;
uniform float		vScale;

uniform float 		fade;

//varying vec2 depth;

vec2 encode(vec3 n)
{
	n=normalize(n);
    float f = sqrt(8.0*n.z+8.0);
    return n.xy / f + 0.5;
}

/*half3 decode (half4 enc, float3 view)
{
    half2 fenc = enc*4-2;
    half f = dot(fenc,fenc);
    half g = sqrt(1-f/4);
    half3 n;
    n.xy = fenc*g;
    n.z = 1-f/2;
    return n;
}*/

void main()
{
	//vec2 screenCoords=prev.xy;
	
	#ifdef PSYSTEM
	
		if(life<=0.0)
			discard;
			
	#endif

	vec4 	texcolor;
	vec4 	fdcolor,
			fbcolor;
	vec3	fnormal;
	vec2	fspec,
			ffresnel;
			
	#ifndef _HEIGHTMAP_		
		#ifdef MACRODIFFUSE	
			vec4 baseColor=texture2D(dif0,texcoord.st*dscale0+dofs0);
			baseColor.rgb=pow(baseColor.rgb,vec3(2.2))*dcolor0.rgb;
			fdcolor=vec4(1.0,1.0,1.0,baseColor.a);
		#else
			fdcolor=texture2D(dif0,texcoord.st*dscale0+dofs0);
			fdcolor.rgb=pow(fdcolor.rgb,vec3(2.2))*dcolor0.rgb;
		#endif
	#endif
	
	#ifdef ALPHATEST

		#ifdef PSYSTEM
			float alpha=fdcolor.a*life;
			if(alpha<=alphalevel)
				discard;
		#else
			#ifdef BSET
				float alpha=texture2D(noisemap,curpos.st*vec2(0.0125)).r;
				if(alpha>pcolor.w)
					discard;
			#else
				#ifdef MSET
					float alpha=texture2D(noisemap,curpos.st*vec2(0.0125)).r;
					if(alpha>fade)
						discard;
				#else
					#ifdef _HEIGHTMAP_
					#else
						#ifdef SKINNING
						#else
							#ifndef _NOT_INSTANCED_
								float alpha=texture2D(noisemap,curpos.st*vec2(0.0125)).r;
								if(alpha>alphaFade)
									discard;
							#else
								float alpha=texture2D(noisemap,curpos.st*vec2(0.0125)).r;
								if(alpha>fade)
									discard;
							#endif
						#endif
					#endif
				#endif
			#endif
			
			#ifdef BSET
				if(fdcolor.a<=alphalevel)
					discard;
			#else
				if(fdcolor.a<=mix(alphalevel,alphalevel*0.8,clamp(curpos.z*25000.0-4500.0,0.0,1.0)))
					discard;
			#endif
		#endif
		
	#endif

	#ifdef MACROBUMP
		
		vec4 baseNormal=texture2D(bmp0,texcoord.st*bscale0+bofs0);
		baseNormal.xy=(baseNormal.xy*2.0-1.0);
		fnormal=vec3(0,0,0);
	//	fspec.x=0.0;
		ffresnel.x=fresnel0.x*baseNormal.a;
		ffresnel.y=fresnel0.y*baseNormal.z;//1.0;//basefresnel;
		//float basefresnel=fresnel0.y*baseNormal.z;
		baseNormal.z=sqrt(1.0-baseNormal.x*baseNormal.x-baseNormal.y*baseNormal.y);
		
	#else

		#ifdef BSET
		
		#else
			fbcolor=texture2D(bmp0,texcoord.st*bscale0+bofs0);
			fnormal.xy=(fbcolor.xy*2.0-1.0);
		#endif

		ffresnel.x=fresnel0.x*fbcolor.a;
		ffresnel.y=fresnel0.y*fbcolor.z;

	#endif

	#ifdef _HEIGHTMAP_
	
	/* PROVA NORMAL COMPUTATION */
		float 	h00,
				h10,
				h01;
		h00=texture2D(heightmap,texcoord.st).r;
		h10=texture2D(heightmap,texcoord.st+vec2(invHeightmapSize.x,0.0)).r;
		h01=texture2D(heightmap,texcoord.st+vec2(0.0,invHeightmapSize.y)).r;
		
		vec3 binormal3=(vec3(0.0,0.0,h00)-vec3(invHeightmapSize.x*bumpScale,0.0,h10));
		vec3 tangent3=(vec3(0.0,0.0,h00)-vec3(0.0,invHeightmapSize.y*bumpScale,h01));
		vec3 normal3=normalize(cross(binormal3,tangent3));
	//	binormal3=cross(normal3,vec3(1.0,0.0,0.0));
	//	tangent3=cross(binormal3,normal3);
	//	normal3.xy=normal3.yx;
		normal3.y=-normal3.y;
	//	fnormal=normalize(normal3+vec3(fnormal.x,fnormal.y,0.0));//*4.0);
		/* ------------------------ */
		
		float t=clamp(-pos.z*0.000025,0.0,1.0);
		float t0=clamp(-pos.z*0.0005,0.0,1.0);
		
		vec2 texcoord0=texcoord.st*bscale0+bofs0;
		vec4 detailNormal=texture2D(bmp0,texcoord0*8.0);
		detailNormal.xy=(detailNormal.xy*2.0-1.0);
		fbcolor=texture2D(bmp0,texcoord.st*baseFarCoords);
		
		ffresnel.y=mix(ffresnel.y,fresnel0.y*fbcolor.z,t);
		ffresnel.y=mix(fresnel0.y*detailNormal.z,ffresnel.y,t0);
		
		detailNormal.z=0.0;//sqrt(1.0-detailNormal.x*detailNormal.x-detailNormal.y*detailNormal.y);
		
		fbcolor.xy=(fbcolor.xy*2.0-1.0);
		fbcolor.z=sqrt(1.0-fbcolor.x*fbcolor.x-fbcolor.y*fbcolor.y);
		
		/* ----------- */  
		//fbcolor.xyz=normal3;
		/* ------------- */
		
		fnormal.z=sqrt(1.0-fnormal.x*fnormal.x-fnormal.y*fnormal.y);
	
		fnormal=fbcolor.xyz + fnormal + detailNormal.xyz;		
		vec4 f0=pow(texture2D(dif0,texcoord.st*baseFarCoords),vec4(2.2));
		vec3 baseNormal=fnormal;
		
		//vec3 wNormalTex=mix(fnormal,vec3(0.0,0.0,0.0),t);
		/* ****************** */
		//wNormal=normalize(wNormal+normal3);
		/* ****************** */
		
		float dotNUp=abs(dot(normalize(vec3(detailNormal.x,detailNormal.y,0.0)+normal3),vec3(0.0,0.0,1.0)));
		float vSlope=dotNUp;
		float vSlopeHeight;
		vSlope=clamp( pow((vSlope-baseTexParams.x)*baseTexParams.z,6.0), 0.0,1.0);
		vSlopeHeight=vSlope*(1.0 - clamp( (NWheight-baseTexParams.y)*1000.0, 0.0,1.0));
		
		//float invSlope=1.0-vSlope;
		fbcolor.xyz=vec3(0.0,0.0,1.0);//normalize(fbcolor.xyz+vec3(0.0,0.0,2.0));
		fnormal=mix(normalize(fnormal),fbcolor.xyz,vSlope);//fbcolor.xyz*vSlope + invSlope*fnormal;
		
		texcoord0=texcoord.st*dscale0+dofs0;
		vec4 fdcolor0=pow(texture2D(dif0,texcoord0),vec4(2.2));
		fdcolor0=mix(fdcolor0,f0,t);
		
		fdcolor=pow(texture2D(dif0,texcoord0*8.0),vec4(2.2))*dcolor0;
		fdcolor=mix(fdcolor,fdcolor0,t0);
		
		vec4 baseColor=texture2D(baseTex,baseCoords);
		baseColor.rgb=pow(baseColor.rgb,vec3(2.2));
		
		float alphat=mix(baseColor.a,1.0,t);
				
		fdcolor.xyz=mix(fdcolor.xyz,baseColor.xyz,vSlopeHeight*alphat);//baseColor.xyz*vSlope + invSlope*fdcolor.xyz;	
		ffresnel.y=mix(ffresnel.y,baseColor.a*baseGloss,vSlopeHeight*baseColor.a);//baseColor.a*vSlope+invSlope*ffresnel.y;
		//ffresnel.x=mix(ffresnel.x,baseColor.a,vSlopeHeight*baseColor.a);//baseColor.a*vSlope+invSlope*ffresnel.y;
		
		float vSlope1=0.0;
		float vSlope2=0.0;
		float vSlope3=0.0;
				
	#endif

	#ifdef LAYER1

//	#ifdef _HEIGHTMAP_
		vec3 	mask=vec3(1.0,1.0,1.0);
		if(-pos.z<10000.0)
		{
		//	float fade=1.0-clamp( (-pos.z-9000.0)/1000.0,0.0,1.0);
//	#endif
			mask=clamp(texture2D(lmask,texcoord.st).rgb*maskMul,vec3(0.0),vec3(1.0));
					
//		#ifdef _HEIGHTMAP_
			
			//float rangeMin=10000.0;//15000.0-5000.0;
			vec3 fadedmask=mix(mask,vec3(0.0,0.0,0.0),( clamp( (-pos.z-7000.0/*rangeMin*/)/(3000.0/*15000.0-rangeMin*/),0.0,1.0) ));
			
//		#endif
			vec3	compMask;//=vec3(1.0,1.0,1.0)-fadedmask;
						
			texcolor=texture2D(dif1,texcoord.st*dscale1+dofs1);
			texcolor.rgb=pow(texcolor.rgb,vec3(2.2));
			fadedmask.r*=texcolor.a;
			
			/*float dist=(-pos.z-fade*0.8)/(fade*0.2);
			float fadeAlpha=(1.0 - (clamp(dist,0.0,1.0)));*/
			#ifdef _HEIGHTMAP_
				vSlope1=dotNUp;//abs(dot(normalize(vec3(detailNormal.x,detailNormal.y,0.0)+normal3),vec3(0.0,0.0,1.0)));
				vSlope1=clamp( pow((vSlope1-lParams1.x)*lParams1.z,6.0), 0.0,1.0);
				vSlope=mix(vSlope,vSlope1,fadedmask.r);
				vSlope1*=(1.0 - clamp( (NWheight-lParams1.y)*1000.0, 0.0,1.0));
				vSlopeHeight=mix(vSlopeHeight,vSlope1,fadedmask.r);
				
				fadedmask.r=vSlopeHeight*fadedmask.r;
			#endif
			compMask.r=1.0-fadedmask.r;
				
			fdcolor=mix(fdcolor,texcolor*dcolor1,fadedmask.r);//texture2D(dif1,texcoord.st*dscale1+dofs1)*dcolor1*mask.r + (compMask.r)*fdcolor;	
			fbcolor=texture2D(bmp1,texcoord.st*bscale1+bofs1);
			fnormal.xy=(fbcolor.xy*2.0-1.0)*fadedmask.r + (compMask.r)*fnormal.xy;
			ffresnel.y=fresnel1.y*fbcolor.z*fadedmask.r + (compMask.r)*ffresnel.y;
			ffresnel.x=fbcolor.a*fresnel1.x*fadedmask.r + (compMask.r)*ffresnel.x;
			
			#ifdef LAYER2
			
				texcolor=texture2D(dif2,texcoord.st*dscale2+dofs2);
				texcolor.rgb=pow(texcolor.rgb,vec3(2.2));
				fadedmask.g*=texcolor.a;
				
				#ifdef _HEIGHTMAP_
					vSlope2=dotNUp;//abs(dot(normalize(vec3(detailNormal.x,detailNormal.y,0.0)+normal3),vec3(0.0,0.0,1.0)));
					vSlope2=clamp( pow((vSlope2-lParams2.x)*lParams2.z,6.0), 0.0,1.0);
					vSlope=mix(vSlope,vSlope2,fadedmask.g);
					vSlope2*=(1.0 - clamp( (NWheight-lParams2.y)*1000.0, 0.0,1.0));
					vSlopeHeight=mix(vSlopeHeight,vSlope2,fadedmask.g);
					
					fadedmask.g=vSlopeHeight*fadedmask.g;
				#endif
				compMask.g=1.0-fadedmask.g;
			
				fdcolor=mix(fdcolor,texcolor*dcolor2,fadedmask.g);//texture2D(dif2,texcoord.st*dscale2+dofs2)*dcolor2*mask.g + (compMask.g)*fdcolor;	
				fbcolor=texture2D(bmp2,texcoord.st*bscale2+bofs2);
				fnormal.xy=(fbcolor.xy*2.0-1.0)*fadedmask.g + (compMask.g)*fnormal.xy;
				ffresnel.y=fresnel2.y*fbcolor.z*fadedmask.g + (compMask.g)*ffresnel.y;
				ffresnel.x=fbcolor.a*fresnel2.x*fadedmask.g + (compMask.g)*ffresnel.x;
				
				#ifdef LAYER3
				
					texcolor=texture2D(dif3,texcoord.st*dscale3+dofs3);
					texcolor.rgb=pow(texcolor.rgb,vec3(2.2));
					fadedmask.b*=texcolor.a;
				
					#ifdef _HEIGHTMAP_
						vSlope3=dotNUp;//abs(dot(normalize(vec3(detailNormal.x,detailNormal.y,0.0)+normal3),vec3(0.0,0.0,1.0)));
						vSlope3=clamp( pow((vSlope3-lParams3.x)*lParams3.z,6.0), 0.0,1.0);
						vSlope=mix(vSlope,vSlope3,fadedmask.b);
						vSlope3*=(1.0 - clamp( (NWheight-lParams3.y)*1000.0, 0.0,1.0));
						vSlopeHeight=mix(vSlopeHeight,vSlope3,fadedmask.b);
						
						fadedmask.b=vSlopeHeight*fadedmask.b;
						
					#endif
					compMask.b=1.0-fadedmask.b;
				
					fdcolor=mix(fdcolor,texcolor*dcolor3,fadedmask.b);//texture2D(dif3,texcoord.st*dscale3+dofs3)*dcolor3*mask.b + (compMask.b)*fdcolor;	
					fbcolor=texture2D(bmp3,texcoord.st*bscale3+bofs3);
					fnormal.xy=(fbcolor.xy*2.0-1.0)*fadedmask.b + (compMask.b)*fnormal.xy;
					ffresnel.y=fresnel3.y*fbcolor.z*fadedmask.b + (compMask.b)*ffresnel.y;
					ffresnel.x=fbcolor.a*fresnel3.x*fadedmask.g + (compMask.g)*ffresnel.x;
					
					
					
				#endif

			#endif
			
//	#ifdef _HEIGHTMAP_
		}
		
//	#endif
		
	#endif

	#ifdef MACROBUMP

		fnormal.z=0.0;
		fnormal=baseNormal.xyz+fnormal;
		normalize(fnormal);
		//ffresnel.y*=basefresnel;
		
	#else
	
		// normalize resultant normal
		fnormal.z=sqrt(1.0-fnormal.x*fnormal.x-fnormal.y*fnormal.y);
	//	normalize(fnormal);
	
	#endif
	
	#ifdef MACRODIFFUSE	
		fdcolor.rgb=baseColor.rgb*fdcolor.rgb;
	#endif

	
	#ifdef _HEIGHTMAP_

		vec3 one=vec3(1.0,1.0,1.0);
		vec3 two=vec3(2.0,2.0,2.0);
		vec3 mid=vec3(0.5,0.5,0.5);
		vec3 textureColor=pow(texture2D(cmask,texcoord.st).rgb,vec3(2.2));
		
		vec3 maskColor=textureColor;//mix(mid,textureColor,vSlope);
		
		vec3 rmul=fdcolor.rgb*maskColor.rgb;
		vec3 rscr=one-((one-maskColor.rgb)*(one-fdcolor.rgb));
		fdcolor.rgb=fdcolor.rgb*rscr+(one-fdcolor.rgb)*rmul;
		
		//fdcolor.rgb*=maskColor.a;	// occlusion
		
		//fdcolor.rgb*=maskColor;//vColor;
		
	/*	vec3 A=step(fdcolor.rgb,mid);
		
		fdcolor.rgb = A*(one - (one - maskColor.rgb)*(one-two*(fdcolor.rgb-mid))) + 
		(one-A)*(maskColor.rgb * (two* fdcolor.rgb));
		*/
	#endif

	#ifndef _HEIGHTMAP_
		float scatterMask=texture2D(thickness,texcoord).r;
		fdcolor.a=scatterlevel*scatterMask;
	#else
		fnormal=normalize(normal3+vec3(fnormal.x,fnormal.y,0.0));//*4.0);
		fdcolor.a=0.0;
	#endif
	
	#ifdef VEGETATION
		#ifndef BSET
			#ifndef MSET
				vec3 one=vec3(1.0,1.0,1.0);
				vec3 rmul=fdcolor.rgb*vgColor.xyz;
				vec3 rscr=one-((one-vgColor.xyz)*(one-fdcolor.rgb));
				fdcolor.rgb=fdcolor.rgb*rscr+(one-fdcolor.rgb)*rmul;
			#endif
		#endif
	#endif
	
	gl_FragData[0]=fdcolor;

	#ifdef PSYSTEM
			
		gl_FragData[1].xy=encode(vec3((fnormal.x*cosa)+(fnormal.y*sina),(fnormal.x*sina)-(fnormal.y*cosa),fnormal.z));
			
	#else
		
		#ifdef BSET
			
			vec3 one=vec3(1.0,1.0,1.0);
			vec3 rmul=gl_FragData[0].rgb*pcolor.xyz;
			vec3 rscr=one-((one-pcolor.xyz)*(one-gl_FragData[0].rgb));
			gl_FragData[0].rgb=gl_FragData[0].rgb*rscr+(one-gl_FragData[0].rgb)*rmul;
		
			//gl_FragData[0].xyz = max(gl_FragData[0].xyz*pcolor.xyz,0.0);
			//fnormal.z=sqrt(1.0-fnormal.x*fnormal.x-fnormal.y*fnormal.y);
			
			gl_FragData[1].xy = encode(pnormal.xyz);
			
			//gl_FragData[1].xy=encode(TBN*fnormal.xyz);
			
		#else
		
			// normal
			gl_FragData[1].xy=encode(TBN*fnormal.xyz);
			
			#ifdef MSET
			vec3 one=vec3(1.0,1.0,1.0);
			vec3 rmul=gl_FragData[0].rgb*pcolor.xyz;
			vec3 rscr=one-((one-pcolor.xyz)*(one-gl_FragData[0].rgb));
			gl_FragData[0].rgb=mix(gl_FragData[0].rgb,gl_FragData[0].rgb*rscr+(one-gl_FragData[0].rgb)*rmul,terrainColorAmount);
			#else
				#ifdef SKINNING
				#else
					#ifdef _HEIGHTMAP_
					#else
						gl_FragData[0]*=occlusion; 
					#endif
				#endif
			#endif
			
		#endif
			
	#endif
	
	gl_FragData[1].z=ffresnel.x;//*0.0625;// /16.0;
	gl_FragData[1].a=backScatter;//*scatterMask;
	
	// pos
	vec2 vel=((curpos.xy/curpos.w)-(prev.xy/prev.w))*vScale;///*0.05*/*vScale;
	
	// material params
	gl_FragData[2].r=matID;//scatterlevel*scatterMask; //COSINE POWER (SHININESS) //(floor(glossPow)*32.0 + floor(fspec.y));//fspec.x;	GlossScale=[0...32]
	gl_FragData[2].g=ffresnel.y/256.0; //1.0/256.0; //Fresnel (SPECULAR REFLECTANCE)//0.0;//fspec.y;
	gl_FragData[2].ba=(vel*vec2(0.5))+vec2(0.5);//0.0;//floor(fresnPow)*32.0 + floor((ffresnel.y/4.0)*32.0);//);//fspec.x;	fresnScale=[0...32]
	//gl_FragData[2].a=0.0;//ffresnel.x;
	
	/*gl_FragData[1].xy = vel;
	gl_FragData[1].z = pos.z;//wFar;
	
	// scatter
	gl_FragData[1].a=0.0;//scatterlevel;//floor(scatterlevel*256.0)+scatterRed;*/
}
