Let's say that I have standard left-handed WorldToView
and ViewToScreen
row-major matrices in the same vein as the DirectX D3DXMatrixPerspectiveLH functions, like so:
EXVector vView = NormalizeVector(LookAt() - m_Position);
float fDotProduct = DotProduct(m_WorldUp, vView);
EXVector vUp = NormalizeVector(m_WorldUp - fDotProduct * vView);
// Generate x basis vector (crossproduct of y&z basis vectors)
EXVector vRight = CrossProduct(vUp, vView);
// Generate the matrix
row0.Set(vRight.x, vUp.x, vView.x, 0);
row1.Set(vRight.y, vUp.y, vView.y, 0);
row2.Set(vRight.z, vUp.z, vView.z, 0);
row3.Set(-DotProduct(m_Position, vRight),
-DotProduct(m_Position, vUp),
-DotProduct(m_Position, vView), 1);
EXMatrix mWorldToView(row0, row1, row2, row3);
Here's the left-handed mViewToScreen
/ projection matrix:
float zNear = 0.001f;
float zFar = 1000.000f;
float Aspect = DisplayHeight() / DisplayWidth();
float sinfov, cosfov; qsincosf(VFOV() / 2, sinfov, cosfov);
float cotfov = cosfov / sinfov; // cos(n) / sin(n) = 1/tan(n)
float w = Aspect * (cotfov);
float h = 1.0f * (cotfov);
float Q = zFar / (zFar - zNear);
float R = -Q * zNear;
row0.Set(w, 0, 0, 0);
row1.Set(0, h, 0, 0);
row2.Set(0, 0, Q, 1);
row3.Set(0, 0, R, 0);
EXMatrix mViewToScreen(row0, row1, row2, row3);
Many things like map/object culling depend on this fact:
// View to cull matrix
Q = ( zFar + zNear) / (zFar - zNear);
R = (2.0f * zFar * zNear) / (zFar - zNear);
row0.Set(w, 0, 0, 0);
row1.Set(0, h, 0, 0);
row2.Set(0, 0, Q, 1);
row3.Set(0, 0, R, 0);
EXMatrix mViewToCull(row0, row1, row2, row3);
Does anyone know how to derive the infamous "reverse depth with infinite far plane" from the original blog post for mViewToScreen
and mViewToCull
? Every single reference I have found (nlguillemot and nVidia, for example) is in the right-handed space.
Normally I am able to figure things out visually, but 4D matrices are a headache.