# Perspective correct depth interpolation

This topic is 2694 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi,

I'm writing a depth only software rasterizer and have a few questions about perspective correct depth interpolation.

Vertex position in homogeneous coordinates in clip space: [x, y, z, w]
Vertex position after projection: [x', y', z'] = [x/w, y/w, z/w]

1. In some articles they say that You should interpolate z/w and 1/w. And later divide it to calculate persp corr depth. Other ones (C. Hecker's texture mapper docs) say that You can just interpolate 1/z'. This two ways lead to two different equations, so what is the correct way?

2. If it's ok to interpolate 1/z', then what to do, when z' is 0? For example DirectX style projection matrix returns z' from [0;1] range. Should I tweak it to have z' in (0;1] range or am I missing something?

##### Share on other sites
I haven't done the math in a long time, but I don't see why you would want to interpolate 1/z'. 1/w or 1/z is correct I think, it doesn't really matter since w depends linearly of z. You can either interpolate 1/z and do the inverse to get the actual depth, or interpolate z/w and 1/w and divide z/w by 1/w.

So you dont have to worry about z' being equal to 0 (which it will be for a point in the near plane), since you interpolate 1/w, which will never be zero. w will usually be a multiple of your z coordinate, so if it's equal to 0, it will be clipped away by the near plane.

[Edited by - zurekx on September 7, 2010 3:54:03 PM]

##### Share on other sites
Quote:
 Original post by zurekxWell z' is only gonna be 0 when z is zero. This should never happen since you got a near plane and everything behind it should be clipped away.

By DirectX convention in clip space z has range [0;w] and 0 means a point on the near plane.

Quote:
 Original post by zurekxI haven't done the math in a long time, but I don't see why you would want to interpolate 1/z'. 1/w or 1/z is correct I think, it doesn't really matter since w depends linearly of z. You can either interpolate 1/z and do the inverse to get the actual depth, or interpolate z/w and 1/w and divide z/w by 1/w.

I think I can't just interpolate 1/z, because it's in homogeneous coordinates, so I need to include division by w somewhere.

##### Share on other sites
I just changed my post a little bit before I saw your answer. I haven't worked with the matrices in DirectX, but usually the z clip coordinate is in [-1, 1]. But you shouldnt divide by the z clip coordinate, you should divide by w.

No you shouldnt use just 1/z, since you are using homogenous coordinates and projection matrices and such things. But if you're just thinking, "hey I wanna draw a triangle", you can get away with interpolating 1/z. But if you're somewhat serious and want to make things thw right way, you use a projection matrix. Then you should interpolate 1/w. This will _basically_ be the same thing since w usually is a multiple of z. Maybe I'm mixing things up a little bit though.

The important things though are: w will be a multiple of z. It will never be 0 since it's a multiple of z, and the minimum value of z is the near-plane, which is never 0. It doesn't really matter if you interpolate 1/z or 1/w, but you should use 1/w if you use homogenous coordinates, that's standard.

##### Share on other sites
I'll be using this rasterizer for geometry culling, so it needs to be accurate and as fast as possible. That's why I asked if the 1/z' way is correct, as interpolating 1 attribute is much faster than interpolating 2 attributes and multiplication per pixel :). Anyway thanks for answers.

##### Share on other sites
Actually, I looked on the page you posted on some of the DX matrices, and you can use 1/z' aswell if you'd like. Sorry if I confused you, I've never written a rasterizer properly with homogenous coordinates. Anyway, for a depth buffer you could use 1/z'. But you can use 1/w aswell as you don't need the exact z-values. Since w is a multiple of the z-coordinate before projection, it can be used for depth tests.

Wait again :) Sorry if I change my mind all the time, I've had a few glasses of wine :) But you should be able to interpolate just z', not 1/z'.

Let's work it out. If you have a world space coordinate (x, y, z, 1) and you multiply it with the projection matrix, you should have something on the form (xxx, xxx, z*a + b, z * c), for some constants a,b,c. Now if you divide the new z-coordinate by the w-coordinate (to obtain what you called z'), you should get something like Constant1 + Constant2 / z. This is a number that depends on the inverse of z. You should be able to interpolate it linearly in screen space, and just store that value in the depth buffer for comparision.