improve camera precondition checks and default state (#9420)
* improve camera precondition checks and default state - Camera is now initialized with a default projection matrix with left/right, top/bottom set to (-1,1) and near/far set to (0.1,1). - setLensProjection() and setProjection(FOV) now check the near/far precondition (near>0 and far>near). - sanitize user's light near/far to avoid infs and nans during froxelization - finally froxelizer asserts that near>0 and far>near on debug builds. FIXES=[458030186]
This commit is contained in:
@@ -243,10 +243,10 @@ public:
|
||||
/** Utility to set the projection matrix from the field-of-view.
|
||||
*
|
||||
* @param fovInDegrees full field-of-view in degrees. 0 < \p fov < 180.
|
||||
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
* @param direction direction of the \p fovInDegrees parameter.
|
||||
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
* @param direction direction of the \p fovInDegrees parameter.
|
||||
*
|
||||
* @see Fov.
|
||||
*/
|
||||
@@ -256,9 +256,9 @@ public:
|
||||
/** Utility to set the projection matrix from the focal length.
|
||||
*
|
||||
* @param focalLengthInMillimeters lens's focal length in millimeters. \p focalLength > 0.
|
||||
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
*/
|
||||
void setLensProjection(double focalLengthInMillimeters,
|
||||
double aspect, double near, double far);
|
||||
@@ -270,8 +270,8 @@ public:
|
||||
* that is all 3 axis are mapped to [-1, 1].
|
||||
*
|
||||
* @param projection custom projection matrix used for rendering and culling
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
* @param near distance in world units from the camera to the near plane.
|
||||
* @param far distance in world units from the camera to the far plane. \p far != \p near.
|
||||
*/
|
||||
void setCustomProjection(math::mat4 const& projection, double near, double far) noexcept;
|
||||
|
||||
@@ -282,8 +282,8 @@ public:
|
||||
*
|
||||
* @param projection custom projection matrix used for rendering
|
||||
* @param projectionForCulling custom projection matrix used for culling
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
* @param near distance in world units from the camera to the near plane.
|
||||
* @param far distance in world units from the camera to the far plane. \p far != \p near.
|
||||
*/
|
||||
void setCustomProjection(math::mat4 const& projection, math::mat4 const& projectionForCulling,
|
||||
double near, double far) noexcept;
|
||||
|
||||
@@ -16,14 +16,30 @@
|
||||
|
||||
#include "details/Camera.h"
|
||||
|
||||
#include <filament/Camera.h>
|
||||
|
||||
#include <math/mat4.h>
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace filament {
|
||||
|
||||
using namespace math;
|
||||
|
||||
void Camera::setProjection(double const fovInDegrees, double const aspect, double const near, double const far,
|
||||
Fov const direction) {
|
||||
void Camera::setProjection(double const fovInDegrees, double const aspect,
|
||||
double const near, double const far, Fov const direction) {
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(near > 0 && far > near)
|
||||
<< "Camera preconditions not met in setProjection(): near <= 0 or far <= near, near="
|
||||
<< near << ", far=" << far;
|
||||
|
||||
setCustomProjection(
|
||||
projection(direction, fovInDegrees, aspect, near),
|
||||
projection(direction, fovInDegrees, aspect, near, far),
|
||||
@@ -32,6 +48,11 @@ void Camera::setProjection(double const fovInDegrees, double const aspect, doubl
|
||||
|
||||
void Camera::setLensProjection(double const focalLengthInMillimeters,
|
||||
double const aspect, double const near, double const far) {
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(near > 0 && far > near)
|
||||
<< "Camera preconditions not met in setLensProjection(): near <= 0 or far <= near, near="
|
||||
<< near << ", far=" << far;
|
||||
|
||||
setCustomProjection(
|
||||
projection(focalLengthInMillimeters, aspect, near),
|
||||
projection(focalLengthInMillimeters, aspect, near, far),
|
||||
@@ -149,8 +170,9 @@ utils::Entity Camera::getEntity() const noexcept {
|
||||
return downcast(this)->getEntity();
|
||||
}
|
||||
|
||||
void Camera::setExposure(float const aperture, float const shutterSpeed, float const ISO) noexcept {
|
||||
downcast(this)->setExposure(aperture, shutterSpeed, ISO);
|
||||
void Camera::setExposure(
|
||||
float const aperture, float const shutterSpeed, float const sensitivity) noexcept {
|
||||
downcast(this)->setExposure(aperture, shutterSpeed, sensitivity);
|
||||
}
|
||||
|
||||
float Camera::getAperture() const noexcept {
|
||||
@@ -177,7 +199,8 @@ double Camera::getFocalLength() const noexcept {
|
||||
return downcast(this)->getFocalLength();
|
||||
}
|
||||
|
||||
double Camera::computeEffectiveFocalLength(double const focalLength, double const focusDistance) noexcept {
|
||||
double Camera::computeEffectiveFocalLength(
|
||||
double const focalLength, double const focusDistance) noexcept {
|
||||
return FCamera::computeEffectiveFocalLength(focalLength, focusDistance);
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,8 @@ bool Froxelizer::prepare(
|
||||
filament::Viewport const& viewport,
|
||||
const mat4f& projection, float const projectionNear, float const projectionFar,
|
||||
float4 const& clipTransform) noexcept {
|
||||
assert_invariant(projectionFar > projectionNear);
|
||||
assert_invariant(projectionNear > 0);
|
||||
setViewport(viewport);
|
||||
setProjection(projection, projectionNear, projectionFar);
|
||||
|
||||
@@ -383,8 +385,28 @@ bool Froxelizer::update() noexcept {
|
||||
bool uniformsNeedUpdating = false;
|
||||
|
||||
if (UTILS_UNLIKELY(mDirtyFlags & (OPTIONS_CHANGED|PROJECTION_CHANGED))) {
|
||||
float const zLightFar = clamp(mUserZLightFar, mNear, mFar);
|
||||
float zLightNear = clamp(mUserZLightNear, mNear, mFar);
|
||||
|
||||
// sanitize the user's near/far
|
||||
float zLightNear = mUserZLightNear;
|
||||
float zLightFar = mUserZLightFar;
|
||||
if (zLightFar == zLightNear) {
|
||||
zLightNear = mNear;
|
||||
zLightFar = mFar;
|
||||
}
|
||||
if (zLightFar < zLightNear) {
|
||||
std::swap(zLightFar, zLightNear);
|
||||
}
|
||||
if (zLightNear < mNear || zLightNear >= mFar) {
|
||||
zLightNear = mNear;
|
||||
}
|
||||
if (zLightFar > mFar || zLightFar <= mNear) {
|
||||
zLightFar = mFar;
|
||||
}
|
||||
|
||||
assert_invariant(zLightNear < zLightFar);
|
||||
assert_invariant(zLightNear >= mNear && zLightNear <= mFar);
|
||||
assert_invariant(zLightFar <= mFar && zLightNear >= mNear);
|
||||
|
||||
zLightNear = std::min(zLightNear, zLightFar);
|
||||
if (zLightFar != mZLightFar || zLightNear != mZLightNear) {
|
||||
mDirtyFlags |= VIEWPORT_CHANGED;
|
||||
|
||||
@@ -24,27 +24,35 @@
|
||||
#include <filament/Camera.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <math/scalar.h>
|
||||
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
using namespace filament::math;
|
||||
using namespace utils;
|
||||
|
||||
namespace filament {
|
||||
|
||||
static constexpr const float MIN_APERTURE = 0.5f;
|
||||
static constexpr const float MAX_APERTURE = 64.0f;
|
||||
static constexpr const float MIN_SHUTTER_SPEED = 1.0f / 25000.0f;
|
||||
static constexpr const float MAX_SHUTTER_SPEED = 60.0f;
|
||||
static constexpr const float MIN_SENSITIVITY = 10.0f;
|
||||
static constexpr const float MAX_SENSITIVITY = 204800.0f;
|
||||
static constexpr float MIN_APERTURE = 0.5f;
|
||||
static constexpr float MAX_APERTURE = 64.0f;
|
||||
static constexpr float MIN_SHUTTER_SPEED = 1.0f / 25000.0f;
|
||||
static constexpr float MAX_SHUTTER_SPEED = 60.0f;
|
||||
static constexpr float MIN_SENSITIVITY = 10.0f;
|
||||
static constexpr float MAX_SENSITIVITY = 204800.0f;
|
||||
|
||||
FCamera::FCamera(FEngine& engine, Entity const e)
|
||||
: mEngine(engine),
|
||||
mEntity(e) {
|
||||
setProjection(Projection::PERSPECTIVE, -1.0, 1.0, -1.0, 1.0, 0.1, 1.0);
|
||||
}
|
||||
|
||||
mat4 FCamera::projection(Fov const direction, double const fovInDegrees,
|
||||
@@ -84,12 +92,16 @@ mat4 FCamera::projection(double const focalLengthInMillimeters,
|
||||
* All methods for setting the projection funnel through here
|
||||
*/
|
||||
|
||||
void UTILS_NOINLINE FCamera::setCustomProjection(mat4 const& p,
|
||||
mat4 const& c, double const near, double const far) noexcept {
|
||||
void UTILS_NOINLINE FCamera::setCustomProjection(mat4 const& projection,
|
||||
mat4 const& projectionForCulling, double const near, double const far) noexcept {
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(near != far)
|
||||
<< "Camera preconditions not met in setCustomProjection(): near = far = " << near;
|
||||
|
||||
for (auto& eyeProjection: mEyeProjection) {
|
||||
eyeProjection = p;
|
||||
eyeProjection = projection;
|
||||
}
|
||||
mProjectionForCulling = c;
|
||||
mProjectionForCulling = projectionForCulling;
|
||||
mNear = near;
|
||||
mFar = far;
|
||||
}
|
||||
@@ -97,10 +109,15 @@ void UTILS_NOINLINE FCamera::setCustomProjection(mat4 const& p,
|
||||
void UTILS_NOINLINE FCamera::setCustomEyeProjection(mat4 const* projection, size_t const count,
|
||||
mat4 const& projectionForCulling, double const near, double const far) {
|
||||
const Engine::Config& config = mEngine.getConfig();
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(near != far)
|
||||
<< "Camera preconditions not met in setCustomEyeProjection(): near = far = " << near;
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(count >= config.stereoscopicEyeCount)
|
||||
<< "All eye projections must be supplied together, count must be >= "
|
||||
"config.stereoscopicEyeCount ("
|
||||
<< config.stereoscopicEyeCount << ")";
|
||||
|
||||
for (int i = 0; i < config.stereoscopicEyeCount; i++) {
|
||||
mEyeProjection[i] = projection[i];
|
||||
}
|
||||
@@ -290,10 +307,10 @@ CameraInfo::CameraInfo(FCamera const& camera,
|
||||
model = mat4f{ modelMatrix };
|
||||
view = mat4f{ inverse(modelMatrix) };
|
||||
worldTransform = inWorldTransform;
|
||||
zn = (float)camera.getNear();
|
||||
zf = (float)camera.getCullingFar();
|
||||
zn = float(camera.getNear());
|
||||
zf = float(camera.getCullingFar());
|
||||
ev100 = Exposure::ev100(camera);
|
||||
f = (float)camera.getFocalLength();
|
||||
f = float(camera.getFocalLength());
|
||||
A = f / camera.getAperture();
|
||||
d = std::max(zn, camera.getFocusDistance());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user