Why do I divide Z by W in a perspective projection in OpenGL?
Asked Answered
S

2

13

I guess this is more a math question than it is an OpenGL one, but I digress. Anyways, if the whole purpose of the perspective divide is to get usable x and y coordinates, why bother dividing z by w? Also how do I get w in the first place?

Solleret answered 30/8, 2014 at 16:44 Comment(3)
en.wikipedia.org/wiki/…Houston
This has to do with homogenous coordinates. They mapping R^3 -> R^4 is clearly not one-to-one. The w factor can be 'cannonized' to 1. But one applying 4x4 matrix operator the resulted 'w' may change. If I recall correctly, one advantage of homogenous-coordinates is to have translation as a linear operator.Belongings
IMO the shortest answer is - because dividing z by w ultimately affects x and y values. In the next step in gpu pipeline you divide x and y by z to have 2d NDC space that can be transformed into screen coordinates.Godoy
C
24

Actually, the explanation has much more to do with the limitations of the depth buffer than it does math.

At its simplest, "the depth buffer is a texture in which each on-screen pixel is assigned a grayscale value depending on its distance from the camera. This allows visual effects to easily alter with distance." Source

More accurately, a depth buffer is a texture containing the value of z/w for each fragment, where:

  • Z is the distance from the near clipping plane to the fragment.
  • W is the distance from the camera to the fragment.

In the following diagram illustrating the relationship between z, w, and z/w, n is equal to the zNear parameter passed to gluPerspective, or an equivalent function, and f is equal to the zFar parameter passed to the same function.

Diagram illustrating the relationship between *z*, *w*, and *z*/*w*

At a glance, this system look unintuitive. But as a result, z/w is always a floating-point value between 0 and 1 (0/n and f/f), and can therefore be represented as a single channel of a texture.

A second important note: the depth buffer is nonlinear, meaning an object exactly in between the near and far clipping planes is nowhere near a value of 0.5 in the depth buffer. As shown above, it would correlate to a value of 0.999 in the depth buffer. Depending on your view, this could be good or bad; you may want the depth buffer to be more detailed close-up (which it is), or offer even detail throughout (which it doesn't).

TL;DR:

  • You divide z by w so it is always in the range [0, 1].
  • W is the distance from the camera to the fragment.
Chlorophyll answered 30/8, 2014 at 22:9 Comment(4)
I really don't quite agree with this answer, the question pertains to a purely mathematical problem, what is explained here is an opengl and z-buffer algorithm implementation detail (the depth buffer).Fortier
The z in NDC is in range [-1, 1], not [0, 1] which is DirectX convention.Tracheotomy
why at the furthest fragment, both w and z are f? There is "n" distance between w and z starting points. Thank you.Consortium
Z is the distance from the near clipping plane to the fragment. W is the distance from the camera to the fragment. I think I can safely assume that these sentences apply in DirectX as well.Aylmer
G
0

Mathematically if you forget to divide by w which contains -z, then you'll notice that points or objects won't appear smaller the further they are from the camera.

Golfer answered 6/2 at 19:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.