Original Post
Hi, I am having some issues when downsampling a MSAAx2 depth buffer and using it when redenring in a 1x buffer: Here is a quick summary of what I do: The opaque objects are rendered in a RGBA8 MSAA 2x, and translucent objects in a FP16 1x Buffer. After rendering the opaque objects, the MSSA 2x depth buffer as well as the MSAA 2x color buffer get downsampled using a draw quad and a specific pixel shader. Once done, the translucent objects are drawn into the FP16 buffer using the downsampled depth buffer . Fragment from the translucent objects are testing against the 1x zbuffer and some pixels are not drawn because of the loss of precision during the depth buffer downsampling. I tried several methods to ensure to get the best depth buffer downsample technique: Everything is in float in the fragement shader, When sampling the 2x depth buffer, the sampler filters are correctly set to NEAREST, texture is correctly aliased to a RGBA8 value without sRGB correction and the depth value is retrieved using texDepth2D in the FP. Here are the different techniques I tried: Getting the 2 neighbours value of depth:
void PS(PixelInput IN, out float d : DEPTH)
{
#define DEPTH(POS) texDepth2D(MSAADepthSampler, (POS))
const float2 offset0 = float2(1.0f / 2560.0f, 0.0f); // sample from MSAA2x Depth buffer
float z1 = DEPTH(IN.UV0 + offset0);
float z2 = DEPTH(IN.UV0 - offset0);
d = min(z1, z2)
}
Averaging 2 depth values in camera space and put it back in [0;1] space:
void PS(PixelInput IN, out float d : DEPTH)
{
#define DEPTH(POS) texDepth2D(MSAADepthSampler, (POS)) // sample from MSAA2x Depth buffer
float n = ProjectionClipNearFar.x;
float f = ProjectionClipNearFar.y;
float a0 = (-2*f*n);
float a1 = (f-n);
float a2 = (f+n);
const float2 offset0 = float2(1.0f / 2560.0f, 0.0f);
float z1 = DEPTH(IN.UV0 + offset0);
float z2 = DEPTH(IN.UV0 - offset0);
z1 = (z1 * 2.0f) - 1.0f; //[-1;1]
z2 = (z2 * 2.0f) - 1.0f; //[-1;1]
//http://en.wikipedia.org/wiki/Z-buffer
//z = (-2*f*n) / ((z * (f-n)) - (f+n));
z1 = a0 / ((z1 * a1) - a2); // Camera space
z2 = a0 / ((z2 * a1) - a2); // Camera space
float z = (z1 + z2) * 0.5f; // Average
z = (a2/a1) + ((1.0f/z) * (a0/a1)); // [-1;1]
d = (z * 0.5f) + 0.5f; // [0;1]
}
Any idea, or any suggestion would be highly appreciated. Thanks