diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 48984c4d5b..129244274a 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -84,6 +84,9 @@ void CameraMatrix::adjust_perspective_znear(real_t p_new_znear) { } void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) { + // Zero or negative Z near values are only valid in orthogonal projection. + p_z_near = MAX(0.01, p_z_near); + if (p_flip_fov) { p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect); } @@ -110,6 +113,9 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_ } void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) { + // Zero or negative Z near values are only valid in orthogonal projection. + p_z_near = MAX(0.01, p_z_near); + if (p_flip_fov) { p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect); } @@ -148,6 +154,9 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_ } void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) { + // Zero or negative Z near values are only valid in orthogonal projection. + p_z_near = MAX(0.01, p_z_near); + // we first calculate our base frustum on our values without taking our lens magnification into account. real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens; real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens; @@ -196,6 +205,9 @@ void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear } void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) { + // Zero or negative Z near values are only valid in orthogonal projection. + p_near = MAX(0.01, p_near); + ERR_FAIL_COND(p_right <= p_left); ERR_FAIL_COND(p_top <= p_bottom); ERR_FAIL_COND(p_far <= p_near); @@ -228,6 +240,9 @@ void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, r } void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) { + // Zero or negative Z near values are only valid in orthogonal projection. + p_near = MAX(0.01, p_near); + if (!p_flip_fov) { p_size *= p_aspect; } diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index 06e2f83f05..dbc4f405fb 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -166,7 +166,7 @@ The [Environment] to use for this camera. - The distance to the far culling boundary for this camera relative to its local Z axis. + The distance to the far culling boundary for this camera relative to its local Z axis. Higher values make it possible to see further away, but will reduce performance in large scenes since fewer distant objects will be culled by the clipping plane. To fade objects smoothly in the distance instead of having them cut off suddenly, consider using [Environment] fog. The camera's field of view angle (in degrees). Only applicable in perspective mode. Since [member keep_aspect] locks one axis, [code]fov[/code] sets the other axis' field of view angle. @@ -186,7 +186,8 @@ The axis to lock during [member fov]/[member size] adjustments. Can be either [constant KEEP_WIDTH] or [constant KEEP_HEIGHT]. - The distance to the near culling boundary for this camera relative to its local Z axis. + The distance to the near culling boundary for this camera relative to its local Z axis. Lower values prevent nearby objects from appearing cut off by the clipping plane, but will reduce the depth buffer precision available. This can result in distant objects appearing to flicker when the camera moves due to Z-fighting. + [b]Note:[/b] Negative [member near] values are only valid when the camera's projection is [constant PROJECTION_ORTHOGONAL]. When using [constant PROJECTION_PERSPECTIVE] or [constant PROJECTION_FRUSTUM], the [member near] value is clamped to a value of [code]0.01[/code] or greater. The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size. diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index cc5b7078e3..43983e62cd 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -513,7 +513,7 @@ void Camera3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1,degrees"), "set_fov", "get_fov"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp"), "set_near", "get_near"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_RANGE, "-4000,10,0.001,or_lesser,or_greater,exp"), "set_near", "get_near"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp"), "set_far", "get_far"); BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE);