Merge pull request #89714 from lawnjelly/tighter_light_cull_colinear_fix

Tighter shadow culling - fix light colinear to frustum edge
This commit is contained in:
Rémi Verschelde 2024-04-05 12:15:53 +02:00
commit b5064a6160
No known key found for this signature in database
GPG key ID: C3336907360768E1
2 changed files with 45 additions and 6 deletions

View file

@ -427,15 +427,19 @@ bool RenderingLightCuller::_add_light_camera_planes(LightCullPlanes &r_cull_plan
uint8_t *entry = &data.LUT_entries[lookup][0];
int n_edges = data.LUT_entry_sizes[lookup] - 1;
const Vector3 &pt2 = p_light_source.pos;
for (int e = 0; e < n_edges; e++) {
int i0 = entry[e];
int i1 = entry[e + 1];
const Vector3 &pt0 = data.frustum_points[i0];
const Vector3 &pt1 = data.frustum_points[i1];
// Create plane from 3 points.
Plane p(pt0, pt1, p_light_source.pos);
r_cull_planes.add_cull_plane(p);
if (!_is_colinear_tri(pt0, pt1, pt2)) {
// Create plane from 3 points.
Plane p(pt0, pt1, pt2);
r_cull_planes.add_cull_plane(p);
}
}
// Last to 0 edge.
@ -446,9 +450,11 @@ bool RenderingLightCuller::_add_light_camera_planes(LightCullPlanes &r_cull_plan
const Vector3 &pt0 = data.frustum_points[i0];
const Vector3 &pt1 = data.frustum_points[i1];
// Create plane from 3 points.
Plane p(pt0, pt1, p_light_source.pos);
r_cull_planes.add_cull_plane(p);
if (!_is_colinear_tri(pt0, pt1, pt2)) {
// Create plane from 3 points.
Plane p(pt0, pt1, pt2);
r_cull_planes.add_cull_plane(p);
}
}
#ifdef LIGHT_CULLER_DEBUG_LOGGING

View file

@ -163,6 +163,39 @@ private:
bool _prepare_light(const RendererSceneCull::Instance &p_instance, int32_t p_directional_light_id = -1);
// Avoid adding extra culling planes derived from near colinear triangles.
// The normals derived from these will be inaccurate, and can lead to false
// culling of objects that should be within the light volume.
bool _is_colinear_tri(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c) const {
// Lengths of sides a, b and c.
float la = (p_b - p_a).length();
float lb = (p_c - p_b).length();
float lc = (p_c - p_a).length();
// Get longest side into lc.
if (lb < la) {
SWAP(la, lb);
}
if (lc < lb) {
SWAP(lb, lc);
}
// Prevent divide by zero.
if (lc > 0.00001f) {
// If the summed length of the smaller two
// sides is close to the length of the longest side,
// the points are colinear, and the triangle is near degenerate.
float ld = ((la + lb) - lc) / lc;
// ld will be close to zero for colinear tris.
return ld < 0.00001f;
}
// Don't create planes from tiny triangles,
// they won't be accurate.
return true;
}
// Internal version uses LightSource.
bool _add_light_camera_planes(LightCullPlanes &r_cull_planes, const LightSource &p_light_source);