Search Unity

Why DownsampleBox13Tap in post-processing stack do so much sample?

Discussion in 'Shaders' started by Middle-earth, May 6, 2019.

  1. Middle-earth

    Middle-earth

    Joined:
    Jan 23, 2018
    Posts:
    31
    This function is a part of fragment shader in Sampling.hlsl used in bloom.Each edge of destination texture is 1/2 of the source texture.

    // . A . B . C .
    // . . D . E . .
    // . F . G . H .
    // . . I . J . .
    // . K . L . M .

    half4 DownsampleBox13Tap(TEXTURE2D_ARGS(tex, samplerTex), float2 uv, float2 texelSize)
    {
    half4 A = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2(-1.0, -1.0)));
    half4 B = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2( 0.0, -1.0)));
    half4 C = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2( 1.0, -1.0)));
    half4 D = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2(-0.5, -0.5)));
    half4 E = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2( 0.5, -0.5)));
    half4 F = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2(-1.0, 0.0)));
    half4 G = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv ));
    half4 H = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2( 1.0, 0.0)));
    half4 I = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2(-0.5, 0.5)));
    half4 J = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2( 0.5, 0.5)));
    half4 K = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2(-1.0, 1.0)));
    half4 L = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2( 0.0, 1.0)));
    half4 M = SAMPLE_TEXTURE2D(tex, samplerTex, UnityStereoTransformScreenSpaceTex(uv + texelSize * float2( 1.0, 1.0)));

    half2 div = (1.0 / 4.0) * half2(0.5, 0.125);

    half4 o = (D + E + I + J) * div.x;
    o += (A + B + G + F) * div.y;
    o += (B + C + H + G) * div.y;
    o += (F + G + L + K) * div.y;
    o += (G + H + M + L) * div.y;

    return o;
    }

    I think "G" is equal to "(D + E + I + J)*0.25".
    So it just samples G is enough,why does it sample D,E,I,J?It looks like not necessary.There must be some reason to add so mush extra sampling.
     
    Last edited: May 8, 2019
  2. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    119
    This shader is based on a talk http://goo.gl/eomGso
    If you look at the slides it becomes clear that all 13 samples are supposed to be bilinear fetches across a 6 by 6 texel grid, but I think the shader code done by Unity Tech. might be implementing it incorrectly. Below is the screenshot of the slide in question:
    upload_2019-5-23_14-26-34.png

    In the original slides G(center-most sample) would not be equal (D + E + I + J) * 0.25 (red samples) because all the components are already bilinear interpolations, not texels.

    As the DownsampleBox13Tap function is now, it looks like samples D, E, I and J are interpolated(since they use half-texel offsets) and the rest seem to be uninterpolated. Have you investigated this further? Any interesting discoveries?

    Disclaimer: I might be completely wrong.
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    6,742
    That kernel assumes the starting UV is at the corner between texels. When downsampling, the texture UV of the lower res texture will already be centered between the 4 texels of the previous texture.