SSAO halo in half resolution

Started by
3 comments, last by Alundra 7 years ago

Hi,
I moved the SSAO in half-resolution because it's very expensive but doing that I got halo.
Is it really needed to downsample the depth map (the normal map doesn't need I think) to avoid the halo ?
Thanks

Advertisement

Do you currently do any downsampling? How do you do the upsampling too? Are you using a bilateral filter?

This is the start of the question, yes.
What kind of downsampling is good, is it needed to do the downsampling pass separately, another forum's thread says it looks better to do a pass before do the other pass.
Same question for the upsampling, needed to do a custom filtering or the sample in the shader is enough ?
But yea, doing simply this chain gives the halo issue :


SSAO in Half resolution (with depth map and normal map in full resolution) -> Blur in half resolution -> Combine in a render target in full resolution

So the question is is it needed to do :


Downsampling depth map in half resolution -> SSAO in half resolution -> Blur in half resolution -> Up sampling the blur result -> Combine

This downsampling/upsampling question about the pass needed is the same kind of question about all other things which needs to work in another resolution, for example the Bloom.

You can merge the up-sample/combine shaders together if required, and the downsample/ssao shaders together if required.

Downsampling the depth as a seperate step may actually improve performance though! The SSAO shader takes a lot of samples from the depth map, and the cost of sampling is directly related to how well the texture cache is working for you. A smaller depth map is more likely to make the texture cache happy. A typical depth downsampling filter would select the maximum depth value from a 2x2 area.

The upsampling shader should first calculate bilinear weights for the 4 texels which are nearest to the high-resolution pixel location, as the hardware would normally do if you were using linear filtering. i.e. start by implementing the HW linear filter yourself, in shader code. Then to extend this into a bilateral filter, you need to compare the half-resolution depth value at each of those texel locations to the high-resolution depth value. Modify the 4 weights based on the difference in depth. Then renormalize the weights to ensure they add up to 1.0 (e.g. weights.xyzw /= weights.x+weights.y+weights.z+weights.w). This is a "depth aware bilateral filter", which will ignore results from incorrect depth ranges, reducing the halo effect on edges.

Good to know about the performance won using a downsampled depth map !
I already do the blur testing the depth and normal like that :


float4 main( in PS_INPUT Input ) : SV_TARGET
{
  float TotalWeight = 0.0f;
  float4 Color = float4( 0.0f, 0.0f, 0.0f, 0.0f );
  float3 CenterNormal = NormalMap.SampleLevel( PointSampler, Input.TexCoord, 0.0f ).rgb;
  float CenterDepth = DepthMap.SampleLevel( PointSampler, Input.TexCoord, 0.0f ).r;
  for( int i = -5; i <= 5; ++i )
  {
    float2 Texcoord = Input.TexCoord + ( float( i ) * TextureOffset );
    float3 Normal = NormalMap.SampleLevel( PointSampler, Texcoord, 0.0f ).rgb;
    float Depth = DepthMap.SampleLevel( PointSampler, Texcoord, 0.0f ).r;
    if( ( dot( Normal, CenterNormal ) >= 0.8f ) && ( abs( Depth - CenterDepth ) <= 0.2f ) )
    {
      float Weight = Weights[ i + 5 ];
      Color += Weight * DiffuseMap.SampleLevel( PointSampler, Texcoord, 0.0f );
      TotalWeight += Weight;
    }
  }
  return Color / TotalWeight;
}

This topic is closed to new replies.

Advertisement