Fix orthographic projection

OrthoFrustum and OrthoMatrix were not properly set up for reverse-Z.
This PR fixes it by using the proper inversion of a right-handed ortho matrix.
master
Webster Sheets 2021-01-15 21:10:42 -05:00
parent 719e652257
commit 3bd735e40d
2 changed files with 17 additions and 7 deletions

View File

@ -483,8 +483,7 @@ void ModelViewer::Update(float deltaTime)
if (m_zoom <= 0.0) m_zoom = 0.01;
float screenW = Graphics::GetScreenWidth() * m_zoom / 10;
float screenH = Graphics::GetScreenHeight() * m_zoom / 10;
matrix4x4f orthoMat = matrix4x4f::OrthoFrustum(-screenW, screenW, -screenH, screenH, 0.1f, 100000.0f);
orthoMat.ClearToRotOnly();
matrix4x4f orthoMat = matrix4x4f::OrthoMatrix(screenW, screenH, 0.1f, 100000.0f);
m_renderer->SetProjection(orthoMat);
}

View File

@ -245,7 +245,7 @@ public:
const T e = 1 / tan(fovR / T(2));
const T x = fovX ? e : e / aspect;
const T y = fovX ? e / aspect : e;
const T z = (zfar) / (zfar - znear) - 1;
const T z = (znear) / (zfar - znear);
const T w = (zfar * znear) / (zfar - znear);
// Based on: http://www.terathon.com/gdc07_lengyel.pdf
@ -295,17 +295,27 @@ public:
///////////////////////////////////////////////////////////////////////////////
// set a orthographic frustum with 6 params similar to glOrtho()
// (left, right, bottom, top, near, far)
//
// Derived from:
// [1] https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthorh
// [2] https://thxforthefish.com/posts/reverse_z/
//
// Specifically, the `tz` and `c` terms are based on a right-handed DirectX-style
// (Z=0..1) matrix [1], multiplied by the given reversing matrix [2].
// If looking at the sources, keep in mind that [1] is presented in row-major order
// and [2] is presented in column-major order, and thus multiplication occurs in
// column-column fashion.
///////////////////////////////////////////////////////////////////////////////
static matrix4x4 OrthoFrustum(T left, T right, T bottom, T top, T znear, T zfar)
{
assert((znear >= T(-1)) && (zfar > T(0)));
T a = T(2) / (right - left);
T b = T(2) / (top - bottom);
T c = T(1) / (zfar - znear) - 1;
T c = T(1) / (zfar - znear);
T tx = (right + left) / (left - right);
T ty = (top + bottom) / (bottom - top);
T tz = (zfar + znear) / (zfar - znear);
T tz = (zfar) / (zfar - znear);
T ortho[16] = {
a, 0, 0, 0,
@ -317,14 +327,15 @@ public:
return m;
}
// Optimized form that takes width/height and near/far planes
static matrix4x4 OrthoMatrix(T width, T height, T znear, T zfar)
{
assert((znear >= T(-1)) && (zfar > T(0)));
T a = T(2) / width;
T b = T(2) / height;
T c = T(1) / (zfar - znear) - 1;
T c = T(1) / (zfar - znear);
T tz = (zfar + znear) / (zfar - znear);
T tz = (zfar) / (zfar - znear);
T ortho[16] = {
a, 0, 0, 0,