compute projection inverse in double precision

also concatenate transforms used for rendering using double precision
intermediates.
This commit is contained in:
Mathias Agopian
2021-08-09 15:55:27 -07:00
committed by Mathias Agopian
parent 53d4fa3095
commit 3671469046
4 changed files with 33 additions and 22 deletions

View File

@@ -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<T> inverseProjection(const math::details::TMat44<T>& 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);

View File

@@ -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;

View File

@@ -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:

View File

@@ -557,6 +557,26 @@ constexpr typename TMat44<T>::col_type MATH_PURE operator*(const TMat44<T>& lhs,
typedef details::TMat44<double> mat4;
typedef details::TMat44<float> 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