WickedEngine/shaders/ffx-shadows-dnsr/ffx_denoiser_shadows_tileclassification.h
float FFX_DNSR_Shadows_HorizontalNeighborhood(int2 did)
{
   const int2 base_did = did;

    // Prevent vertical out of bounds access
    if ((base_did.y < 0) || (base_did.y >= FFX_DNSR_Shadows_GetBufferDimensions().y)) return 0;

    const uint2 tile_index = FFX_DNSR_Shadows_GetTileIndexFromPixelPosition(base_did);
    const uint linear_tile_index = FFX_DNSR_Shadows_LinearTileIndex(tile_index, FFX_DNSR_Shadows_GetBufferDimensions().x);

    const int left_tile_index = linear_tile_index - 1;
    const int center_tile_index = linear_tile_index;
    const int right_tile_index = linear_tile_index + 1;

    bool is_first_tile_in_row = tile_index.x == 0;
    bool is_last_tile_in_row = tile_index.x == (FFX_DNSR_Shadows_RoundedDivide(FFX_DNSR_Shadows_GetBufferDimensions().x, 8) - 1);

    uint left_tile = 0;
    if (!is_first_tile_in_row) left_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask(left_tile_index);
    uint center_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask(center_tile_index);
    uint right_tile = 0;
    if (!is_last_tile_in_row) right_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask(right_tile_index);

    // Construct a single uint with the lowest 17bits containing the horizontal part of the local neighborhood.

    // First extract the 8 bits of our row in each of the neighboring tiles
    const uint row_base_index = (did.y % 4) * 8;
    const uint left = (left_tile >> row_base_index) & 0xFF;
    const uint center = (center_tile >> row_base_index) & 0xFF;
    const uint right = (right_tile >> row_base_index) & 0xFF;

    // Combine them into a single mask containting [left, center, right] from least significant to most significant bit
    uint neighborhood = left | (center << 8) | (right << 16);

    // Make sure our pixel is at bit position 9 to get the highest contribution from the filter kernel
    const uint bit_index_in_row = (did.x % 8);
    neighborhood = neighborhood >> bit_index_in_row; // Shift out bits to the right, so the center bit ends up at bit 9.

    float moment = 0.0; // For one sample per pixel this is both, mean and variance

    // First 8 bits up to the center pixel
    uint mask;
    int i;
    for (i = 0; i < 8; ++i)
    {
        mask = 1u << i;
        moment += (mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(8 - i) : 0;
    }

    // Center pixel
    mask = 1u << 8;
    moment += (mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(0) : 0;

    // Last 8 bits
    for (i = 1; i <= 8; ++i)
    {
        mask = 1u << (8 + i);
        moment += (mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(i) : 0;
    }

    return moment;
}
// The horizontal part of a 17x17 local neighborhood kernel
The horizontal part of a 17x17 local neighborhood kernel
The horizontal part of a 17x17 local neighborhood kernel
float FFX_DNSR_Shadows_HorizontalNeighborhood(int2 did)
{
   const int2 base_did = did;
    if ((base_did.y < 0) || (base_did.y >= FFX_DNSR_Shadows_GetBufferDimensions().y)) return 0;
    const uint2 tile_index = FFX_DNSR_Shadows_GetTileIndexFromPixelPosition(base_did);
    const uint linear_tile_index = FFX_DNSR_Shadows_LinearTileIndex(tile_index, FFX_DNSR_Shadows_GetBufferDimensions().x);
    const int left_tile_index = linear_tile_index - 1;
    const int center_tile_index = linear_tile_index;
    const int right_tile_index = linear_tile_index + 1;
    bool is_first_tile_in_row = tile_index.x == 0;
    bool is_last_tile_in_row = tile_index.x == (FFX_DNSR_Shadows_RoundedDivide(FFX_DNSR_Shadows_GetBufferDimensions().x, 8) - 1);
    uint left_tile = 0;
    if (!is_first_tile_in_row) left_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask(left_tile_index);
    uint center_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask(center_tile_index);
    uint right_tile = 0;
    if (!is_last_tile_in_row) right_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask(right_tile_index);
    const uint row_base_index = (did.y % 4) * 8;
    const uint left = (left_tile >> row_base_index) & 0xFF;
    const uint center = (center_tile >> row_base_index) & 0xFF;
    const uint right = (right_tile >> row_base_index) & 0xFF;
    uint neighborhood = left | (center << 8) | (right << 16);
    const uint bit_index_in_row = (did.x % 8);
    neighborhood = neighborhood >> bit_index_in_row; 
    float moment = 0.0; 
    uint mask;
    int i;
    for (i = 0; i < 8; ++i)
    {
        mask = 1u << i;
        moment += (mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(8 - i) : 0;
    }
    mask = 1u << 8;
    moment += (mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(0) : 0;
    for (i = 1; i <= 8; ++i)
    {
        mask = 1u << (8 + i);
        moment += (mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(i) : 0;
    }
    return moment;
}
float FFX_DNSR_Shadows_HorizontalNeighborhood ( int2 did ) { const int2 base_did = did ; if ( ( base_did . y < 0 ) || ( base_did . y >= FFX_DNSR_Shadows_GetBufferDimensions ( ) . y ) ) return 0 ; const uint2 tile_index = FFX_DNSR_Shadows_GetTileIndexFromPixelPosition ( base_did ) ; const uint linear_tile_index = FFX_DNSR_Shadows_LinearTileIndex ( tile_index , FFX_DNSR_Shadows_GetBufferDimensions ( ) . x ) ; const int left_tile_index = linear_tile_index - 1 ; const int center_tile_index = linear_tile_index ; const int right_tile_index = linear_tile_index + 1 ; bool is_first_tile_in_row = tile_index . x == 0 ; bool is_last_tile_in_row = tile_index . x == ( FFX_DNSR_Shadows_RoundedDivide ( FFX_DNSR_Shadows_GetBufferDimensions ( ) . x , 8 ) - 1 ) ; uint left_tile = 0 ; if ( ! is_first_tile_in_row ) left_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask ( left_tile_index ) ; uint center_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask ( center_tile_index ) ; uint right_tile = 0 ; if ( ! is_last_tile_in_row ) right_tile = FFX_DNSR_Shadows_ReadRaytracedShadowMask ( right_tile_index ) ; const uint row_base_index = ( did . y % 4 ) * 8 ; const uint left = ( left_tile >> row_base_index ) & 0xFF ; const uint center = ( center_tile >> row_base_index ) & 0xFF ; const uint right = ( right_tile >> row_base_index ) & 0xFF ; uint neighborhood = left | ( center << 8 ) | ( right << 16 ) ; const uint bit_index_in_row = ( did . x % 8 ) ; neighborhood = neighborhood >> bit_index_in_row ; float moment = 0.0 ; uint mask ; int i ; for ( i = 0 ; i < 8 ; ++ i ) { mask = 1u << i ; moment += ( mask & neighborhood ) ? FFX_DNSR_Shadows_KernelWeight ( 8 - i ) : 0 ; } mask = 1u << 8 ; moment += ( mask & neighborhood ) ? FFX_DNSR_Shadows_KernelWeight ( 0 ) : 0 ; for ( i = 1 ; i <= 8 ; ++ i ) { mask = 1u << ( 8 + i ) ; moment += ( mask & neighborhood ) ? FFX_DNSR_Shadows_KernelWeight ( i ) : 0 ; } return moment ; }
The horizontal part of a 17x17 local neighborhood kernel
The horizontal part of a 17x17 local neighborhood kernel
// Prevent vertical out of bounds access // Construct a single uint with the lowest 17bits containing the horizontal part of the local neighborhood. // First extract the 8 bits of our row in each of the neighboring tiles // Combine them into a single mask containting [left, center, right] from least significant to most significant bit // Make sure our pixel is at bit position 9 to get the highest contribution from the filter kernel // Shift out bits to the right, so the center bit ends up at bit 9. // For one sample per pixel this is both, mean and variance // First 8 bits up to the center pixel // Center pixel // Last 8 bits