0
votes

Does the technique that vulkan uses (and I assume other graphics libraries too) to interpolate vertex attributes in a perspective-correct manner require that the vertex shader must normalize the homogenous camera-space vertex position (ie: divide through by the w-coordinate such that the w-coordinate is 1.0) prior to multiplication by a typical projection matrix of the form...

 g/s  0    0         0
  0   g    0         n
  0   0    f/(f-n)   -nf/(f-n)
  0   0    1         0

...in order for perspective-correctness to work properly?

Or, will perspective-correctness continue to work on any homogeneous vertex position in camera-space (with a w-coordinate other than 1.0)?

(I didn't completely follow the perspective-correctness math, so it is unclear which to me which is the case.)

Update:

In order to clarify terminology:

vec4 modelCoordinates = vec4(x_in, y_in, z_in, 1);
mat4 modelToWorld = ...;
vec4 worldCoordinates = modelToWorld * modelCoordinates;
mat4 worldToCamera = ...;
vec4 cameraCoordinates = worldToCamera * worldCoordinates;
mat4 cameraToProjection = ...;
vec4 clipCoordinates = cameraToProjection * cameraCoordinates;
output(clipCoordinates);

cameraToProjection is a matrix like the one shown in the question

The question is does cameraCoordinates.w have to be 1.0?

And consequently the last row of both the modelToWorld and worldToCamera matricies have to be 0 0 0 1?

2
"The question is does cameraCoordinates.w have to be 1.0?" It will be whatever your mathematics says that it needs to be. I don't understand your question. You're doing math to achieve some purpose. The numbers should be the ones that achieve that purpose. You can mathematically do transformations in post-projective space; that's mathematically legitimate and such matrices will not necessarily have a W of 1. - Nicol Bolas
@NicolBolas: It's not clear to me what you're not understanding. Anyway, for anyone that does understand the question, I think I've concluded that yes W in cameraCoordinates has to be 1.0 for the usual projection matrix to work (ie homogeneous cameraCoordinates have to be in normal form in the shader). Z_camera becomes W_clip and see "Basic Polygon Rasterization" in the Vulkan spec. Associated datum for a fragment use barycentric coordinates based off framebuffer coordinates and the W_clip. So I think unnormalized camera coordinates won't work. - Andrew Tomazos
I just linked you to an example of doing rotations in post-projection homogenous coordinates. So no, W does not "have to be" 1.0, and thinking that it does is hazardous to properly understanding the math behind this stuff. - Nicol Bolas
@NicolBolas: As shown in the above code, the cameraCoordinates are multiplied by the given projection matrix and output from the vertex shader. The question is do those cameraCoordinates have to be normalized (homogeneous coordinates with a W value of 1.0). I'm not talking about post-projective transformations or anything else. - Andrew Tomazos
"The question is do those cameraCoordinates have to be normalized" "have to be" in order for what to happen? Why are you questioning whether your camera space is homogeneous or not? That is, why do you think that W might not be 1? Don't you control the inputs to this code? - Nicol Bolas

2 Answers

2
votes

You have this exactly backwards. Doing the perspective divide in the shader is what prevents perspective-correct interpolation. The rasterizer needs the perspective information provided by the W component to do its job. With a W of 1, the interpolation is done in window space, without any regard to perspective.

Provide a clip-space coordinate to the output of your vertex processing stage, and let the system do what it exists to do.


the vertex shader must normalize the homogenous camera-space vertex position (ie: divide through by the w-coordinate such that the w-coordinate is 1.0) prior to multiplication by a typical projection matrix of the form...

If your camera-space vertex position does not have a W of 1.0, then one of two things has happened:

  1. You are deliberately operating in a post-projection world space or some similar construct. This is a perfectly valid thing to do, and the math for a camera space can be perfectly reasonable.

  2. Your code is broken somewhere. That is, you intend for your world and camera space to be a normal, Euclidean, non-homogeneous space, but somehow the math didn't work out. Obviously, this is not a perfectly valid thing to do.

In both cases, dividing by W is the wrong thing to do. If your world space that you're placing a camera into is post-projection (such as in this example), dividing by W will break your perspective-correct interpolation, as outlined above. If your code is broken, dividing by W will merely mask the actual problem; better to fix your code than to hide the bug, as it may crop up elsewhere.

0
votes

To see whether or not the camera coordinates need to be in normal form, let's represent the camera coordinates as multiples of w, so they are (wx,wy,wz,w).

Multiplying through by the given projection matrix, we get the clip coordinates (wxg/s, wyg, fwz/(f-n)-nfw/(f-n)), wz)

Calculating the x-y framebuffer coordinates as per the fixed Vulkan formula we get (P_x * xg/sz +O_x, P_y * Hgy/z + O_y). Notice this does not depend on w, so the position in the framebuffer of a polygons verticies doesn't require the camera coordinates be in normal form.

Likewise calculation of the barycentric coordinates of fragments within a polygon only depends on x,y in framebuffer coordinates, and so is also independant of w.

However perspective-correct perspective interpolation of fragment attributes does depend on W_clip of the verticies as this is used in the formula given in the Vulkan spec. As shown above W_clip is wz which does depend on w and scales with it, so we can conclude that camera coordinates must be in normal form (their w must be 1.0)