Original Post
I am implementing the QVSM. I have a question how to calculate the matrix of m4x4_screen_to_shadowmap in vsmshadow_sm_helper2.hlsl(in Book sample of ShaderX5 chapter4.5).
//vsmshadow_sm_helper2.hlsl
float4x4 m4x4_screen_to_shadowmap; // The uniform part of the transformation from screenspace to shadowmapspace
//-------------------------------------------------------------------------------------------------
// ScreenspaceToShadowmapspace
//-------------------------------------------------------------------------------------------------
inline float4 ScreenspaceToShadowmapspace(float screen_x, float screen_y, float z_view)
{
float4 v4_pos_screen_reprojected = float4( screen_x * z_view, screen_y * z_view, z_view, 1 );
float4 v4_pos_lightspace = mul(v4_pos_screen_reprojected, m4x4_screen_to_shadowmap);
return v4_pos_lightspace;
};
//-------------------------------------------------------------------------------------------------
// ScreenspaceToShadowmapCoordinatesAndLightspaceDepth
//-------------------------------------------------------------------------------------------------
inline float3 ScreenspaceToShadowmapCoordinatesAndLightspaceDepth(float screen_x, float screen_y, float z_view)
{
float4 pos_light = ScreenspaceToShadowmapspace(screen_x, screen_y, z_view);
// Project result into shadowmap coordinates
double pos_light_w_inv = 1.0 / pos_light.w;
float3 pos_shadowmap =
float3(
0.5 + 0.5 * pos_light_w_inv * pos_light.x, // SM texture x
0.5 - 0.5 * pos_light_w_inv * pos_light.y, // SM texture y
pos_light_w_inv * pos_light.z // depth in SM space
);
return pos_shadowmap;
};
//vsmshadow_deferred.hlsl
//-------------------------------------------------------------------------------------------------
// PsApplySmTileToFramebufferUsingShadowDepthBuffer
// Apply shadow map tile to the frame buffer using the linear depth values stored in the
// Shadow Depth Buffer
//-------------------------------------------------------------------------------------------------
Ps_DEFAULT_OUT PsApplySmTileToFramebufferUsingShadowDepthBuffer(Ps_TC_IN IN)
{
Ps_DEFAULT_OUT OUT;
float shadow_term = 1.0f;
const float shadow_ambient = 0.7f;
//float shadow_ambient = UNIFORM_shadow_map_ambient;
float z_view_center = tex2D(tex_shadow_depth_buffer, IN.v2_tc.xy).w;
float3 pos_shadowmap =
ScreenspaceToShadowmapCoordinatesAndLightspaceDepth( IN.v2_tc.x, IN.v2_tc.y, z_view_center );
float2 sm_coords = pos_shadowmap.xy;
float depth_lightspace = pos_shadowmap.z;
// Pixel lies on backplane or query does not concern current tile => Skip Fragment
if(
(z_view_center == 0.0f) || // skip pixels lying on the backplane (D3D9 only allows DWORDs for Clear, so we have to use 0 here).
(sm_coords.x < 0) || (sm_coords.x > 1) || // pixel lies outside of current shdow map tile
(sm_coords.y < 0) || (sm_coords.y > 1)
)
{
clip(-1);
}
#if(1)
shadow_term = (tex2D(tex_shadowmap_tile, sm_coords).x < (depth_lightspace)) ? shadow_ambient : 1.0f;
#else
#include "vsmshadow_adaptive_sm_filtering_inc.hlsl"
#endif
OUT.color = tex2D(tex_shadow_depth_buffer, IN.v2_tc.xy) * shadow_term;
return OUT;
}