Fix SDFGI dynamic light culling with Y-scaled cascades #111968
+5
−2
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Resolves #111723
SDFGI dynamic lights are incorrectly culled when positioned at high or low Y coordinates (e.g., Y=±200) with non-100% Y scale settings.
Root Cause
SDFGI stores cascade positions in Y-scaled grid space. When a world position is processed, it's transformed by multiplying Y by
y_mult:When converting back to world space for bounds checking, the inverse transform
* Vector3(1, 1.0 / y_mult, 1)must be applied. This pattern is used correctly throughout the codebase (e.g.,get_pending_region_data()at line ~2101).However,
pre_process_gi()at line ~1931 was missing this inverse transform when constructing thecascade_aabbfor light culling:cascade_aabb.position = Vector3(...) * cascade.cell_size; // Missing: * Vector3(1, 1.0 / y_mult, 1)This caused
cascade_aabb(in Y-scaled grid space) andlight_aabb(in world space) to be compared in different coordinate systems, resulting in incorrect culling.The Fix
Apply the inverse Y-scale transform to convert cascade bounds to world space:
This matches the pattern used in
get_pending_region_data()and ensures both AABBs are in the same coordinate space for intersection testing.Note: This bug was masked when
y_mult=1.0(100% Y-scale), as the inverse transform becomes a no-op.