143 lines
3.9 KiB
HLSL
143 lines
3.9 KiB
HLSL
|
|
texture2D gShadowMap : ShadowMap;
|
|
float4x4 gLightWorldViewProj : LightViewProjection;
|
|
|
|
DepthStencilState ShadowDepthStencilState
|
|
{
|
|
DepthEnable = true;
|
|
DepthWriteMask = ALL; // Write depth to the shadow map
|
|
DepthFunc = LESS_EQUAL; // Compare depth in the shadow map
|
|
StencilEnable = false; // We don't need stencil operations here
|
|
};
|
|
|
|
SamplerState gShadowSampler2 : ShadowSampler {
|
|
Filter = MIN_MAG_MIP_POINT;
|
|
AddressU = CLAMP;
|
|
AddressV = CLAMP;
|
|
ComparisonFunc = LESS_EQUAL;
|
|
};
|
|
|
|
|
|
SamplerState gSampleState : SampleState;
|
|
|
|
RasterizerState gRasterizerState : RastState;
|
|
|
|
float4x4 gWorldViewProj : WorldViewProjection;
|
|
float4x4 gWorldMatrix : WorldMatrix;
|
|
|
|
texture2D gDiffuseMap : DiffuseMap;
|
|
texture2D gNormalMap : Normal;
|
|
texture2D gSpecularMap : Specular;
|
|
texture2D gGlossMap : Gloss;
|
|
|
|
float3 gLightDirection : LightDirection;
|
|
float3 gLightColor : LightColor;
|
|
float3 gCameraPosition : CameraPosition;
|
|
bool gUseNormal : UseNormal;
|
|
|
|
static const float3 gAmbient = float3(.03f, .03f, .03f);
|
|
|
|
// Input output structures
|
|
struct VS_INPUT {
|
|
float3 Position : POSITION;
|
|
float2 TexCoord : TEXCOORD;
|
|
float3 Normal : NORMAL;
|
|
float3 Tangent : TANGENT;
|
|
};
|
|
|
|
struct VS_OUTPUT {
|
|
float4 Position : SV_POSITION;
|
|
float4 WorldPosition : WORLDPOSITION;
|
|
float2 TexCoord : TEXCOORD;
|
|
float3 Normal : NORMAL;
|
|
float3 Tangent : TANGENT;
|
|
float4 ShadowCoord : SHADOWCOORD; // Add this to store shadow map coordinates
|
|
};
|
|
|
|
// Vertex shader
|
|
VS_OUTPUT VS(VS_INPUT input) {
|
|
VS_OUTPUT output = (VS_OUTPUT)0;
|
|
|
|
output.WorldPosition = mul(float4(input.Position, 1.f), gWorldMatrix);
|
|
output.Position = mul(float4(input.Position, 1.f), gWorldViewProj);
|
|
|
|
|
|
output.TexCoord = input.TexCoord;
|
|
output.Normal = mul(input.Normal, (float3x3) gWorldMatrix);
|
|
output.Tangent = mul(input.Tangent, (float3x3) gWorldMatrix);
|
|
|
|
// Calculate shadow map coordinates
|
|
// lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
|
|
output.ShadowCoord = mul(float4(input.Position, 1.f) , gLightWorldViewProj);
|
|
return output;
|
|
}
|
|
|
|
// Shadow sampling function
|
|
float ShadowCalculation(float4 shadowCoord, float3 normal) {
|
|
// Normalize the depth by dividing by the w component
|
|
float3 projCoord = shadowCoord.xyz / shadowCoord.w;
|
|
|
|
float shadow = 0.0;
|
|
uint width, height;
|
|
gShadowMap.GetDimensions(width, height);
|
|
float2 texelSize = float2(1.f / width, 1.f / height);
|
|
|
|
// Convert from [-1, 1] to [0, 1]
|
|
float2 UVCoords;
|
|
UVCoords.x = 0.5f * projCoord.x + 0.5f;
|
|
UVCoords.y = -0.5f * projCoord.y + 0.5f;
|
|
float z = projCoord.z;
|
|
|
|
float bias = max(0.05 * (1.0 - dot(normal, -gLightDirection)), 0.005);
|
|
|
|
for(int x = -1; x <= 1; ++x)
|
|
{
|
|
for(int y = -1; y <= 1; ++y)
|
|
{
|
|
float pcfDepth = gShadowMap.Sample(gShadowSampler2, UVCoords.xy + float2(x, y) * texelSize).r;
|
|
shadow += z - bias > pcfDepth ? 1.0 : 0.0;
|
|
}
|
|
}
|
|
|
|
shadow /= 9.0f;
|
|
|
|
// float shadowDepth = gShadowMap.Sample(gShadowSampler2, UVCoords.xy).r;
|
|
|
|
|
|
if(projCoord.z > 1.0)
|
|
shadow = 0.0;
|
|
|
|
return shadow;
|
|
}
|
|
// Pixel shader
|
|
float4 PS(VS_OUTPUT input) : SV_TARGET {
|
|
float shadowFactor = ShadowCalculation(input.ShadowCoord, input.Normal);
|
|
|
|
float3 diffuseColor = gDiffuseMap.Sample(gSampleState, input.TexCoord).rgb;
|
|
|
|
float3 finalColor = diffuseColor * (1 - shadowFactor);
|
|
finalColor += gAmbient;
|
|
|
|
return float4(finalColor, 1.0f);
|
|
}
|
|
|
|
// DepthStencilState
|
|
DepthStencilState gDepthStencilState {
|
|
DepthEnable = true;
|
|
DepthWriteMask = ALL;
|
|
DepthFunc = LESS;
|
|
StencilEnable = true;
|
|
};
|
|
|
|
|
|
// Technique
|
|
technique11 DefaultTechnique {
|
|
pass P0 {
|
|
SetDepthStencilState(ShadowDepthStencilState, 0);
|
|
SetRasterizerState(gRasterizerState);
|
|
SetVertexShader(CompileShader(vs_5_0, VS()));
|
|
SetGeometryShader(NULL);
|
|
SetPixelShader(CompileShader(ps_5_0, PS()));
|
|
}
|
|
}
|