float4x4 gWorld : WORLD;
float4x4 gWorldViewProj : WORLDVIEWPROJECTION;
float4x4 gWorldViewProj_Light;
float3 gLightDirection = float3(-0.577f, -0.577f, 0.577f);
float gShadowMapBias = 0.01f;
Texture2D gDiffuseMap;
Texture2D gShadowMap;
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;// or Mirror or Clamp or Border
AddressV = Wrap;// or Mirror or Clamp or Border
};
SamplerState samPoint
{
Filter = MIN_MAG_MIP_POINT;
AddressU = Wrap;// or Mirror or Clamp or Border
AddressV = Wrap;// or Mirror or Clamp or Border
};
SamplerComparisonState cmpSampler
{
// sampler state
Filter = COMPARISON_MIN_MAG_MIP_LINEAR;
AddressU = MIRROR;
AddressV = MIRROR;
// sampler comparison state
ComparisonFunc = LESS_EQUAL;
};
RasterizerState Solid
{
FillMode = SOLID;
CullMode = FRONT;
};
struct VS_INPUT
{
float3 pos : POSITION;
float3 normal : NORMAL;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
float2 texCoord : TEXCOORD;
float4 lPos : TEXCOORD1;
};
DepthStencilState EnableDepth
{
DepthEnable = TRUE;
DepthWriteMask = ALL;
};
RasterizerState NoCulling
{
CullMode = NONE;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUTPUT VS(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.pos = mul(float4(input.pos, 1.0), gWorldViewProj);
output.normal = normalize(mul(input.normal, (float3x3) gWorld));
output.texCoord = input.texCoord;
output.lPos = mul(float4(input.pos, 1.0), gWorldViewProj_Light);
return output;
}
float2 texOffset(int u, int v)
{
//TODO: return offseted value (our shadow map has the following dimensions: 1280 * 720)
float2 shadowMapSize = float2(1280.0f, 720.0f);
return float2(u * 1.0f / shadowMapSize.x, v * 1.0f / shadowMapSize.y);
}
float EvaluateShadowMap(float4 lpos)
{
// re-homogenize position after interpolation
lpos.xyz /= lpos.w;
// if position is not visible to the light - don't illuminate it
// results in hard light frustum
if (lpos.x < -1.0f || lpos.x > 1.0f ||
lpos.y < -1.0f || lpos.y > 1.0f ||
lpos.z < 0.0f || lpos.z > 1.0f)
return 0.0f;
// transform clip space coords to texture space coords (-1:1 to 0:1)
lpos.x = lpos.x / 2.0f + 0.5f;
lpos.y = lpos.y / -2.0f + 0.5f;
//apply shadow map bias
lpos.z -= gShadowMapBias;
// PCF filtering
float sum = 0;
for (float y = -1.5; y <= 1.5; y += 1)
{
for (float x = -1.5; x <= 1.5; x += 1)
{
sum += gShadowMap.SampleCmpLevelZero(cmpSampler, lpos.xy + texOffset(x, y), lpos.z).r;
}
}
return sum / 16.f;
}
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS(VS_OUTPUT input) : SV_TARGET
{
float shadowValue = EvaluateShadowMap(input.lPos);
shadowValue = saturate(shadowValue + 0.5f); // make shadows less harsh
float4 diffuseColor = gDiffuseMap.Sample( samLinear,input.texCoord );
float3 color_rgb= diffuseColor.rgb;
float color_a = diffuseColor.a;
//HalfLambert Diffuse :)
float diffuseStrength = dot(input.normal, -gLightDirection);
diffuseStrength = diffuseStrength * 0.5 + 0.5;
diffuseStrength = saturate(diffuseStrength);
color_rgb = color_rgb * diffuseStrength;
return float4(color_rgb * shadowValue , color_a );
}
//--------------------------------------------------------------------------------------
// Technique
//--------------------------------------------------------------------------------------
technique11 Default
{
pass P0
{
SetRasterizerState(NoCulling);
SetDepthStencilState(EnableDepth, 0);
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}