Perspective correct interpolation

Reading this very useful series about the graphics pipeline I realized I had never thought about what is the proper way to interpolate between vertex attributes (outputted by the vertex, domain or geometry shader to the pixel shader) using the vertices of the triangle after perspective divison. I spent some time thinking on that, and although it’s not hard to figure out and the result is described in the link above, I thought I describe one possible way to get the solution.

Let’s assume we have a triangle before perspective divison with vertices (p_0, w_0), (p_1, w_1)  , (p_2,w_2)  with some corresponding vertex attributes c_0  , c_1  , c_2  (e.g. texture coordinates, color, normal). After perspective divison we have p'_0=\frac{p_0}{w_0}  , p'_1=\frac{p_1}{w_1}  , p'_2=\frac{p_2}{w_2}  . Let’s have p'=(1-t'_1-t'_2)p'_0+t'_1p'_1+t'_2p'_2  . The question is, how should we compute the proper vertex attribute c  corresponding to p'  ?

Let’s think backward: assume we have p=(1-t_1-t_2)p_0+t_1p_1+t_2p_2  . Then, of course, the vertex attribute corresponding to p  is simply c= (1-t_1-t_2)c_0+t_1c_1+t_2c_2  . Now, what is the point p'  we get from p  after perspective divison? Using the notation w =  (1-t_1-t_2)w_0+t_1w_1+t_2w_2  we have

p' =\frac{p}{w} \\ \quad =  \frac{(1-t_1-t_2)p_0+t_1p_1+t_2p_2 }{w} \\ \quad =\frac{(1-t_1-t_2)w_0}{w}\frac{p_0}{w_0}+ \frac{t_1w_1}{w}\frac{p_1}{w_1} +  \frac{t_2w_2}{w}\frac{p_2}{w_2} \\ \quad =  \frac{(1-t_1-t_2)w_0}{w}p'_0+ \frac{t_1w_1}{w}p'_1 + \frac{t_2w_2}{w}p'_2

Well, it’s easy to check that the sum of the coefficients in the above interpolation between p'_0  , p'_1  and p'_2  is 1  . So by setting t_1'= \frac{t_1w_1}{w}  and t_2'= \frac{t_2w_2}{w}  , we can write p'= (1-t'_1-t'_2)p'_0+t'_1p'_1+t'_2p'_2  .

And basically, we are done: for a point p'= (1-t'_1-t'_2)p'_0+t'_1p'_1+t'_2p'_2  , the corresponding vertex attribute is c=  (1-t_1-t_2)c_0+t_1c_1+t_2c_2  , where t_1  and t_2  can be computed from the two equations t_1'= \frac{t_1w_1}{w}  and t_2'= \frac{t_2w_2}{w}  , where w =  (1-t_1-t_2)w_0+t_1w_1+t_2w_2  .

Of course, we can solve for t_1  and t_2  explicitly (it’s just a system a linear equations with two variable), and we get

t_1 = \frac{t'_1w^{-1}_1}{\tilde{w}}  , and t_2 = \frac{t'_2w^{-1}_2}{\tilde{w}}  ,

where \tilde{w} = (1-t'_0-t'_1)w^{-1}_0 +  t'_1w^{-1}_1  +t'_2 w^{-1}_2  . We can go further by substituting t_1  and t_2  into the equation for c

c=  (1-t_1-t_2)c_0+t_1c_1+t_2c_2   \\ (1- \frac{t'_1w^{-1}_1}{\tilde{w}} - \frac{t'_2w^{-1}_2}{\tilde{w}} )c_0 +  \frac{t'_1w^{-1}_1}{\tilde{w}} c_1 +  \frac{t'_2w^{-1}_2}{\tilde{w}} c_2 \\ =   ((\tilde{w} -   t'_1w^{-1}_1  -  t'_2w^{-1}_2)c_0 +   t'_1w^{-1}_1 c_1 +  t'_1w^{-1}_2 c_2)/\tilde{w} \\= ((1-t'_1-t'_2)\frac{c_0}{w_0} + t'_1\frac{c_1}{w_1} + t'_2\frac{c_2}{w_2})/\tilde{w}

Therefore, to do the interpolation in practice, we have two main choices:

  • For given t'_1  and t'_2  values (that is, basically, for a given pixel inside the triangle) we calculate t_1  and t_2  , and use them to calculate all vertex attributes by a simple linear interpolation.
  • For all vertex attributes c_i  , we compute the corresponding \frac{c_i}{w_i}  values, and use them to calculate the vertex attributes directly from given t'_1  and t'_2  .

Of course, in both cases we have to compute \tilde{w}  as well.

Leave a comment