There May be a bug in Sample: "CascadingShadowMaps", or I got it wrong.
HuazyYang opened this issue · 1 comments
Hi, @walbourn , I am studying the DirectX11 samples "CascadingShadowMaps" shipped with DirexX11-SDK(june 2010) and I have a question about render scene pixel shader in "RenderCascadeScene.hlsl" and
and the constant buffer:
cbuffer cbAllShadowData : register( b0 )
{
...
// For Map based selection scheme, this keeps the pixels inside of the the valid range.
// When there is no boarder, these values are 0 and 1 respectivley.
**float m_fMinBorderPadding;
float m_fMaxBorderPadding;**
...
};
VS_OUTPUT VSMain( VS_INPUT Input )
{
VS_OUTPUT Output;
[Omitted]
// Transform the shadow texture coordinates for all the cascades.
**Output.vTexShadow = mul( Input.vPosition, m_mShadow );**
return Output;
}
float4 PSMain( VS_OUTPUT Input ) : SV_TARGET
{
...
float4 vShadowMapTextureCoordViewSpace = Input.vTexShadow;
...
if ( !SELECT_CASCADE_BY_INTERVAL_FLAG )
{
iCurrentCascadeIndex = 0;
if ( CASCADE_COUNT_FLAG == 1 )
{
vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * m_vCascadeScale[0];
vShadowMapTextureCoord += m_vCascadeOffset[0];
}
if ( CASCADE_COUNT_FLAG > 1 ) {
for( int iCascadeIndex = 0; iCascadeIndex < CASCADE_COUNT_FLAG && iCascadeFound == 0; ++iCascadeIndex )
{
vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * m_vCascadeScale[iCascadeIndex];
vShadowMapTextureCoord += m_vCascadeOffset[iCascadeIndex];
if ( **min( vShadowMapTextureCoord.x, vShadowMapTextureCoord.y ) > m_fMinBorderPadding
&& max( vShadowMapTextureCoord.x, vShadowMapTextureCoord.y** ) < m_fMaxBorderPadding )
{
iCurrentCascadeIndex = iCascadeIndex;
iCascadeFound = 1;
}
}
}
}
...
}
When I check the buffer settings in cpp code,, it is like:
// The border padding values keep the pixel shader from reading the borders during PCF filtering.
pcbAllShadowConstants->m_fMaxBorderPadding = (float)( m_pCascadeConfig->m_iBufferSize - 1.0f ) /
(float)m_pCascadeConfig->m_iBufferSize;
pcbAllShadowConstants->m_fMinBorderPadding = (float)( 1.0f ) /
(float)m_pCascadeConfig->m_iBufferSize;
Obviously, in hlsl pixel shaer, the global variables: m_fMinBorderPadding, m_fMaxBorderPadding will be bound to (0, 1), whereas, vShadowMapTextureCoord can not be in range [0, 1][0, 1][0,1] before perspective divide( divide by its w component ). When checking the code previously in pixel shader to check whether there is any piece of code doing perspective divide, I find none unfortunately. I think this is a bug in the implementation, or I got it wrong. I beg your opinion about this.
Yet, another question, In PSMain mentioned above, the usage of “ddx()” and "ddy()" intrinsic function
in HLSL may be wrong:
vShadowMapTextureCoordDDX = ddx( vShadowMapTextureCoordViewSpace );
vShadowMapTextureCoordDDY = ddy( vShadowMapTextureCoordViewSpace );
Refer to https://docs.microsoft.com/zh-cn/windows/desktop/direct3dhlsl/dx-graphics-hlsl-ddx, ddx and ddy take screen space coordinates, but vShadowMapTextureCoordViewSpace is in light view space, more transformations are needed here.
Hi, @walbourn , I am studying the DirectX11 samples "CascadingShadowMaps" shipped with DirexX11-SDK(june 2010) and I have a question about render scene pixel shader in "RenderCascadeScene.hlsl" and
and the constant buffer:cbuffer cbAllShadowData : register( b0 ) { ... // For Map based selection scheme, this keeps the pixels inside of the the valid range. // When there is no boarder, these values are 0 and 1 respectivley. **float m_fMinBorderPadding; float m_fMaxBorderPadding;** ... };
VS_OUTPUT VSMain( VS_INPUT Input ) { VS_OUTPUT Output; [Omitted] // Transform the shadow texture coordinates for all the cascades. **Output.vTexShadow = mul( Input.vPosition, m_mShadow );** return Output; }
float4 PSMain( VS_OUTPUT Input ) : SV_TARGET { ... float4 vShadowMapTextureCoordViewSpace = Input.vTexShadow; ... if ( !SELECT_CASCADE_BY_INTERVAL_FLAG ) { iCurrentCascadeIndex = 0; if ( CASCADE_COUNT_FLAG == 1 ) { vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * m_vCascadeScale[0]; vShadowMapTextureCoord += m_vCascadeOffset[0]; } if ( CASCADE_COUNT_FLAG > 1 ) { for( int iCascadeIndex = 0; iCascadeIndex < CASCADE_COUNT_FLAG && iCascadeFound == 0; ++iCascadeIndex ) { vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * m_vCascadeScale[iCascadeIndex]; vShadowMapTextureCoord += m_vCascadeOffset[iCascadeIndex]; if ( **min( vShadowMapTextureCoord.x, vShadowMapTextureCoord.y ) > m_fMinBorderPadding && max( vShadowMapTextureCoord.x, vShadowMapTextureCoord.y** ) < m_fMaxBorderPadding ) { iCurrentCascadeIndex = iCascadeIndex; iCascadeFound = 1; } } } } ... }
When I check the buffer settings in cpp code,, it is like:
// The border padding values keep the pixel shader from reading the borders during PCF filtering. pcbAllShadowConstants->m_fMaxBorderPadding = (float)( m_pCascadeConfig->m_iBufferSize - 1.0f ) / (float)m_pCascadeConfig->m_iBufferSize; pcbAllShadowConstants->m_fMinBorderPadding = (float)( 1.0f ) / (float)m_pCascadeConfig->m_iBufferSize;
Obviously, in hlsl pixel shaer, the global variables: m_fMinBorderPadding, m_fMaxBorderPadding will be bound to (0, 1), whereas, vShadowMapTextureCoord can not be in range [0, 1][0, 1][0,1] before perspective divide( divide by its w component ). When checking the code previously in pixel shader to check whether there is any piece of code doing perspective divide, I find none unfortunately. I think this is a bug in the implementation, or I got it wrong. I beg your opinion about this.
Yet, another question, In PSMain mentioned above, the usage of “ddx()” and "ddy()" intrinsic function
in HLSL may be wrong:vShadowMapTextureCoordDDX = ddx( vShadowMapTextureCoordViewSpace ); vShadowMapTextureCoordDDY = ddy( vShadowMapTextureCoordViewSpace );
Refer to https://docs.microsoft.com/zh-cn/windows/desktop/direct3dhlsl/dx-graphics-hlsl-ddx, ddx and ddy take screen space coordinates, but vShadowMapTextureCoordViewSpace is in light view space, more transformations are needed here.