Rendering Components
Rendering components are designed to be plug-and-play blocks of functionaliy that can be used by applications.
Shadows
The shadowing component implements the following BKMs:
- Cascaded shadow maps with cascade stabilization
- PCF
- Variance shadow maps
- Two and four-component exponential variance shadow maps
- Optimized fixed-size or world-sized filter kernels
- Best cascade search based on projection into light space
- Filtering across cascades
- Various artifact removal techniques
Integrating shadows into application
The component is implemented by the following source files:
- ShadowMapManager.h/ShadowMapManager.cpp - implementation of the shadow map manager.
- Shadows.fxh - shader functionality.
Initialization
The shadow map manager is responsible for creating required textures and views, cascade partitioning, converting shadow map to filterable representations (VSM/EVSM) etc.
To initialize the manager, prepare ShadowMapManager::InitInfo
structure that defines initialization parameters
and call ShadowMapManager::Initialize
, for example:
ShadowMapManager::InitInfo SMMgrInitInfo;
SMMgrInitInfo.Format = TEX_FORMAT_D16_UNORM;
SMMgrInitInfo.Resolution = 1024;
SMMgrInitInfo.NumCascades = 4;
SMMgrInitInfo.ShadowMode = SHADOW_MODE_PCF;
SMMgrInitInfo.pComparisonSampler = m_pComparisonSampler;
m_ShadowMapMgr.Initialize(m_pDevice, SMMgrInitInfo);
Most of the fields of ShadowMapManager::InitInfo
structure are self-explanatory. pComparisonSampler
defines
optional texture sampler to be set in the shadow map resource view. If the sampler is null
, the application is responsible
for setting appropriate sampler before using the shadow map in the shader.
Cascade Partitioning
To distribute shadow map cascades, populate ShadowMapManager::DistributeCascadeInfo
that defines partitioning
parameters and call ShadowMapManager::DistributeCascades
:
ShadowMapManager::DistributeCascadeInfo DistrInfo;
DistrInfo.pCameraView = &m_Camera.GetViewMatrix();
DistrInfo.pCameraProj = &m_Camera.GetProjMatrix();
DistrInfo.pLightDir = &m_f3LightDirection;
DistrInfo.fPartitioningFactor = 0.95f;
m_ShadowMapMgr.DistributeCascades(DistrInfo, m_LightAttribs.ShadowAttribs);
fPartitioningFactor
member defines the ratio between fully linear (0.0) and
fully logarithmic (1.0) partitioning. The method populates the ShadowMapAttribs
structure that
is part of the LightAttribs
structure and should be made available to a shader via constant buffer.
Rendering Shadow Cascades
After cascades are distributed, use ShadowMapManager::GetCascadeTranform
method to access
transform matrices and render every cascade:
auto iNumShadowCascades = m_LightAttribs.ShadowAttribs.iNumCascades;
for(int iCascade = 0; iCascade < iNumShadowCascades; ++iCascade)
{
const auto CascadeProjMatr = m_ShadowMapMgr.GetCascadeTranform(iCascade).Proj;
auto WorldToLightViewSpaceMatr = m_LightAttribs.ShadowAttribs.mWorldToLightViewT.Transpose();
auto WorldToLightProjSpaceMatr = WorldToLightViewSpaceMatr * CascadeProjMatr;
CameraAttribs ShadowCameraAttribs = {};
ShadowCameraAttribs.mViewT = m_LightAttribs.ShadowAttribs.mWorldToLightViewT;
ShadowCameraAttribs.mProjT = CascadeProjMatr.Transpose();
ShadowCameraAttribs.mViewProjT = WorldToLightProjSpaceMatr.Transpose();
{
MapHelper<CameraAttribs> CameraData(m_pImmediateContext, m_CameraAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD);
*CameraData = ShadowCameraAttribs;
}
auto* pCascadeDSV = m_ShadowMapMgr.GetCascadeDSV(iCascade);
m_pImmediateContext->SetRenderTargets(0, nullptr, pCascadeDSV,
RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
m_pImmediateContext->ClearDepthStencil(pCascadeDSV, CLEAR_DEPTH_FLAG, 1.f, 0,
RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
DrawMesh(m_pImmediateContext);
}
When using filterable representations, the shadow map must be post-processed before it can be used in a shader:
if (m_ShadowSettings.iShadowMode > SHADOW_MODE_PCF)
m_ShadowMapMgr.ConvertToFilterable(m_pImmediateContext, m_LightAttribs.ShadowAttribs);
Rendering with Shadows
To use shadowing functionality in the shader, include BasicStructures.fxh
and Shadows.fxh
files and
depending on the shadowing mode, define shadow map or filterable shadow map textures and corresponding samplers
(note that the names must be different to allow HLSL to GLSL conversion):
#include "BasicStructures.fxh"
#include "Shadows.fxh"
#if SHADOW_MODE == SHADOW_MODE_PCF
Texture2DArray<float> g_tex2DShadowMap;
SamplerComparisonState g_tex2DShadowMap_sampler;
#else
Texture2DArray<float4> g_tex2DFilterableShadowMap;
SamplerState g_tex2DFilterableShadowMap_sampler;
#endif
To filter shadow map, call FilterShadowMap
or SampleFilterableShadowMap
function:
FilteredShadow Shadow;
#if SHADOW_MODE == SHADOW_MODE_PCF
Shadow = FilterShadowMap(g_LightAttribs.ShadowAttribs, g_tex2DShadowMap, g_tex2DShadowMap_sampler,
VSOut.PosInLightViewSpace, VSOut.CameraSpaceZ);
#else
Shadow = SampleFilterableShadowMap(g_LightAttribs.ShadowAttribs, g_tex2DFilterableShadowMap,
g_tex2DFilterableShadowMap_sampler, VSOut.PosInLightViewSpace,
VSOut.CameraSpaceZ);
#endif
DiffuseIllumination *= Shadow.fLightAmount;
Shadow filtering mode is controlled by a number of macros that should be defined when creating the shader:
ShaderCreateInfo ShaderCI;
ShaderMacroHelper Macros;
Macros.AddShaderMacro( "SHADOW_MODE", m_ShadowSettings.iShadowMode);
Macros.AddShaderMacro( "SHADOW_FILTER_SIZE", m_LightAttribs.ShadowAttribs.iFixedFilterSize);
Macros.AddShaderMacro( "FILTER_ACROSS_CASCADES", m_ShadowSettings.FilterAcrossCascades);
Macros.AddShaderMacro( "BEST_CASCADE_SEARCH", m_ShadowSettings.SearchBestCascade );
ShaderCI.Macros = Macros;
Shadows sample gives an example of using the shadowing component.
References
History of
Components
@gltf-multiview
git clone https://git.s-ol.nu/forks/DiligentFX.git
- Fix misc. typos luz paz 2 years ago
- Updated copyright notice assiduous 2 years ago
- Some updates to match API240076 assiduous 2 years ago
- Fixed compilation after PSO refactoring azhirnov 2 years ago
- Updated to match API Version 240056 assiduous 3 years ago
- Renamed RightHandedLightViewTransform to UseRightHandedLightViewTransform assiduous 3 years ago
- Added RightHandedLightViewTransform parameter to DistributeCascadeInfo assiduous 3 years ago
- Renamed .h -> .hpp where appropriate assiduous 3 years ago
- Fixed issue with FLT_MAX assiduous 3 years ago
- Updates to comply with the new API assiduous 3 years ago
- Updated copyright notice assiduous 3 years ago
- clang-formatted Components Egor Yusov 3 years ago
- Updated relative paths to shaders included into source files Egor Yusov 3 years ago
- Fixed compliler warning Egor Yusov 3 years ago
- Fixed few compiler warnings Egor Yusov 3 years ago
- Updated copyright notice Egor Yusov 4 years ago
- Few minor readme updates Egor Yusov 4 years ago
- Updated readme Egor Yusov 4 years ago
- Updated Shadow map manager & added readme Egor Yusov 4 years ago
- Fixed minor ShadowMapManager build issue on Mac Egor Yusov 4 years ago
- Few minor updates to shadow map manager Egor Yusov 4 years ago
- ShadowMap manager: fixed GL warning Egor Yusov 4 years ago
- Shadow map manager: improved cascade distribution to support world-scale sized filters Egor Yusov 4 years ago
- Shadows: implemented world-size filtering of VSM/EVSM Egor Yusov 4 years ago
- Shadows: using 16-bit UNORM instead of 16-bit float for VSM Egor Yusov 4 years ago
- Fixed 16-bit VSM/EVSM format from UNORM to Float Egor Yusov 4 years ago
- Added EVSM shadows Egor Yusov 4 years ago
- Implemented VSM filtering Egor Yusov 4 years ago
- Shadows: added VSM mode Egor Yusov 4 years ago
- Shadows: improved blending between cascades Egor Yusov 4 years ago