Skip to content

Commit

Permalink
MathLib: fixed GetNearFarClipPlanes for orthographic matrices
Browse files Browse the repository at this point in the history
Also, enable SetNearFarClipPlanes for both perspective and
orthographics projections
  • Loading branch information
TheMostDiligent committed Dec 19, 2024
1 parent d3c9457 commit 96917d5
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 42 deletions.
96 changes: 62 additions & 34 deletions Common/interface/BasicMath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1716,46 +1716,74 @@ template <class T> struct Matrix4x4
// See https://github.com/DiligentGraphics/DiligentCore/blob/master/doc/CoordinateSystem.md
void SetNearFarClipPlanes(T zNear, T zFar, bool NegativeOneToOneZ)
{
if (NegativeOneToOneZ)
if (_44 == 0)
{
// https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
// http://www.terathon.com/gdc07_lengyel.pdf
// Note that OpenGL uses right-handed coordinate system, where
// camera is looking in negative z direction:
// OO
// |__|<--------------------
// -z +z
// Consequently, OpenGL projection matrix given by these two
// references inverts z axis.

// We do not need to do this, because we use DX coordinate
// system for the camera space. Thus we need to invert the
// sign of the values in the third column in the matrix
// from the references:

_33 = -(-(zFar + zNear) / (zFar - zNear));
_43 = -2 * zNear * zFar / (zFar - zNear);
_34 = -(-1);
// Perspective projection
if (NegativeOneToOneZ)
{
// https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
// http://www.terathon.com/gdc07_lengyel.pdf
// Note that OpenGL uses right-handed coordinate system, where
// camera is looking in negative z direction:
// OO
// |__|<--------------------
// -z +z
// Consequently, OpenGL projection matrix given by these two
// references inverts z axis.

// We do not need to do this, because we use DX coordinate
// system for the camera space. Thus we need to invert the
// sign of the values in the third column in the matrix
// from the references:

_33 = -(-(zFar + zNear) / (zFar - zNear));
_43 = -2 * zNear * zFar / (zFar - zNear);
_34 = -(-1);
}
else
{
_33 = zFar / (zFar - zNear);
_43 = -zNear * zFar / (zFar - zNear);
_34 = 1;
}
}
else
{
_33 = zFar / (zFar - zNear);
_43 = -zNear * zFar / (zFar - zNear);
_34 = 1;
// Orthographic projection
_33 = (NegativeOneToOneZ ? 2 : 1) / (zFar - zNear);
_43 = (NegativeOneToOneZ ? zNear + zFar : zNear) / (zNear - zFar);
}
}

void GetNearFarClipPlanes(T& zNear, T& zFar, bool NegativeOneToOneZ) const
{
if (NegativeOneToOneZ)
if (_44 == 0)
{
zNear = _43 / (-1 - _33);
zFar = _43 / (+1 - _33);
// Perspective projection
if (NegativeOneToOneZ)
{
zNear = _43 / (-1 - _33);
zFar = _43 / (+1 - _33);
}
else
{
zNear = -_43 / _33;
zFar = _33 / (_33 - 1) * zNear;
}
}
else
{
zNear = -_43 / _33;
zFar = _33 / (_33 - 1) * zNear;
// Orthographic projection
if (NegativeOneToOneZ)
{
zNear = (-1 - _43) / _33;
zFar = (+1 - _43) / _33;
}
else
{
zNear = -_43 / _33;
zFar = (1 - _43) / _33;
}
}
}

Expand All @@ -1774,17 +1802,17 @@ template <class T> struct Matrix4x4

static Matrix4x4 OrthoOffCenter(T left, T right, T bottom, T top, T zNear, T zFar, bool NegativeOneToOneZ) // Left-handed ortho projection
{
auto _22 = (NegativeOneToOneZ ? 2 : 1) / (zFar - zNear);
auto _32 = (NegativeOneToOneZ ? zNear + zFar : zNear) / (zNear - zFar);
// clang-format off
return Matrix4x4
Matrix4x4 Proj
{
2 / (right - left), 0, 0, 0,
0, 2 / (top - bottom), 0, 0,
0, 0, _22, 0,
(left + right)/(left - right), (top + bottom) / (bottom - top), _32, 1
2 / (right - left), 0, 0, 0,
0, 2 / (top - bottom), 0, 0,
0, 0, 0, 0,
(left + right)/(left - right), (top + bottom) / (bottom - top), 0, 1
};
// clang-format on
Proj.SetNearFarClipPlanes(zNear, zFar, NegativeOneToOneZ);
return Proj;
}

static Matrix4x4 Ortho(T width, T height, T zNear, T zFar, bool NegativeOneToOneZ) // Left-handed ortho projection
Expand Down
45 changes: 37 additions & 8 deletions Tests/DiligentCoreTest/src/Common/MathLibTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1074,37 +1074,66 @@ TEST(Common_BasicMath, OrthoProjection)
{
float4x4 OrthoProj = float4x4::Ortho(2.f, 4.f, -4.f, 12.f, false);

auto c0 = float3{-1.f, -2.f, -4.f} * OrthoProj;
auto c1 = float3{+1.f, +2.f, +12.f} * OrthoProj;
float3 c0 = float3{-1.f, -2.f, -4.f} * OrthoProj;
float3 c1 = float3{+1.f, +2.f, +12.f} * OrthoProj;
EXPECT_EQ(c0, float3(-1, -1, 0));
EXPECT_EQ(c1, float3(+1, +1, +1));

float Near = 0, Far = 0;
OrthoProj.GetNearFarClipPlanes(Near, Far, false);
EXPECT_FLOAT_EQ(Near, -4);
EXPECT_FLOAT_EQ(Far, 12);

OrthoProj.SetNearFarClipPlanes(2, 34, false);
OrthoProj.GetNearFarClipPlanes(Near, Far, false);
EXPECT_FLOAT_EQ(Near, 2);
EXPECT_FLOAT_EQ(Far, 34);
}

{
float4x4 OrthoProj = float4x4::Ortho(2.f, 4.f, -4.f, 12.f, true);

auto c0 = float3(-1.f, -2.f, -4.f) * OrthoProj;
auto c1 = float3(+1.f, +2.f, +12.f) * OrthoProj;
float3 c0 = float3(-1.f, -2.f, -4.f) * OrthoProj;
float3 c1 = float3(+1.f, +2.f, +12.f) * OrthoProj;
EXPECT_EQ(c0, float3(-1, -1, -1));
EXPECT_EQ(c1, float3(+1, +1, +1));

float Near = 0, Far = 0;
OrthoProj.GetNearFarClipPlanes(Near, Far, true);
EXPECT_FLOAT_EQ(Near, -4);
EXPECT_FLOAT_EQ(Far, 12);

OrthoProj.SetNearFarClipPlanes(2, 34, true);
OrthoProj.GetNearFarClipPlanes(Near, Far, true);
EXPECT_FLOAT_EQ(Near, 2);
EXPECT_FLOAT_EQ(Far, 34);
}

{
float4x4 OrthoProj = float4x4::OrthoOffCenter(-2.f, 6.f, -4.f, +12.f, -6.f, 10.f, false);

auto c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
auto c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
float3 c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
float3 c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
EXPECT_EQ(c0, float3(-1, -1, 0));
EXPECT_EQ(c1, float3(+1, +1, +1));

float Near = 0, Far = 0;
OrthoProj.GetNearFarClipPlanes(Near, Far, false);
EXPECT_FLOAT_EQ(Near, -6);
EXPECT_FLOAT_EQ(Far, 10);
}

{
float4x4 OrthoProj = float4x4::OrthoOffCenter(-2.f, 6.f, -4.f, +12.f, -6.f, 10.f, true);

auto c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
auto c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
float3 c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
float3 c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
EXPECT_EQ(c0, float3(-1, -1, -1));
EXPECT_EQ(c1, float3(+1, +1, +1));

float Near = 0, Far = 0;
OrthoProj.GetNearFarClipPlanes(Near, Far, true);
EXPECT_FLOAT_EQ(Near, -6);
}
}

Expand Down

0 comments on commit 96917d5

Please sign in to comment.