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

Prevent very far away point lights from being culled #98641

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion servers/rendering/renderer_rd/cluster_builder_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ class ClusterBuilderRD {
} else {
// Contains camera inside light.
float radius2 = radius * shared->sphere_overfit; // Overfit again for outer size (camera may be outside actual sphere but behind an icosphere vertex)
e.touches_near = xform.origin.length_squared() < radius2 * radius2;
real_t sum_abs_origin = 1.0 + abs(xform.origin.x) + abs(xform.origin.y) + abs(xform.origin.z); // Used to avoid overflows with length() when xform.origin components exceed sqrt(MAX_REAL_T_VALUE)
e.touches_near = (xform.origin / sum_abs_origin).length() * sum_abs_origin < radius2;
}

e.touches_far = (depth + radius) > z_far;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ float henyey_greenstein(float cos_theta, float g) {
return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
}

// Used to avoid overflows with length() when point components exceed sqrt(MAX_REAL_T_VALUE)
float length_safe(vec3 point) {
float L1_norm_p1 = 1.0 + abs(point.x) + abs(point.y) + abs(point.z);
return length(point / L1_norm_p1) * L1_norm_p1;
}

#define TEMPORAL_FRAMES 16

const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
Expand Down Expand Up @@ -570,15 +576,15 @@ void main() {

vec3 light_pos = spot_lights.data[light_index].position;
vec3 light_rel_vec = spot_lights.data[light_index].position - view_pos;
float d = length(light_rel_vec);
float d = length_safe(light_rel_vec);
float shadow_attenuation = 1.0;

if (spot_lights.data[light_index].volumetric_fog_energy > 0.001 && d * spot_lights.data[light_index].inv_radius < 1.0) {
float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);

vec3 spot_dir = spot_lights.data[light_index].direction;
highp float cone_angle = spot_lights.data[light_index].cone_angle;
float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
float scos = max(dot(-light_rel_vec / d, spot_dir), cone_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation);

Expand All @@ -600,7 +606,7 @@ void main() {

shadow_attenuation = mix(1.0 - spot_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (pos.z - depth)) / spot_lights.data[light_index].inv_radius * INV_FOG_FADE));
}
total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g) * spot_lights.data[light_index].volumetric_fog_energy;
total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(light_rel_vec / d, normalize(view_pos)), params.phase_g) * spot_lights.data[light_index].volumetric_fog_energy;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,12 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
return nd * pow(max(distance, 0.0001), -decay);
}

// Used to avoid overflows with length() when point components exceed sqrt(MAX_REAL_T_VALUE)
float length_safe(vec3 point) {
float L1_norm_p1 = 1.0 + abs(point.x) + abs(point.y) + abs(point.z);
return length(point / L1_norm_p1) * L1_norm_p1;
}

void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
Expand All @@ -409,7 +415,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v

// Omni light attenuation.
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
float light_length = length_safe(light_rel_vec);
float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);

// Compute size.
Expand Down Expand Up @@ -704,7 +710,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v

// Spot light attenuation.
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
float light_length = length_safe(light_rel_vec);
vec3 light_rel_vec_norm = light_rel_vec / light_length;
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
vec3 spot_dir = spot_lights.data[idx].direction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,20 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
return nd * pow(max(distance, 0.0001), -decay);
}

// Used to avoid overflows with length() when point components exceed sqrt(MAX_REAL_T_VALUE)
float length_safe(vec3 point) {
float L1_norm_p1 = 1.0 + abs(point.x) + abs(point.y) + abs(point.z);
return length(point / L1_norm_p1) * L1_norm_p1;
}

void light_process_omni_vertex(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness,
inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
float light_length = length_safe(light_rel_vec);
float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
vec3 color = omni_lights.data[idx].color * omni_attenuation;

light_compute_vertex(normal, normalize(light_rel_vec), eye_vec, color, false, roughness,
light_compute_vertex(normal, light_rel_vec / light_length, eye_vec, color, false, roughness,
diffuse_light,
specular_light);
}
Expand All @@ -63,20 +69,20 @@ void light_process_spot_vertex(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal,
inout vec3 diffuse_light,
inout vec3 specular_light) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
float light_length = length_safe(light_rel_vec);
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
vec3 spot_dir = spot_lights.data[idx].direction;

// This conversion to a highp float is crucial to prevent light leaking
// due to precision errors in the following calculations (cone angle is mediump).
highp float cone_angle = spot_lights.data[idx].cone_angle;
float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
float scos = max(dot(-light_rel_vec / light_length, spot_dir), cone_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));

spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
vec3 color = spot_lights.data[idx].color * spot_attenuation;
float specular_amount = spot_lights.data[idx].specular_amount;

light_compute_vertex(normal, normalize(light_rel_vec), eye_vec, color, false, roughness,
light_compute_vertex(normal, light_rel_vec / light_length, eye_vec, color, false, roughness,
diffuse_light, specular_light);
}
Loading