diff --git a/filament/include/filament/Camera.h b/filament/include/filament/Camera.h index 10fe041b7c..abf8b2c16b 100644 --- a/filament/include/filament/Camera.h +++ b/filament/include/filament/Camera.h @@ -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; diff --git a/filament/src/Camera.cpp b/filament/src/Camera.cpp index 7ae393ebc7..863bd03af4 100644 --- a/filament/src/Camera.cpp +++ b/filament/src/Camera.cpp @@ -16,14 +16,30 @@ #include "details/Camera.h" +#include + #include +#include + +#include +#include +#include + +#include +#include + 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); } diff --git a/filament/src/Froxelizer.cpp b/filament/src/Froxelizer.cpp index 1a3724cf19..3a33adf35e 100644 --- a/filament/src/Froxelizer.cpp +++ b/filament/src/Froxelizer.cpp @@ -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; diff --git a/filament/src/details/Camera.cpp b/filament/src/details/Camera.cpp index 775e3f175e..d006e22d4c 100644 --- a/filament/src/details/Camera.cpp +++ b/filament/src/details/Camera.cpp @@ -24,27 +24,35 @@ #include #include +#include #include #include - +#include #include +#include + +#include +#include +#include +#include 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()); }