4

To improve my understanding of OpenGL and 3D I am trying to implement a simple rendering pipeline running only on the CPU. Where it makes sense, I'm trying to use the same standards as OpenGL. For example, I'm using a right handed coordinate system like OpenGL. As it often happens when learning something new, I've now run into a question I cannot find an answer to. If something in the following doesn't make sense, please forgive and correct me.

In clip space (the coordinate you give to gl_Position in your vertex shader), negative Z is away from the user. But in the depth buffer, positive Z is away (if you're using the default depth settings).

One answer to this question suggests that the flip is due to the projection transformation. But I made a little experiment (based on WebGL/OpenGL ES) that suggests the opposite: In clip space, Z is pointing away from the user even if you don't use a projection transformation.

So at some point, after you've handed it your gl_Position, OpenGL flips the Z coordinate. When and how is that?

My guess is that it is in the viewport transform but I haven't been able to find documentation that supports this.

Community
  • 1
  • 1

2 Answers2

4

Clip-Space in OpenGL is already left handed (and always was). So, in modern GL there is no space explicitely using a right-handed system, and there is no "flipping" done at all. However, the eye space in old GL was often defined right-handed, and the "flipping" was done as part of the projection matrix, glFrustum() and gluPerpective() explicitely expect positive values for near and far to refer to the repsective negative z values. However, as you could use arbitrary matrices, you never were forced to define your eye or object spaces right-handed, it was just something like a default convention. And still a lot of people follow this convention with the programmable pipeline.

derhass
  • 43,833
  • 2
  • 57
  • 78
  • That explains a lot. However, it doesn't explain why [my little example program](https://github.com/rasmusrn/webgl_triangles) suggests the opposite. Basically, I'm setting up two triangles and then push them through the simplest possible shaders I could think of. If clip space is left handed I would expect the triangle with the highest z coordinate to come out on top, but it doesn't. The meat of the program is in [`app.js`](https://github.com/rasmusrn/webgl_triangles/blob/master/javascript/app.js). It should be fairly easy to read. Why is the green triangle on top of the other? – Rasmus Rønn Nielsen Jul 15 '13 at 16:17
  • @RasmusRønnNielsen: think about it. i a left-handed system, z is pointing away from you, so the traingle with the lowest z value will be on top. If we ignore perspective and the w component for a moment (as your code does), clip space is identical to normalized device space and at z=-1 lies the near plane (front of the frustum), and at z=1 lies the far (back) plane, so all is well, isn't it? – derhass Jul 15 '13 at 16:30
  • @RasmusRønnNielsen: also, I have not checked if and how you set up the `DEPTH_TEST` in your code. So the drawing order might fully determine what comes out on top if the test is disabled. Otherwise, assuming a stanard depth test setup, the green triangle (z=-0.9) should be on top of the red (z=0) one. – derhass Jul 15 '13 at 16:37
  • Yes, I see now. It makes perfect sense. In retrospect, I don't understand how I got myself so confused about it. Thank you very much :) – Rasmus Rønn Nielsen Jul 16 '13 at 06:43
0

According to WebGL Beginner's Guide, the z-axis is inverted during the perspective division which is done after the projection transform.

Here is what it says:

The perspective division transforms the viewing frustum into a cube centered in the origin with minimum coordinates [-1,-1,-1] and maximum coordinates [1,1,1]. Also, the direction of the z-axis is inverted, as shown in the following figure:

enter image description here

jz1108
  • 1,300
  • 1
  • 11
  • 14