From 36714690464e2c03d566ca55efd618bc50750dc4 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 9 Aug 2021 15:55:27 -0700 Subject: [PATCH] compute projection inverse in double precision also concatenate transforms used for rendering using double precision intermediates. --- filament/src/Camera.cpp | 13 +++---------- filament/src/View.cpp | 21 ++++++++++----------- filament/src/details/Camera.h | 1 - libs/math/include/math/mat4.h | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/filament/src/Camera.cpp b/filament/src/Camera.cpp index 33648bb190..fef2f61505 100644 --- a/filament/src/Camera.cpp +++ b/filament/src/Camera.cpp @@ -213,7 +213,7 @@ mat4 FCamera::getModelMatrix() const noexcept { } mat4 UTILS_NOINLINE FCamera::getViewMatrix() const noexcept { - return FCamera::getViewMatrix(getModelMatrix()); + return inverse(getModelMatrix()); } Frustum FCamera::getFrustum() const noexcept { @@ -281,13 +281,6 @@ math::details::TMat44 inverseProjection(const math::details::TMat44& p) no return r; } -UTILS_NOINLINE -mat4 FCamera::getViewMatrix(mat4 const& model) noexcept { - // We can't use rigidTransformInverse here. The camera's model matrix might have scaling, which - // would make it non-rigid. - return inverse(model); -} - Frustum FCamera::getFrustum(mat4 const& projection, mat4 const& viewMatrix) noexcept { return Frustum(mat4f{ projection * viewMatrix }); } @@ -298,7 +291,7 @@ CameraInfo::CameraInfo(FCamera const& camera) noexcept { projection = mat4f{ camera.getProjectionMatrix() }; cullingProjection = mat4f{ camera.getCullingProjectionMatrix() }; model = mat4f{ camera.getModelMatrix() }; - view = mat4f{camera.getViewMatrix() }; + view = mat4f{ camera.getViewMatrix() }; zn = camera.getNear(); zf = camera.getCullingFar(); ev100 = Exposure::ev100(camera); @@ -312,7 +305,7 @@ CameraInfo::CameraInfo(FCamera const& camera, const math::mat4& worldOriginCamer projection = mat4f{ camera.getProjectionMatrix() }; cullingProjection = mat4f{ camera.getCullingProjectionMatrix() }; model = mat4f{ modelMatrix }; - view = mat4f{ FCamera::getViewMatrix(modelMatrix) }; + view = mat4f{ inverse(modelMatrix) }; zn = camera.getNear(); zf = camera.getCullingFar(); ev100 = Exposure::ev100(camera); diff --git a/filament/src/View.cpp b/filament/src/View.cpp index 18d710f3d0..074efd0652 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -423,7 +423,7 @@ void FView::prepare(FEngine& engine, backend::DriverApi& driver, ArenaScope& are mCullingFrustum = FCamera::getFrustum( mCullingCamera->getCullingProjectionMatrix(), - FCamera::getViewMatrix(worldOriginScene * mCullingCamera->getModelMatrix())); + inverse(worldOriginScene * mCullingCamera->getModelMatrix())); /* * Gather all information needed to render this scene. Apply the world origin to all @@ -639,23 +639,22 @@ UTILS_NOINLINE void FView::prepareCamera(const CameraInfo& camera) const noexcept { SYSTRACE_CALL(); - const mat4f viewFromWorld(camera.view); - const mat4f worldFromView(camera.model); - const mat4f projectionMatrix(camera.projection); + mat4f const& viewFromWorld = camera.view; + mat4f const& worldFromView = camera.model; + mat4f const& clipFromView = camera.projection; - const mat4f clipFromView(projectionMatrix); - const mat4f viewFromClip(inverse(clipFromView)); - const mat4f clipFromWorld(clipFromView * viewFromWorld); - const mat4f worldFromClip(worldFromView * viewFromClip); + const mat4f viewFromClip{ inverse((mat4)camera.projection) }; + const mat4f clipFromWorld{ highPrecisionMultiply(clipFromView, viewFromWorld) }; + const mat4f worldFromClip{ highPrecisionMultiply(worldFromView, viewFromClip) }; auto& s = mPerViewUb.edit(); s.viewFromWorldMatrix = viewFromWorld; // view s.worldFromViewMatrix = worldFromView; // model - s.clipFromViewMatrix = clipFromView; // projection - s.viewFromClipMatrix = viewFromClip; // 1/projection + s.clipFromViewMatrix = clipFromView; // projection + s.viewFromClipMatrix = viewFromClip; // 1/projection s.clipFromWorldMatrix = clipFromWorld; // projection * view s.worldFromClipMatrix = worldFromClip; // 1/(projection * view) - s.cameraPosition = float3{camera.getPosition()}; + s.cameraPosition = float3{ camera.getPosition() }; s.worldOffset = camera.worldOffset; s.cameraFar = camera.zf; s.clipControl = mClipControl; diff --git a/filament/src/details/Camera.h b/filament/src/details/Camera.h index 500f18b255..d17bc83ca1 100644 --- a/filament/src/details/Camera.h +++ b/filament/src/details/Camera.h @@ -183,7 +183,6 @@ public: return mEntity; } - static math::mat4 getViewMatrix(math::mat4 const& model) noexcept; static Frustum getFrustum(math::mat4 const& projection, math::mat4 const& viewMatrix) noexcept; private: diff --git a/libs/math/include/math/mat4.h b/libs/math/include/math/mat4.h index d3c52da992..0740370c29 100644 --- a/libs/math/include/math/mat4.h +++ b/libs/math/include/math/mat4.h @@ -557,6 +557,26 @@ constexpr typename TMat44::col_type MATH_PURE operator*(const TMat44& lhs, typedef details::TMat44 mat4; typedef details::TMat44 mat4f; +// mat4 * float4, with double precision intermediates +constexpr float4 highPrecisionMultiply(mat4f const& lhs, float4 const& rhs) noexcept { + double4 result{}; + result += lhs[0] * rhs[0]; + result += lhs[1] * rhs[1]; + result += lhs[2] * rhs[2]; + result += lhs[3] * rhs[3]; + return float4{ result }; +} + +// mat4 * mat4, with double precision intermediates +constexpr mat4f highPrecisionMultiply(mat4f const& lhs, mat4f const& rhs) noexcept { + return { + highPrecisionMultiply(lhs, rhs[0]), + highPrecisionMultiply(lhs, rhs[1]), + highPrecisionMultiply(lhs, rhs[2]), + highPrecisionMultiply(lhs, rhs[3]) + }; +} + // ---------------------------------------------------------------------------------------- } // namespace math } // namespace filament