Jump to content
  • Advertisement
Sign in to follow this  
Deckards

Projection Matrix

This topic is 4886 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need to build the projection matrix (with a fov value) to transform my geometry in a software renderer. I'm using a right-handed coordinate system. The x, y values need to be clamped to [-1,1] and the z values need to be clamped to [0,1]. The result of the transformation is completely wrong and I really don't understand why... With a far plane at 10000 and a near plane at 1, a z values of about 5000 should be transformed into ~= 0.5, right? The matrix I build is: w 0 0 0 0 h 0 0 0 0 q qn 0 0 -1 0 with: q = -zFarPlane/(zFarPlane-zNearPlane) qn = -zFarPlane*zNearPlane/(zFarPlane-zNearPlane) Here are the 2 functions I wrote that build the projection matrix and transform a 3D Vector:
Matrix4 Matrix4::Perspective(real32 fov, real32 aspectRatio, real32 zNearPlane, real32 zFarPlane)
{
	Matrix4 mat;
	real32 fHeight = 1.0 / tan(DEGTORAD(fov) * 0.5);
	real32 fWidth = fHeight / aspectRatio;

	mat._00 = 2.0*zNearPlane/fWidth;
	mat._01 = 0.0;
	mat._02 = 0.0;
	mat._03 = 0.0;

	mat._10 = 0.0;
	mat._11 = 2.0*zNearPlane/fHeight;
	mat._12 = 0.0;
	mat._13 = 0.0;

	mat._20 = 0.0;
	mat._21 = 0.0;
	mat._22 = -zFarPlane / (zFarPlane-zNearPlane);
	mat._23 = -zFarPlane*zNearPlane / (zFarPlane-zNearPlane);

	mat._30 = 0.0;
	mat._31 = 0.0;
	mat._32 = -1.0;
	mat._33 = 0.0;

	return mat;
}

inline Vector3 Matrix4::Transform(const Vector3& v) const
{
	Vector3 vecNew;

	real fInvW = 1.0 / (m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3]);

	vecNew.x = (m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3]) * fInvW;
	vecNew.y = (m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3]) * fInvW;
	vecNew.z = (m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]) * fInvW;

	return vecNew;
}


Any help would be greatly appreciated! Thanks [Edited by - Deckards on July 28, 2005 9:39:12 AM]

Share this post


Link to post
Share on other sites
Advertisement
Thanks the link. My matrix is a bit different from the OpenGL one because I need to clamp the Z values to [0.1] instead of [-1,1].
Unfortunately, I still don't understand why my results are wrong :(

Share this post


Link to post
Share on other sites
Quote:
Original post by Deckards
With a far plane at 10000 and a near plane at 1, a z values of about 5000 should be transformed into ~= 0.5, right?


This may be the source of your confusion: the world Z values are not mapped linearly into [0,1] space. Generally most of the [0,1] range will be taken up by the area very near to the camera. I haven't done the math for this case but I wouldn't be surprised if the Z buffer value at 5000 ends up > .99. What actual value did you get?

Your functions look correct from a cursory glance.

Share this post


Link to post
Share on other sites
Quote:
Original post by ganchmaster
This may be the source of your confusion: the world Z values are not mapped linearly into [0,1] space. Generally most of the [0,1] range will be taken up by the area very near to the camera.


Yes, the Z values aren't mapped linearly into [0,1] space, but as [0,1] is the view volume between the near and far plane, all the vertices that have a Z value in the [near,far] range should have their transformed value in the [0,1] range, right?

I get the following homogeneous values with those properties:
near=0.1 far=10000 fov=90 aspect=1.33
Those are negative values because the camera looks down the Z axis.

-10000 -> 1.0
-5000 -> 0.99
-5 -> 0.98
-2 -> 0.95
-0.1 -> ~0


[Edited by - Deckards on July 28, 2005 11:11:19 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Deckards
Yes, the Z values aren't mapped linearly into [0,1] space, but as [0,1] is the view volume between the near and far plane, all the vertices that have a Z value in the [near,far] range should have their transformed value in the [0,1] range, right?


Yeah, that is correct. So I guess what I stated earlier is not the problem.

It looks like the sign of your mat._23 term is incorrect. Usually people have +1 as the _32 parameter, and the signs of the _22 and _23 terms are + and -, respectively. Since you have -1 as _32, probably the signs of _22 and _23 should be - and +.

Share this post


Link to post
Share on other sites
Quote:
Original post by DeckardsI get the following homogeneous values with those properties:
near=0.1 far=10000 fov=90 aspect=1.33
Those are negative values because the camera looks down the Z axis.

-10000 -> 1.0
-5000 -> 0.99
-5 -> 0.98
-2 -> 0.95
-0.1 -> ~0
Those values are correct. Read this.

From the calculator on that page, with a 24 bit depth buffer...

z-distance value value scaled to [0,1]
10000 16777216 1.0000000596046483281045155587504
5000 16777048 0.99999004602372920654590168868909
5 16441836 0.98000985264836863567642186143529
2 15938514 0.95000952184257041469636051037076
0.1 0 0.0
Your near value is way too close, push it out as far as possible.

EDIT: There's a slight bug (rounding bug I assume) in that calculator, the max value for 24-bits is 16777215, that's why the scaled value for 10000 is slightly larger than 1.0

Share this post


Link to post
Share on other sites
Thank you very much!
I thought those values were weird but thanks to this calculator, I now undersand that it was alright :)

[Edited by - Deckards on July 30, 2005 4:47:31 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!