diff --git a/glm/ext/matrix_clip_space.inl b/glm/ext/matrix_clip_space.inl index bb3a05d7..27fb6a13 100644 --- a/glm/ext/matrix_clip_space.inl +++ b/glm/ext/matrix_clip_space.inl @@ -483,7 +483,7 @@ namespace glm } template - GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveRH(T fovy, T aspect, T zNear) + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveRH_NO(T fovy, T aspect, T zNear) { T const range = tan(fovy / static_cast(2)) * zNear; T const left = -range * aspect; @@ -499,6 +499,24 @@ namespace glm Result[3][2] = - static_cast(2) * zNear; return Result; } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveRH_ZO(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = - static_cast(1); + Result[2][3] = - static_cast(1); + Result[3][2] = - zNear; + return Result; + } template GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveLH_NO(T fovy, T aspect, T zNear) @@ -543,8 +561,10 @@ namespace glm return infinitePerspectiveLH_ZO(fovy, aspect, zNear); # elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO return infinitePerspectiveLH_NO(fovy, aspect, zNear); -# else - return infinitePerspectiveRH(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return infinitePerspectiveRH_ZO(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return infinitePerspectiveRH_NO(fovy, aspect, zNear); # endif } diff --git a/test/gtc/gtc_matrix_transform.cpp b/test/gtc/gtc_matrix_transform.cpp index 88db9d91..3d8170fb 100644 --- a/test/gtc/gtc_matrix_transform.cpp +++ b/test/gtc/gtc_matrix_transform.cpp @@ -32,6 +32,26 @@ int test_perspective() Error += glm::notEqual(N.z, -1.f, Eps); Error += glm::notEqual(F.z, 1.f, Eps); } + + Projection = glm::perspectiveRH_ZO(glm::pi() * 0.25f, 4.0f / 3.0f, Near, Far); + { + glm::vec4 N = Projection * glm::vec4{0.f, 0.f, -Near, 1.f}; + glm::vec4 F = Projection * glm::vec4{0.f, 0.f, -Far, 1.f}; + N /= N.w; + F /= F.w; + Error += glm::notEqual(N.z, 0.f, Eps); + Error += glm::notEqual(F.z, 1.f, Eps); + } + + Projection = glm::perspectiveRH_NO(glm::pi() * 0.25f, 4.0f / 3.0f, Near, Far); + { + glm::vec4 N = Projection * glm::vec4{0.f, 0.f, -Near, 1.f}; + glm::vec4 F = Projection * glm::vec4{0.f, 0.f, -Far, 1.f}; + N /= N.w; + F /= F.w; + Error += glm::notEqual(N.z, -1.f, Eps); + Error += glm::notEqual(F.z, 1.f, Eps); + } return Error; } @@ -66,6 +86,26 @@ int test_infinitePerspective() Error += glm::notEqual(F.z, 1.f, Eps); } + Projection = glm::infinitePerspectiveRH_ZO(glm::pi() * 0.25f, 4.0f / 3.0f, Near); + { + glm::vec4 N = Projection * glm::vec4{0.f, 0.f, -Near, 1.f}; + glm::vec4 F = Projection * glm::vec4{0.f, 0.f, -Inf, 1.f}; + N /= N.w; + F /= F.w; + Error += glm::notEqual(N.z, 0.f, Eps); + Error += glm::notEqual(F.z, 1.f, Eps); + } + + Projection = glm::infinitePerspectiveRH_NO(glm::pi() * 0.25f, 4.0f / 3.0f, Near); + { + glm::vec4 N = Projection * glm::vec4{0.f, 0.f, -Near, 1.f}; + glm::vec4 F = Projection * glm::vec4{0.f, 0.f, -Inf, 1.f}; + N /= N.w; + F /= F.w; + Error += glm::notEqual(N.z, -1.f, Eps); + Error += glm::notEqual(F.z, 1.f, Eps); + } + return Error; }