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.