
//#include "Types.h"

#ifndef SHADER_MODEL
#define SHADER_MODEL 2
#endif

/*
VS_PROFILE and VS_PROFILE are designed for pass parameters like "vertexshader = compile VS_PROFILE VS_ZBUFFER();"
. In this case, VS_PROFILE will be automatically changed according to the macro SHADER_MODEL, and the fx file
can fit both usage in SM3 and SM2.
*/
#ifndef VS_PROFILE
#if SHADER_MODEL == 3 
#define VS_PROFILE	vs_3_0
#else
#define VS_PROFILE	vs_2_0
#endif
#endif

#ifndef PS_PROFILE
#if SHADER_MODEL == 3
#define PS_PROFILE	ps_3_0
#else
#define PS_PROFILE	ps_2_0
#endif
#endif

#define	SHARED shared

#ifndef PACKTYPE
#define PACKTYPE 0
#endif

//The elements of lightParam is initiated

//Do not change orders of the members, they correspond to a certern struct in engine with the same bit-order;
struct LightParam	
{
	float3 m_dir;
	float4 m_diffuse;
	float4 m_specular;
	float4 m_sceneAmbient;	//this is different from "ambient", the previous "ambient" denotes the ambient of light
	float4 m_sky_light;
	float4 m_com_light;
};

//Do not change orders of the members, they correspond to a certern struct in engine with the same bit-order;
struct MaterialParam
{
	float4 diff;
	float4 ambi;
	float4 spec;
	float4 emis;
	float  specPower;
};



struct MaterialParamEx 
{
	int   bhightlight;
	float4 color_cast;
	float  emssive_power;
	float  spe_exp;
};

struct ShadowMapParam 
{
	int bShadowMask;	//use shadow map or not
	float2 vBiasUV;
	float2 vViewPortWidthHeight;
};

/*These params will not be compiled as shader asm if you do not use them in any ps or vs.
Therefore, no matter how many params you declare here, it will not add any burden to the 
graphic cards. It is the same situation while any C codes are compiled by a qualified complier
, and for any unused codes, they are just declarations. In another aspect, be awared that too 
many declarations do add burden to the compiler itself.
*/

MaterialParamEx materialEx = {
	false,
	{0.f, 0.f, 1.f, 0.f},
	20.0f,
	1.0f,
};	//this is not shared

MaterialParam materialCur = 
{
	{0,0,0,0},
	{0,0,0,0},
	{0,0,0,0},
	{0,0,0,0},
	1,
};	//this is not shared


SHARED LightParam sunLight;
SHARED LightParam playerLight;


SHARED const float3 sky_light_dir  = {0.f,-1.f, 0.f};
SHARED float3 eyes = {0,0,0};		//camera pos

float3 LUMINANCE_VECTOR  =float3(0.2125f, 0.7154f, 0.0721f);;
SHARED float sharpValue = 0;

SHARED float speValue = 0;

//<Env>
SHARED texture tEnv;	//shared Environement Map, used in reflection
samplerCUBE SameplerEnv = sampler_state	//Sampler can not be shared in DX9
{
	Texture   = <tEnv>;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	ADDRESSU = WRAP;
	ADDRESSV = WRAP;
};
//</Env>

//<Conver>
SHARED float4  vConverRect= {0,0,12800,12800};
SHARED texture tConver;
sampler2D SamplerConver = sampler_state
{
	Texture   = <tConver>;
	MipFilter = NONE;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	ADDRESSU = WRAP;
	ADDRESSV = WRAP;
};
float2 ConverUV(float x,float z)
{ 
	float2 uv;
	uv.x  = (x - vConverRect.x)/vConverRect.z;
	uv.y  = (z - vConverRect.y)/vConverRect.w;
	return uv;
}

struct FogParam 
{
	float4 color;
	float  start;
	float  densityDevidedBy_endMinusStart;
	/*Because fogFactor = 1 - ((posZ - start) / (end - start)) * density
	So. fogFactor = 1 - (posZ - start) * A;
	A = density / (end - start)

	We only need A 

	It can also deduce fogFactor = 1 + start * A - posZ * A，
	but it also need 2 params, and few performence can be increased
	*/
};

SHARED FogParam    fogParam;

float CalFogFactor(float fZInView)	//fZInView 只需要传递pos * world * view * proj之后的那个float4的z就可以了，那个z因为是在float4中，所以没有正规化，就是view的z，（proj矩阵一般不改z，所以不用单独求view坐标的z），只有除了w之后那个才是0-1的
{
	float fTemp = 1 - (fZInView - fogParam.start) * fogParam.densityDevidedBy_endMinusStart;
	return saturate(fTemp);
}


float4 CalFogColor(float4 color, float fFogFactor)
{
	return float4(lerp(fogParam.color.rgb, color.rgb, fFogFactor).rgb, color.a);
}

float4 PackingFloatToRGB(float fValue)
{
	float4 color = float4(0,0,0,0);
#if PACKTYPE == 1
	//float4 bitSh = float4(256*256*256,256*256,256,1);
	//float4 bitMsk = float4(0,1.0/256.0,1.0/256.0,1.0/256.0);
	float4 bitSh = float4(1,256,256 * 256, 256*256*256);
	float4 bitMsk = float4(1.0/256.0,1.0/256.0,1.0/256.0,0);
	color	= fValue * bitSh;
	color	= frac(color);
	//if (abs(fValue - 1) < 0.00000000001)
	//	color = float4(1,0,0,0);

	color	-= color.yzww * bitMsk;
#else
    color.rgb = fValue;
#endif
   return color;
}

float3 normalCheckVS(float3 iNormal, float4x4 matWorld)
{
	//return abs(normalize(iNormal));
	return abs(normalize(mul(iNormal, (float3x3)matWorld))); 
}

//float4*4 matWorldViewProj;
//float4*4 matWorld;
//float4*4 matWorldInverse;
//float4*4 matWorldInverseTranspose;
//float4*4 matWroldViewInverse;

float4x4 wvp : WorldViewProjection < string UIType = "None"; >;  
float4x4 worldI : WorldInverse < string UIType = "None"; >;  
float4x4 worldIT : WorldInverseTranspose < string UIType = "None"; >;  
float4x4 viewInv : ViewInverse < string UIType = "None"; >;  
float4x4 world : World < string UIType = "None"; >;  
//SHARED worldforNormal;

float3x3 invert_3x3( float3x3 M )
{
	float D = determinant( M );		
	float3x3 T = transpose( M );	

	return float3x3(
		cross( T[1], T[2] ),
		cross( T[2], T[0] ),
		cross( T[0], T[1] ) ) / D;	
}

float3x3 GetWorldMatrixforNormal()
{
    float3x3 worldForNormal;
    worldForNormal[0] = world[0].xyz;
    worldForNormal[1] = world[1].xyz;
    worldForNormal[2] = world[2].xyz;
    worldForNormal = invert_3x3(worldForNormal);
    worldForNormal = transpose(worldForNormal);
    return worldForNormal;
}

//XX
SHARED float3 LookInterTerrain = {0,0,0};
//<FogOfWar>
SHARED float fOutRgnClr = 1.f;
SHARED texture tFogOfWar;
sampler2D SamplerFogOfWar = sampler_state
{
    Texture   = <tFogOfWar>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    ADDRESSU = CLAMP;
    ADDRESSV = CLAMP;
};
//</FogOfWar>

SHARED float2 FogSize = float2(-10.f, -10.f);
float4 tex2D_FogOfWar(float2 pos)
{
    float2 uv = 0.f;
    float4 eyesRect = {LookInterTerrain.x - FogSize.x * 0.5f, LookInterTerrain.z + FogSize.y * 0.5f, 
    LookInterTerrain.x + FogSize.x * 0.5f, LookInterTerrain.z - FogSize.y * 0.5f};
    float2 leftTop = ConverUV(eyesRect.x, eyesRect.y);
    float2 rightDown = ConverUV(eyesRect.z, eyesRect.w);
    float2 converSize = FogSize / vConverRect.zw;
    
    if(pos.y >= leftTop.y && pos.y < rightDown.y &&
       pos.x >= leftTop.x && pos.x < rightDown.x)
    {
       uv.x = (pos.x - leftTop.x) / converSize.x;
       uv.y = (pos.y - leftTop.y) / converSize.y;
       return tex2D(SamplerFogOfWar, uv);
    }
    else
       return float4(fOutRgnClr, fOutRgnClr, fOutRgnClr, 1.f);
}

SHARED texture tPtLightColor;
sampler2D SamplerPtLightCol = sampler_state
{
    Texture   = <tPtLightColor>;
    MipFilter = POINT;//LINEAR;//
    MinFilter = POINT;//LINEAR;//
    MagFilter = POINT;//LINEAR;//
    ADDRESSU = CLAMP;
    ADDRESSV = CLAMP;
};
SHARED float2 g_ScreenSize = 0;

float3 tex2D_PointLight(float3 normal,float3 ScreenPos)	//参数大多跟迷雾一样
{
	float2 uv = (ScreenPos.xy)/g_ScreenSize.xy;
	ScreenPos.x = 2.0f*uv.x-1.0f;//(uv.x-0.5f)*2.0f;
	ScreenPos.y = 1.0f - 2.0f*uv.y;// - (uv.y-0.5f)*2.0f;
	
	float4 color = tex2D(SamplerPtLightCol,uv);
	return color.rgb;
}

#define LINEARDEPTH 1
SHARED float4x4 WorldView; 
SHARED float2   CameraPlane;

float2 ComputeZW(float3 Pos,float4 pos_wvp)
{
	float2 Out;
#if LINEARDEPTH == 1
	float4 Pos_View = mul(float4(Pos,1),WorldView);
	Out.x = Pos_View.z;
	Out.y = 1;
#else
	Out.x = pos_wvp.z;
	Out.y = pos_wvp.w;
#endif
	return Out;
}

float3 ComputeLinearDepth(float2 PosZW)
{
	float3 Out;

#if LINEARDEPTH == 1
	float lz = (PosZW.x - CameraPlane.x)/(CameraPlane.y - CameraPlane.x);
	Out.rgb = PackingFloatToRGB(lz).rgb;
#else
	Out.rgb = PackingFloatToRGB(PosZW.x / PosZW.y).rgb;
#endif
	return Out;
}

