3

I have doubts on 1/z depth buffer interpolation. According to this website, the correct 1/z interpolation formula is

$\dfrac{1}{P.z} = \dfrac{1}{V0.z} * \lambda_0 + \dfrac{1}{V1.z} * \lambda_1 + \dfrac{1}{V2.z} * \lambda_2. $

Here is my 1/z interpolation implementation in my barycentric triangle rendering algorithm for my software renderer

    void DrawFilledTriangleBarycentric(const vec3f& v1, const vec3f& v2, const vec3f& v3, const Colour& colour) {
        ...
                // Barycentric weights
                float w1 = ((px - v2[0]) * (v3[1] - v2[1]) - (py - v2[1]) * (v3[0] - v2[0])) / area;
                float w2 = ((px - v3[0]) * (v1[1] - v3[1]) - (py - v3[1]) * (v1[0] - v3[0])) / area;
                float w3 = ((px - v1[0]) * (v2[1] - v1[1]) - (py - v1[1]) * (v2[0] - v1[0])) / area;
            if ((w1 >= 0.0f) & (w2 >= 0.0f) & (w3 >= 0.0f))
            {
                float z = w1 * v1[2] + w2 * v2[2] + w3 * v3[2];
                float depth = 1.0f / z;

                PutPixel(x, y, depth, colour.argb);
            }
    ...
}

especially this part

float z = w1 * v1[2] + w2 * v2[2] + w3 * v3[2];
float depth = 1.0f / z;

v1[2], v2[2], and v3[2] are z values. I am wondering whether I should change it to

float z = w1 * (1.0 / v1[2]) + w2 * (1.0 / v2[2]) + w3 * (1.0 / v3[2]);
float depth = z;

But if I do I got the following output

1

which is different from what I expect (using depth=1.0f/(w1 * v1[2] + w2 * v2[2] + w3 * v3[2]))

2

These are the triangles I am trying to render

DrawFilledTriangleBarycentric(vec3f(10, 50, 10), vec3f(400, 100, 10), vec3f(290, 380, 10), RED);
DrawFilledTriangleBarycentric(vec3f(50, 350, 2), vec3f(130, 40, 20), vec3f(380, 200, 5), GREEN);

Edit: I think I got it now. Depth testing method actually depends on what projection I use. If I use orthographic projection, z is linear but 1/z is not so I can use naive z buffer without problems. If I use perspective projection, z is no longer linear but 1/z becomes linear. In this case, inverse z testing is necessary. Am I right here? no?

Jimmy Yang
  • 167
  • 8
  • You may find this reply on a different thread of use: https://computergraphics.stackexchange.com/a/8022/209 – Simon F Sep 05 '22 at 09:19

1 Answers1

3

You are right. In the examples you provided you only seem to render "pre-transformed" triangles which is why I think you were missing the point made in the article. Which depth testing is the correct one depends on what those triangles representeded before being transformed.

Interpolating 1 / z instead of z is needed to get the correct depth for perspective-transformed geometry.

Michele M.
  • 41
  • 3