/*
	Xform "Texture Splatting shader" DEMO
	Made by Joep Peters during internship at Xform (www.xform.nl), 2007
	Partially based on examples found online.
	
	This shader can blend up to 4 diffuse textures on an object, which can be usefull when
	creating large landscapes. It also supports lightmapping, fog and burning. Pixelshader 2.0 and up.
	
	LICENCE : 
	This shader is Art-ware. 
	This means that the shader is free for use in personal as well as commercial projects. 
	HOWEVER, if you make something beautiful with it, you are obliged to post a screenshot, vmo or cmo on the swapmeet forum!  
	Any possible damage (physically AND mentally) by this shader is totally your own responsibility... ;)
	
	For any questions or suggestions: info@xform.nl
	
*/

// matrix values
float4x4 wvp : WORLDVIEWPROJECTION;
float3x3 itworld : ITWORLD;
float4x4 view : VIEW;
float4x4 vp : VIEWPROJECTION;

// texture init
texture texBaseDiffuse: BaseDiffuseMap< 
	string name = ""; 
	string UIName = "BaseDiffuse Map";
		int Texcoord = 0;
	int MapChannel = 1;
	>;

texture texDiffuse1: Diffuse1Map< 
	string name = ""; 
	string UIName = "Diffuse1 Map";
		int Texcoord = 0;
	int MapChannel = 1;	
	>;

texture texDiffuse2: Diffuse2Map< 
	string name = ""; 
	string UIName = "Diffuse2 Map";
		int Texcoord = 0;
	int MapChannel = 1;	
	>;

texture texDiffuse3: Diffuse3Map< 
	string name = ""; 
	string UIName = "Diffuse3 Map";
		int Texcoord = 0;
	int MapChannel = 1;	
	>;

texture texMask: Maskmap< 
	string name = ""; 
	string UIName = "mask Map";
	int Texcoord = 1;
	int MapChannel = 1;		
	>;

texture texLightmap: LightMap< 
	string name = ""; 
	string UIName = "Light Map";
	int Texcoord = 1;
	int MapChannel = 1;	
	>;


// texture samplers, change filtering settings here
sampler2D TextureBaseDiffuse =  sampler_state {
	 texture = <texBaseDiffuse>;
     MinFilter = LINEAR;
     MagFilter = LINEAR;
};  
	

sampler2D TextureDiffuse1 =  sampler_state {
	 texture = <texDiffuse1>;
	 MinFilter = LINEAR;
     MagFilter = LINEAR;
	 MipFilter = LINEAR;
}; 

sampler2D TextureDiffuse2 =  sampler_state {
	 texture = <texDiffuse2>; 
	 MinFilter = LINEAR;
     MagFilter = LINEAR;
	 MipFilter = LINEAR;
}; 

sampler2D TextureDiffuse3 =  sampler_state {
	 texture = <texDiffuse3>; 
	 MinFilter = LINEAR;
     MagFilter = LINEAR;
	 MipFilter = LINEAR;
}; 

sampler2D TextureMask = sampler_state { 
	texture = <texMask>;
     MinFilter = LINEAR;
     MagFilter = LINEAR;
	 MipFilter = LINEAR;
}; 

sampler2D TextureLightmap = sampler_state { 
	texture = <texLightmap>;
     MinFilter = LINEAR;
     MagFilter = LINEAR;
	 MipFilter = LINEAR;
}; 

// fog, diff, emissive colors, burn paramters
bool lightmap<
    string UIName = "Lightmap";

>;
bool fog<
    string UIName = "Fog";

>;
float4 fogcolor <
	string UIName = "Fog Color"; 
	string UIType = "MaxSwatch";
	>;
float fognear<string UIName = "fognear";
	string UIType = "FloatSlider";
float UIMin=0; float UIMax=4000;>   = 100; 

float fogfar<string UIName = "fogfar";
	string UIType = "FloatSpinner";
float UIMin=0; float UIMax=4000;>   = 150;
float4 colorEmissive<
	string UIName = "Emissive Color"; 
	string UIType = "MaxSwatch";
	>;
float4 colorDiffuse<
	string UIName = "Diffuse Color"; 
	string UIType = "MaxSwatch";
	>;
float burn <string UIName = "burn";
	string UIType = "FloatSpinner";
float UIMin=0; float UIMax=5;>   = 3; 

//vertex shader in en out structs
struct VSIN {
	float3 pos : POSITION;
	float4 col : COLOR;
	float3 norm : NORMAL;
	float2 uv : TEXCOORD0;
	float2 uv2 : TEXCOORD1;

};

struct VSOUT {
	float4 pos : POSITION;
	float4 col : COLOR;
	float2 uv : TEXCOORD0;
	float2 uv2 : TEXCOORD1;
};

//Getting the light position
float3 LightPos<  string UIName = "Light Position"; string Object = "PointLight";>;
float4 LightCol<string UIName = "Light color";
float4 Default={1,1,1,0};>;

// Something with light intenstity....
float overflowingDiffuse <
	string UIName = "Overflowingdiffuse";
	string UIType = "MaxSpinner";
float UIMin=-1; float UIMax=1;> = 0.3;
static float4 combinedDif = colorDiffuse * LightCol;

//vertex shader
VSOUT Diffuse_VS( VSIN vsIn )
{
	//Create variable vsOut as VSOUT
	VSOUT vsOut;
	
	//calculate the position vector
	vsOut.pos = mul( float4(vsIn.pos,1), wvp );

	//calculate the light settings
	float3 lightDir = normalize(LightPos-vsIn.pos);
	float lightDot = dot( vsIn.norm, lightDir );

	lightDot += -lightDot*overflowingDiffuse+overflowingDiffuse;

	//combine the diffuse with the light
	float4 col = saturate(combinedDif * lightDot);
	
	//define all the variables	
	vsOut.col = colorEmissive + col; 
	vsOut.uv = vsIn.uv;
	vsOut.uv2 = vsIn.uv2;
	
	//return the variable 
	return vsOut;
}

//pixelshader
float4 Diffuse_PS( VSOUT psIn ) : COLOR
{

	// color variables
	float4 result;
	float4 diffuseColor;

	// initialize diffuse colors
	diffuseColor= tex2D(TextureBaseDiffuse , psIn.uv);
	
	// initialize all color layers
	float4 ColorLayer1 = tex2D(TextureDiffuse1 , psIn.uv);
	float4 ColorLayer2 = tex2D(TextureDiffuse2 , psIn.uv);
	float4 ColorLayer3 = tex2D(TextureDiffuse3 , psIn.uv);
	
	//reverse uv's
	//psIn.uv2.y = 1 - psIn.uv2.y;
	
	// get the alpha and light colors 
	float4 AlphaLayer = tex2D(TextureMask , psIn.uv2);
	float4 LightLayer = tex2D(TextureLightmap, psIn.uv2);	
	
	//caculate the first layer
	result=  ((diffuseColor*(1-AlphaLayer.r)) + ColorLayer1*(AlphaLayer.r))/2;
	
	//calculate the second..
	result=  ((result*(1-AlphaLayer.g)*2) + ColorLayer2*(AlphaLayer.g))/2;
	
	// and third
	result= ((result*(1-AlphaLayer.b)*2) + ColorLayer3*(AlphaLayer.b))/2;
	
	// get the vertex colors from the lighting and store them in 'ex'
	float4 ex = psIn.col ;
	
	// create a final color variable
	float4 finalcolor;
	
	//combine the vertex lighting with the diffuse texture
	finalcolor = (ex*2) * (result);
	
	//if there is a lightmap.. then apply it
	if(lightmap){
		finalcolor = (finalcolor * LightLayer) * burn;
	}
	else{
		finalcolor = finalcolor * burn;
	}
	
	// return the color and draw it!
	return finalcolor;
}

technique tech
{
	pass p
	{
		
		FogEnable     = <fog>; 
      	FogColor      = <fogcolor>; 
      	FogDensity    = 0; 

      	// pixelshader fog
      	FogVertexMode  = NONE; 
      	FogTableMode   = LINEAR;

      	// Fog distance settings
      	FogStart      = <fognear>; 
      	FogEnd        = <fogfar>; 
	
		VertexShader = compile vs_1_1 Diffuse_VS();
		PixelShader = compile ps_2_0 Diffuse_PS(); 
			
	}
}
