Non perspective correct interpolation in screen space of texture coordinates and other attributes

Question


«I want to read screen coordinates directly in a pixel shader or I need a value interpolated in screen space. I have to run on D3D9 hardware with only shader model 2.x support so I can't always use the shader model 3.0 system values or even Direct3D10 non perspective correct interpolation. How do I interpolate values in screen space without the compulsory perspective correction in Direct3D9 ?»


Answer


That's relatively simple. And we'll use the concept of projective texture that have been supported by graphics hardware for some time already (making this solution accessible even on some fixed function hardware). Basically you want to premultiply each texture coordinate by w, the homogenous coordinate that is output by the vertex processing unit and that controls the perspective. But let's detail that a bit further.

Texcoords are not directly interpolated linearly in screen space. You probably know that. Linear interpolation in screen space is still a part of the rasterization process though. That means that what is linearly interpolated instead is s/w, t/w and 1/w. The value is being computed by the triangle setup at each vertex (s0/w0, s1/w1, s2/w2) and then linearly interpolated in screen space. And then there's a division occurring implicitly in the pixel shading unit to retrieve (s/w) / (1/w) = s that is your perspective correct s.

So how to undo the result of the perspective correction ?

Be it two values s' and t' that you want to linearly interpolate (to differentiate them from perspective correct values).

Let's imagine that you pass (s' * w, t' * w, w) as your interpolated attribute instead of s, t. W being of course equal to the w value that you output at each vertex along x,y,z. That means that triangle setup will send (s' * w / w, t' * w / w, w / w) = (s', t', 1) to be interpolated. The result ? s' and t' get interpolated linearly in screen space as well as a constant attribute = 1. That's what you wanted.. but we're not finished. Along those values, 1/w is still being interpolated linearly and in the pixel shader you will divide s' by 1/w.

So your first texcoord will be s'*w, you second texcoord t'*w and your third texcoord w.

You see where we go from there. to retrieve the non perspective correct s', you divide the first texcoord s'*w by the third texcoord w. You can either do that explicitely with a division in the pixel shader or simply by setting a projective texture read (projective texture read will automatically divide s,t,q by fourth texcoord r.).

The use of projective textures here kind of make sense when you think about it. A projective texture "projects" its texture coordinate grid into the scene from a single point of origin. If you confound that point of origin with your optical center, then what you project is your "screen space aligned" grid.


If you want to learn more..




Partner websites : LEGREG | GRAPHICS | GRAPHISME | PHOTOGRAPHY | OUT OF MY MIND | ANIMATION MENTOR | GREEN LIVING | VOXEL | RAY TRACING | GUENARDI | Add this page rank counter to your page.