# PerspectiveFovLH mystery

## Recommended Posts

Hi I was playing around with Perspective transforms and checking I could make the same calculations manually but when I ran this: Vector3 test = new Vector3(1, 1, 5); test.TransformCoordinate(Matrix.PerspectiveFovLH(0.785f, 1.2f, 1, 10)); (fov = 0.785 45 degrees) (aspect = 1.2) (near = 1) (far = 10) it returns: X: 0.4025955 AGREED Y: 0.4831146 AGREED Z: 0.8888889 SHOULD BE 0.44444! My understanding of a perspective transform's treatment of Z values is that it scales them from the range near->far to the range 0->1 so Z' = (Z - near) / (far - near) which in the case above looks like: so Z' = (5 - 1) / (10 - 1) = 0.4444444 if you look at the directx documentation it says: w 0 0 0 0 h 0 0 0 0 zfarPlane/(zfarPlane-znearPlane) 1 0 0 -znearPlane*zfarPlane/(zfarPlane-znearPlane) 0 which means Z' = ((5 * 10) / (10 - 1)) + ((-1 * 10)/(10 - 1)) = 0.444444 the same as my calculation also when I use Vector3.Transform() instead it returns W: 5.0 X: 2.01297784 Y: 2.41557336 Z: 4.44444466 which when "projected back into w=1" which I understand as divide all components by w - you get W: 1.0 X: 0.40259558 Y: 0.4831147 Z: 0.888888955 I do not believe DirectX could be broken in this regard! Where am I going wrong?

##### Share on other sites
Quote:
 Original post by skytigerMy understanding of a perspective transform's treatment of Z valuesis that it scales them from the range near->far to the range 0->1so Z' = (Z - near) / (far - near)

This assumption is not correct. The mapping of Z-values from view space to post-projective space is not linear.

Also,
Quote:
 if you look at the directx documentation it says:w 0 0 00 h 0 00 0 zfarPlane/(zfarPlane-znearPlane) 10 0 -znearPlane*zfarPlane/(zfarPlane-znearPlane) 0which meansZ' = ((5 * 10) / (10 - 1)) + ((-1 * 10)/(10 - 1)) = 0.444444

Correct, that's Z before you project back into w=1. Dividing by w (5 in your case), gives you Z = 0.888888955 (in NDC space), which is what the function TransformCoordinate() is giving you.

So, do you see why the D3DX functions are correct now?

[Edited by - wyrzy on March 23, 2008 6:31:13 PM]

##### Share on other sites

hi

now I see

when I said:

Z' = ((5 * 10) / (10 - 1)) + ((-1 * 10)/(10 - 1)) = 0.444444

= 4.444444  ^

and the correct formula is:

Z' = ((far * Z - far * near) / (far - near)) / ZZ' = ((10 * 5 - 10 * 1) / (10 - 1)) / 5 = 0.8888888

but watch out!

Z' = ((10 * ? - 10 * 0) / (10 - 0)) / ? = 1

so if near plane == 0 then it does not work anymore
and everything will have a depth of 1

this game is just one brain teaser after another

:-)

[Edited by - skytiger on March 28, 2008 3:37:04 AM]