Z Value after Perspective Divide is always less than -1
Asked Answered
P

2

7

So I'm writing my own custom 3D transformation pipeline in order to gain a better understanding of how it all works. I can get everything rendering to the screen properly and I'm now about to go back and look at clipping.

From my understanding, I should be clipping a vertex point if the x or y value after the perspective divide is outside the bounds of [-1, 1] and in my case if the z value is outside the bounds of [0, 1].

When i implement that however, my z value is always -1.xxxxxxxxxxx where xxxxxxx is a very small number.

This is a bit long, and I apologize, but I wanted to make sure I gave all the information I could.

First conventions:

I'm using a left-handed system where a Matrix looks like this:

[m00, m01, m02, m03]
[m10, m11, m12, m13]
[m20, m21, m22, m23]
[m30, m31, m32, m33]

And my vectors are columns looking like this:

[x]
[y]
[z]
[w]

My camera is set up with:

A vertical FOV in radians of PI/4.

An aspect ration of 1. (Square view port)

A near clip value of 1.

A far clip value of 1000.

An initial world x position of 0.

An initial world y position of 0.

An initial world z position of -500.

The camera is looking down the position Z axis (0, 0, 1)

Given a vertex, the pipeline works like this:

Step 1: Multiply the vertex by the camera matrix.

Step 2: Multiply the vertex by the projection matrix.

Projection matrix is:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  1]
[0,       0,       -1.001001, 0]

Step 3: Multiply the x, y and z components by 1/w.

Step 4: [This is where the problem is] Clip the vertex if outside bounds.

Step 5: Convert to screen coordinates.

An example vertex that I have is

(-100, -100, 0, 1)

After multiplying by the camera matrix i get:

(-100, -100, 500, 1)

Which makes sense because relative to the camera, that vertex is 100 units to the left and down and 500 units ahead. It is also between the near clip of 1 and the far clip of 1000. W is still 1.

After multiplying by the projection matrix i get:

(-241.42135, -241.42135, 601.600600, -600.600600)

This I'm not sure if it makes sense. The x and y seem to be correct, but i'm iffy about the z and w since the next step of perspective divide is odd.

After the perspective divide I get:

(0.401966, 0.401966, -1.001665, 1)

Again the x and y make sense, they are both within the bounds of [-1, 1]. But the z value is clearly outside the bounds even though i believe it should still be within the frustrum. W is back to 1 which again makes sense.

Again apologies for the novel, but I'm hoping someone can help me figure out what I'm doing incorrectly.

Thanks!

Poliomyelitis answered 15/7, 2010 at 13:18 Comment(0)
P
4

Ok, it looks like I figured out what the problem it was.

My projection matrix was:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  1]
[0,       0,       -1.001001, 0]

But it really should be transposed and be:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  -1.001001]
[0,       0,       1,         0]

When using this matrix, my x and y values stay the same as expected and now my z values are constrained to be within [0, 1] and only exceed that range if they are outside the near of far clip plane.

The only issue now is that I'm quite confused as to whether I'm using a right or left handed system.

All i know is that now it works...

Poliomyelitis answered 16/7, 2010 at 14:57 Comment(2)
Good stuff. I'm glad to hear you got it figured out :)Mondragon
Thanks for your help though, i definitely appreciate it.Poliomyelitis
M
2

I may be out of my league here, but I thought that the purpose of the projection matrix and perspective divide were to discover the 2D position of that point on the screen. In that case, the left-over z value would not necessarily have any meaning any more, since the math is all geared towards finding those two x and y values.

Update: I think I have it figured out. Your math is all correct. The camera and frustum you describe has a near clipping plane at Z=1, so your example point at (-100, 100, 0) is actually outside of the clipping plane, so that z-buffer value of just below -1 makes perfect sense.

Try a sample point with a z-coordinate inside your frustum, say with a z-coordinate of 2.

Mondragon answered 15/7, 2010 at 13:31 Comment(6)
Hmmn, ok I guess that makes sense since the rendering is still correct. But do i not need that z value to store in my depth buffer? And if i am storing it, does it not need to be between the bounds of [0, 1] or at least [-1, 1]?Poliomyelitis
Have a look at gamedev.net/community/forums/topic.asp?topic_id=483363. I think you may have to do the clipping before dividing by w. In that case, you could calculate the z buffer value in the clipping algorithm, where it would be simply be z/1500 (in your example).Mondragon
Please disregard my previous two comments, and see the update I posted.Mondragon
Ok cool, so i tried that and still no dice. Which makes sense because 0 isn't outside my depth range because the range is relative to the camera, not in absolute terms. However I did manage to solve it and I'll respond below with the answer.Poliomyelitis
scratchapixel.com/lessons/3d-advanced-lessons/…Nucleon
e.James, you mentioned the "left-over z value", but i would just like to point out (in case you haven't found this out, yet) that this z value is used as the x-y-coordinates' corresponding depth in the Depth Buffer.Nanette

© 2022 - 2024 — McMap. All rights reserved.