Allow negative Near values in Camera3D when using orthogonal projection

Negative Near values are valid when using orthogonal projection.
When using perspective or frustum projection, the Near value is now
clamped to 0.01 to prevent rendering from breaking.

This also improves the documentation for the Camera3D `near` and `far`
properties.
This commit is contained in:
Hugo Locurcio 2021-11-10 20:51:13 +01:00
parent a6412e132a
commit ae081c520b
No known key found for this signature in database
GPG key ID: 39E8F8BE30B0A49C
3 changed files with 19 additions and 3 deletions

View file

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

View file

@ -166,7 +166,7 @@
The [Environment] to use for this camera.
</member>
<member name="far" type="float" setter="set_far" getter="get_far" default="4000.0">
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.
</member>
<member name="fov" type="float" setter="set_fov" getter="get_fov" default="75.0">
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].
</member>
<member name="near" type="float" setter="set_near" getter="get_near" default="0.05">
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.
</member>
<member name="projection" type="int" setter="set_projection" getter="get_projection" enum="Camera3D.Projection" default="0">
The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size.

View file

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