# Why does OpenGL require all coordinates in [-1,1] (NDC)?

Why shouldn't the z coordinate be normalized to the [0,1] range instead of [-1,1]? As I understand it, that happens some time after anyways, so what's the catch with this?

There's one massive advantage to NDC's Z being defined as [0,1] and it has to do with floating point precision.

Since about 2006, the standard advice from GPU vendors to avoid z-fighting has been to use a projection matrix that maps the far plane to z=0 and the near plane to z=1 and to use a floating point depth buffer.

Perspective projection results in a hyperbolic precision density that favours the near plane (which results in terrible precision beyond about near*2). Floating point formats have logarithmic precision density that favours 0. Combining these two facts with the above mentioned "backwards" projection matrix results in those two curves almost cancelling out, giving approximate linear precision density across the entire Z range, without sacrificing performance or interpolation quality (unlike some other linear/logarithmic depth buffer schemes).

Unfortunately this trick (which is now standard practice) does not work with OpenGL's "nice, symmetrical" NDC coordinate system -- you have to enable a GL extension to opt in to the NDC definition used by every other sane graphics API.

• The GL extension Brooke's referring to is, I believe, glDepthRangedNV, which is currently supported by both NVidia and AMD GPU drivers, but not by Intel. Commented Sep 30, 2016 at 1:30
• It's ARB_clip_control; by the time of the depth range transformation, the precision would already have been lost. For more information see for example this NVidia blog entry. Commented May 21, 2017 at 8:15
• @Buster: It's in core OpenGL as of 4.5. Commented Jul 13, 2017 at 12:50

The question could very easily be turned around: why the [0, 1] range? What makes that range special?

NDC space is a cube; every component is on the [-1, 1] range. So it's very nice, neat, and uniform. That's why OpenGL uses that space. It's simple, obvious, and very regular.

What you suggest is to turn that nice, neat, uniform cube into a rectangular prism. There is nothing to gain from such a space. Why be irregular when you can be regular?

As I understand it, that happens some time after anyways

No, it does not. The transform from NDC space to window space uses the current glDepthRange setting. That may be [0, 1], and that's what it is by default. But there's no rule that it must be. It can be anything you want, so long as both values are between 0 and 1. You can even reverse the near and far, using a range of [1, 0].

• Another good thing is that with a [-1, 1] range it's easier to figure out a negative/opposite direction compared to a [0, 1] range when you need to manipulate something. (At least I find it easier) Commented May 13, 2012 at 12:43
• I would add that you have an extra bit of information, so before depth value is saved into the 24 bit buffer it could have 1 more right bit in the pre-final calculation (does not matter that much :D) Commented Feb 13, 2015 at 11:43
• "why the [0, 1] range?" ... "It can be anything you want, so long as both values are between 0 and 1." lol so then the question is, why glDepthRange clamps the depth range between 0 to 1? ;) checkmate. maybe cause this range gets scaled to unsigned depth bits max value perhaps? ;) just like with color. lol you could've also tried explaining why directx doesn't do this unneeded mapping. obviously the reason was just to make it a symmetrical cube. there's no loss since they remap via glDepthRange anyway. there's nothing "irregular" about mapping directly to what's more useful. lol Commented Dec 3, 2019 at 0:01
• @Puddle: "obviously the reason was just to make it a symmetrical cube." Isn't that what I said when I said that NDC space was a cube? I'm not sure I understand your comment here. Commented Dec 3, 2019 at 2:23
• that's true for all questions. anyone would still clearly be looking to know if there's any practical use/need for [-1,+1] over [0,1]. if there were (say you knew it's more applicable for cool effects in the shader), that's what anyone would be answering with over a visually pleasing artifact that everyone already noticed. the only valid point you had were the "nothing to gain" which was really, nothing to lose in using [-1,+1]. what i mainly had a problem with was your point with glDepthRange. which should've been, which is why there's no loss. the output is still between [0,1] regardless. Commented Dec 3, 2019 at 19:27