//--------------------------------------------------------------------------
//
// WHALE ENGINE 1.0
// LGM GAMES
// DIRECT X9c
// SHADER v2.0
//          
//--------------------------------------------------------------------------

static const float BRIGHT_PASS_THRESHOLD = 0.85;

static const float HDR_MIDLEGRAY = 0.4;
static const float STAR_HDR_MIDLEGRAY = 0.32;

static const float BRIGHT_PASS_HDR_THRESHOLD = 0.7;
static const float BRIGHT_PASS_HDR_OFFSET    = 1.4;    

static const float STAR_BRIGHT_PASS_HDR_THRESHOLD = 1.2;
static const float STAR_BRIGHT_PASS_HDR_OFFSET    = 2.4;

matrix ViewProjMatrix;
float4	tcLumOffsets[2];

texture tDif; // difuse map
texture Tone; // tone map


texture TextureDifuse;            
texture TextureLightMap;                 
texture TextureNormalMap;
texture TextureCubeMap;                 
texture TextureShadowMap;

float    g_fTime;                    // App's time in seconds
float4	 g_fScale;
float4x4 g_mWorld;                    // World matrix for object
float4x4 g_mWorldViewProjection;    // World * View * Projection matrix
float4x4 g_mShadowProjection;
vector   CameraPosition;
vector   g_LightAmbient =  {1.0f, 1.0f, 1.0f, 1.0f};
float4   UV; //Umin, Umax, Vmin, Vmax
vector   ExtraVector = { 0.5f, 0.5f, 0.5f, 0.5f }; 

//--------------------------------------------------------------------------
// Vertex shader
//--------------------------------------------------------------------------
struct VS_INPUT
{
 float4 Position : POSITION;
 float2 TextureUV : TEXCOORD0;
};
//--------------------------------------------------------------------------
struct VS_OUTPUT
{
 float4 Position : POSITION;
 float2 TextureUV : TEXCOORD0;
};
//--------------------------------------------------------------------------
VS_OUTPUT VShade(VS_INPUT input)
{
 // zero out members of output
 VS_OUTPUT output;
 
 // transform to view space and project
 output.Position  = mul(input.Position, ViewProjMatrix);
 
 output.TextureUV = input.TextureUV;

 return output;
}
//--------------------------------------------------------------------------



//--------------------------------------------------------------------------
// Pixel shader
//--------------------------------------------------------------------------
uniform sampler   BaseTex: register(s0) = 
sampler_state 
{
 texture = <tDif>;
 MinFilter = Point;
 MagFilter = Linear;
 MipFilter = Linear;

 AddressU = Clamp; 
 AddressV = Clamp; 
 AddressW = Clamp; 
};

//--------------------------------------------------------------------------
uniform sampler   ToneTex: register(s1) = 
sampler_state 
{
 texture = <Tone>;
 MinFilter = Point;
 MagFilter = Point;
 MipFilter = Point;

 AddressU = Clamp; 
 AddressV = Clamp; 
 AddressW = Clamp; 
};
//--------------------------------------------------------------------------
uniform sampler   LightTex: register(s2) = 
sampler_state 
{
 texture = <TextureLightMap>;
 MinFilter = Point;
 MagFilter = Linear;
 MipFilter = Linear;

 AddressU = Clamp; 
 AddressV = Clamp; 
 AddressW = Clamp; 
};

//--------------------------------------------------------------------------
struct PS_OUTPUT
{
 vector diffuse : COLOR0;
};
//--------------------------------------------------------------------------
half luminance(half3 c)
{
 return dot(c, float3(0.3, 0.59, 0.11));
}
//--------------------------------------------------------------------------
PS_OUTPUT PShadeSoftBloom(float2 Tex : TEXCOORD0)
{
 PS_OUTPUT output;
 
 // Compute the average of the 4 necessary samples
 float4 color = 0.0f;
 
 for (int i=0; i<2; i++)
 {
  for (int j=0; j<2; j++)
  {
   color += tex2D( BaseTex, Tex + float2(tcLumOffsets[i][j * 2], tcLumOffsets[i][(j * 2) + 1]) );
  }
 }
						
 color /= 4;
 //color.a = luminance(color.rgb);
 color.rgb = max(color.rgb-0.2, 0);
 output.diffuse = color;
 
 return output;
}
//--------------------------------------------------------------------------
PS_OUTPUT PShadeGlow(float2 Tex : TEXCOORD0)
{
 PS_OUTPUT output;
 
 // Compute the average of the 4 necessary samples
 float4 color = 0.0f;
 float4 lightcolor;
/* 
 for (int i=0; i<2; i++)
 {
  for (int j=0; j<2; j++)
  {
   color += tex2D( BaseTex, Tex + float2(tcLumOffsets[i][j * 2], tcLumOffsets[i][(j * 2) + 1]) );
  }
 }
						
 color /= 4;
 */
 color = tex2D( BaseTex, Tex);
 lightcolor = tex2D( LightTex, Tex);
 //color.rgb = max(color.rgb-0.4f, 0)*2.1;
 color = pow(lightcolor, 0.4f);//lightcolor;//*1.9f; + pow(color+0.02f, 14)*2.6f;
 //color = pow(color*2, g_fScale.x*8)*g_fScale.y*32;
 color.a = 1;
 output.diffuse = color;
 
 return output;
}
//--------------------------------------------------------------------------
PS_OUTPUT PShadeGlowHDR(float2 Tex : TEXCOORD0)
{
 PS_OUTPUT output;

 // Compute the average of the 4 necessary samples
 float4 color = 0.0f;
 
 for (int i=0; i<2; i++)
 {
  for (int j=0; j<2; j++)
  {
   color += tex2D( BaseTex, Tex + float2(tcLumOffsets[i][j * 2], tcLumOffsets[i][(j * 2) + 1]) );
  }
 }
						
 color /= 4;
 /*
 // Determine the brightness of this particular pixel
	float luminance = luminance(color.rgb);//dot( color.rgb, float3( 0.33, 0.34, 0.33 ) );
		
	// If this pixel satisfies the bright pass threshold it will
	// be > 0.0 after this operation
	luminance = max( 0.0f, luminance - BRIGHT_PASS_HDR_THRESHOLD );
		
	// Muliply by the above predicate, use the sign() intrinsic
	// to make sure that luminance is either 0.0 or 1.0, thus not
	// scaling any bright pixels that are needed.
	color.rgb *= sign( luminance );
		
	// Write the colour to the bright-pass render target
	color.a = luminance;

 output.diffuse = color;
 */
 
 //color.a = luminance(color.rgb);
 //color.rgb = max(color.rgb-0.92, 0)*15.0;
 //color.rgb = max(color.rgb-0.1, 0);
 
 //float4 vSample = tex2D( s0, vScreenPosition );
 float fAdaptedLum = tex2D(ToneTex, float2(0.5, 0.5)).r;
	
	// Determine what the pixel's value will be after tone-mapping occurs
	color.rgb *= HDR_MIDLEGRAY/(fAdaptedLum + 0.095);
	
	// Subtract out dark pixels
	color.rgb -= BRIGHT_PASS_HDR_THRESHOLD;
	
	// Clamp to 0
	color = max(color, 0.0f);
	
	// Map the resulting value into the 0 to 1 range. Higher values for
	// BRIGHT_PASS_OFFSET will isolate lights from illuminated scene 
	// objects.
	color.rgb /= (BRIGHT_PASS_HDR_OFFSET+color);
	
 output.diffuse = color;
 
 return output;
}
//--------------------------------------------------------------------------
PS_OUTPUT StarBrightPassLDR(float2 Tex : TEXCOORD0)
{
 PS_OUTPUT output;
 
 // Compute the average of the 4 necessary samples
 float4 color = 0.0f;
 
 for (int i=0; i<2; i++)
 {
  for (int j=0; j<2; j++)
  {
   color += tex2D( BaseTex, Tex + float2(tcLumOffsets[i][j * 2], tcLumOffsets[i][(j * 2) + 1]) );
  }
 }
						
 color /= 4;
 color.a = luminance(color.rgb);
 color.rgb = max(color.rgb-0.93, 0)*3.0;
 output.diffuse = color;
 
 return output;
}
//--------------------------------------------------------------------------
PS_OUTPUT StarBrightPassHDR(float2 Tex : TEXCOORD0)
{
 PS_OUTPUT output;

 // Compute the average of the 4 necessary samples
 float4 color = 0.0f;
 
 for (int i=0; i<2; i++)
 {
  for (int j=0; j<2; j++)
  {
   color += tex2D( BaseTex, Tex + float2(tcLumOffsets[i][j * 2], tcLumOffsets[i][(j * 2) + 1]) );
  }
 }
						
 color /= 4;
 
 /*
 // Determine the brightness of this particular pixel
	float luminance = luminance(color.rgb);//dot( color.rgb, float3( 0.33, 0.34, 0.33 ) );
		
	// If this pixel satisfies the bright pass threshold it will
	// be > 0.0 after this operation
	luminance = max( 0.0f, luminance - STAR_BRIGHT_PASS_HDR_THRESHOLD );
		
	// Muliply by the above predicate, use the sign() intrinsic
	// to make sure that luminance is either 0.0 or 1.0, thus not
	// scaling any bright pixels that are needed.
	color.rgb *= sign( luminance );
		
	// Write the colour to the bright-pass render target
	color.a = luminance;

 output.diffuse = color;
 */
 
  //float4 vSample = tex2D( s0, vScreenPosition );
 float fAdaptedLum = tex2D(ToneTex, float2(0.5, 0.5)).r;
	
	// Determine what the pixel's value will be after tone-mapping occurs
	color.rgb *= STAR_HDR_MIDLEGRAY/(fAdaptedLum + 0.095);
	
	// Subtract out dark pixels
	color.rgb -= STAR_BRIGHT_PASS_HDR_THRESHOLD;
	
	// Clamp to 0
	color = max(color, 0.0f);
	
	// Map the resulting value into the 0 to 1 range. Higher values for
	// BRIGHT_PASS_OFFSET will isolate lights from illuminated scene 
	// objects.
	color.rgb /= (STAR_BRIGHT_PASS_HDR_OFFSET+color);
	output.diffuse = color;
	
 return output;
}
//--------------------------------------------------------------------------
technique tec0
{ 
 pass p0
 {      
  VertexShader = NULL;

  PixelShader = compile ps_2_0 PShadeSoftBloom();
 }
 pass p1
 {      
  VertexShader = NULL;

  PixelShader = compile ps_2_0 PShadeGlow();
 }
 pass p2
 {      
  VertexShader = NULL;

  PixelShader = compile ps_2_0 PShadeGlowHDR();
 }
 pass p3
 {      
  VertexShader = NULL;

  PixelShader = compile ps_2_0 StarBrightPassLDR();
 }
 pass p4
 {      
  VertexShader = NULL;

  PixelShader = compile ps_2_0 StarBrightPassHDR();
 }
}
//--------------------------------------------------------