walbourn/directx-sdk-samples

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.