Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for infinite projection matrix #95944

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/math/math_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,10 @@ enum class EulerOrder {
*/
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
#define MAX_REAL_T 1.7976931348623157e+308
#else
typedef float real_t;
#define MAX_REAL_T 3.40282347e+38F
#endif

#endif // MATH_DEFS_H
31 changes: 26 additions & 5 deletions core/math/projection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,14 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
matrix[11] - matrix[10],
matrix[15] - matrix[14]);

new_plane.normal = -new_plane.normal;
new_plane.normalize();
if (new_plane.normal[0] == 0 && new_plane.normal[1] == 0 && new_plane.normal[2] == 0) {
new_plane.normal = Vector3(0, 0, -1);
new_plane.d = MAX_REAL_T;
} else {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
}

return new_plane;
}
case PLANE_LEFT: {
Expand Down Expand Up @@ -408,6 +414,10 @@ real_t Projection::get_z_far() const {
matrix[11] - matrix[10],
matrix[15] - matrix[14]);

if (new_plane.normal[0] == 0 && new_plane.normal[1] == 0 && new_plane.normal[2] == 0) {
return MAX_REAL_T;
}

new_plane.normalize();

return new_plane.d;
Expand Down Expand Up @@ -459,7 +469,13 @@ Vector2 Projection::get_far_plane_half_extents() const {
matrix[7] - matrix[6],
matrix[11] - matrix[10],
-matrix[15] + matrix[14]);
far_plane.normalize();

if (far_plane.normal[0] == 0 && far_plane.normal[1] == 0 && far_plane.normal[2] == 0) {
far_plane.normal = Vector3(0, 0, 1);
far_plane.d = -MAX_REAL_T;
} else {
far_plane.normalize();
}

///////--- Right Plane ---///////
Plane right_plane = Plane(matrix[3] - matrix[0],
Expand Down Expand Up @@ -537,8 +553,13 @@ Vector<Plane> Projection::get_projection_planes(const Transform3D &p_transform)
matrix[11] - matrix[10],
matrix[15] - matrix[14]);

new_plane.normal = -new_plane.normal;
new_plane.normalize();
if (new_plane.normal[0] == 0 && new_plane.normal[1] == 0 && new_plane.normal[2] == 0) {
new_plane.normal = Vector3(0, 0, -1);
new_plane.d = MAX_REAL_T;
} else {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
}

planes.write[1] = p_transform.xform(new_plane);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,8 @@ void vertex_shader(vec3 vertex_input,
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges

vec3 vtx = vertex_interp;
float distance = length(vtx);
vtx = normalize(vtx);
float distance = length(vtx / abs(vertex_interp.z)) * abs(vertex_interp.z); // Dividing before taking length() prevents overflow when values exceed sqrt(MAX_FLOAT)
vtx /= distance;
vtx.xy /= 1.0 - vtx.z;
vtx.z = (distance / scene_data.z_far);
vtx.z = vtx.z * 2.0 - 1.0;
Expand Down Expand Up @@ -515,10 +515,10 @@ void vertex_shader(vec3 vertex_input,
specular_light_interp = vec4(0.0);

#ifdef USE_MULTIVIEW
vec3 view = -normalize(vertex_interp - eye_offset);
vec3 view = -normalize((vertex_interp - eye_offset) / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
vec2 clip_pos = clamp((combined_projected.xy / combined_projected.w) * 0.5 + 0.5, 0.0, 1.0);
#else
vec3 view = -normalize(vertex_interp);
vec3 view = -normalize(vertex_interp / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
vec2 clip_pos = clamp((gl_Position.xy / gl_Position.w) * 0.5 + 0.5, 0.0, 1.0);
#endif

Expand Down Expand Up @@ -1047,7 +1047,7 @@ vec4 fog_process(vec3 vertex) {
if (scene_data_block.data.fog_sun_scatter > 0.001) {
vec4 sun_scatter = vec4(0.0);
float sun_total = 0.0;
vec3 view = normalize(vertex);
vec3 view = normalize(vertex / abs(vertex.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)

for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) {
vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
Expand Down Expand Up @@ -1128,14 +1128,14 @@ void fragment_shader(in SceneData scene_data) {
vec3 vertex = vertex_interp;
#ifdef USE_MULTIVIEW
vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
vec3 view = -normalize(vertex_interp - eye_offset);
vec3 view = -normalize((vertex_interp - eye_offset) / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)

// UV in our combined frustum space is used for certain screen uv processes where it's
// overkill to render separate left and right eye views
vec2 combined_uv = (combined_projected.xy / combined_projected.w) * 0.5 + 0.5;
#else
vec3 eye_offset = vec3(0.0, 0.0, 0.0);
vec3 view = -normalize(vertex_interp);
vec3 view = -normalize(vertex_interp / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#endif
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
Expand Down Expand Up @@ -1257,9 +1257,9 @@ void fragment_shader(in SceneData scene_data) {
#ifdef LIGHT_VERTEX_USED
vertex = light_vertex;
#ifdef USE_MULTIVIEW
view = -normalize(vertex - eye_offset);
view = -normalize((vertex - eye_offset) / abs(vertex.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#else
view = -normalize(vertex);
view = -normalize(vertex / abs(vertex.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#endif //USE_MULTIVIEW
#endif //LIGHT_VERTEX_USED

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,9 +453,9 @@ void main() {
// VERTEX LIGHTING
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING)
#ifdef USE_MULTIVIEW
vec3 view = -normalize(vertex_interp - eye_offset);
vec3 view = -normalize((vertex_interp - eye_offset) / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#else
vec3 view = -normalize(vertex_interp);
vec3 view = -normalize(vertex_interp / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#endif

diffuse_light_interp = vec4(0.0);
Expand Down Expand Up @@ -562,8 +562,8 @@ void main() {
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges

vec3 vtx = vertex_interp;
float distance = length(vtx);
vtx = normalize(vtx);
float distance = length(vtx / abs(vertex_interp.z)) * abs(vertex_interp.z); // Dividing before taking length() prevents overflow when values exceed sqrt(MAX_FLOAT)
vtx /= distance;
vtx.xy /= 1.0 - vtx.z;
vtx.z = (distance / scene_data.z_far);
vtx.z = vtx.z * 2.0 - 1.0;
Expand Down Expand Up @@ -821,7 +821,7 @@ vec4 fog_process(vec3 vertex) {
if (scene_data_block.data.fog_sun_scatter > 0.001) {
vec4 sun_scatter = vec4(0.0);
float sun_total = 0.0;
vec3 view = normalize(vertex);
vec3 view = normalize(vertex / abs(vertex.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)

for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) {
vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
Expand Down Expand Up @@ -876,10 +876,10 @@ void main() {
vec3 vertex = vertex_interp;
#ifdef USE_MULTIVIEW
vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
vec3 view = -normalize(vertex_interp - eye_offset);
vec3 view = -normalize((vertex_interp - eye_offset) / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#else
vec3 eye_offset = vec3(0.0, 0.0, 0.0);
vec3 view = -normalize(vertex_interp);
vec3 view = -normalize(vertex_interp / abs(vertex_interp.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#endif
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
Expand Down Expand Up @@ -1001,9 +1001,9 @@ void main() {
#ifdef LIGHT_VERTEX_USED
vertex = light_vertex;
#ifdef USE_MULTIVIEW
view = -normalize(vertex - eye_offset);
view = -normalize((vertex - eye_offset) / abs(vertex.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#else
view = -normalize(vertex);
view = -normalize(vertex / abs(vertex.z)); // Dividing before normalizing prevents overflow when values exceed sqrt(MAX_FLOAT)
#endif //USE_MULTIVIEW
#endif //LIGHT_VERTEX_USED

Expand Down
Loading