Skip to content

feat: rewrite cascaded shadow pipeline#907

Merged
github-actions[bot] merged 4 commits into
devfrom
feature/lighting-phase2-shadows
Jul 10, 2026
Merged

feat: rewrite cascaded shadow pipeline#907
github-actions[bot] merged 4 commits into
devfrom
feature/lighting-phase2-shadows

Conversation

@MichaelFisher1997

Copy link
Copy Markdown
Collaborator

Summary

  • replace fixed cascade ratios and camera-origin fitting with practical splits, overlapped frustum slices, stable corner-containing projections, and texel snapping
  • use positive view depth for selection/blending/fade, derive filter margins and world-texel bias per cascade, and expose coherent hard/4/9/16-tap tiers
  • extrude receiver volumes toward the light for caster chunk coverage, remove hidden distance caps, enable shadow MDI by default, and alpha-test cutout casters against the atlas
  • expand and reflect the shadow ABI with overlap, depth-span, and configured fade data; add behavioral CSM/reverse-Z/stability/caster tests

Verification

  • nix develop --command zig build test
  • nix develop --command zig build -Dskip-present
  • nix develop --command zig build run -Dskip-present -Dauto-world=normal -Dstartup-diagnostic-seconds=5
  • pre-push formatting and full test hooks

Known verification limitation

  • nix develop --command zig build test-robustness currently fails to compile in unchanged src/integration_test_robustness.zig:34 because Zig 0.16 renamed the std.process.Child.Term.Exited tag.

Closes #903

@github-actions github-actions Bot added documentation Improvements or additions to documentation engine shaders labels Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

kcov coverage

Line coverage ran for this PR and uploaded a non-blocking report artifact named kcov-report. Codecov upload is configured as non-blocking while the project captures a stable baseline.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

📋 Summary

PR #907 rewrites the cascaded shadow pipeline for ZigCraft. It implements practical logarithmic cascade splits, receiver-volume extrusion for caster bounds, texel-snapped stable projections, atlas-aware alpha-tested cutout shadows, and coherent PCF tiers (hard/4/9/16 taps). It expands the ShadowUniforms ABI and keeps the Vulkan/GLSL layouts consistent. It also enables shadow MDI by default and removes hidden shadow-distance caps.

The PR closes issue #903. Most of #903's scope is addressed (splits, fitting, view-depth usage, stability, overlap, margins, bias, caster extrusion, cutout/entity-ish chunk shadows, PCF tiers, MDI, debug channels). The acceptance item "Include supported entities in the shadow scene" is not visibly implemented for non-chunk entities. The PR notes the unrelated test-robustness compile failure caused by a Zig 0.16 rename.

nix develop --command zig build test and nix develop --command zig build -Dskip-present both pass.

📌 Review Metadata

The PR implements the majority of #903's requested scope and required tests. However, it does not visibly add non-chunk entity rendering to the shadow pass, and some acceptance criteria (visual quality, performance target) require runtime/visual verification that cannot be done from this environment.

🔴 Critical Issues (Must Fix - Blocks Merge)

None identified.

⚠️ High Priority Issues (Should Fix)

None identified.

💡 Medium Priority Issues (Nice to Fix)

[MEDIUM] modules/engine-graphics/src/shadow_tests.zig:198-232 - Outdated fixed-split tests
Confidence: High
Description: The tests "computeCascades uses fixed splits for large shadow distance" and "computeCascades uses fixed splits for small shadow distance" still assert 25/50/75/100% splits, but computeCascades now calls practicalSplit with lambda=0.75, producing logarithmic-biased splits (e.g., ~63/133/263/1000 for far=1000). These assertions are factually incorrect. In addition, this file's tests do not appear to be aggregated by the main src/tests.zig suite, so the PR's new ABI tests here are also unexercised.
Impact: Stale incorrect tests mislead maintainers and reduce effective coverage of the new ABI/CSM code.
Suggested Fix: Remove or rewrite the fixed-split tests to match practicalSplit, and ensure engine-graphics.shadow_tests is actually included in the test aggregator (or move the tests to src/shadow_cascade_tests.zig).

[MEDIUM] modules/engine-graphics/src/csm.zig:35-54 - ShadowCascades.isValid() ignores new fields
Confidence: High
Description: isValid() only checks cascade_splits, texel_sizes, and light-space matrices. It does not validate the new overlap_starts, depth_spans, or receiver_corners fields, even though they are computed per frame and uploaded to the GPU for cascade blending, bias scaling, and caster submission.
Impact: Invalid overlap_starts or depth_spans could cause broken cascade blends, wrong receiver bias, or incorrect fade behavior; NaN/Inf in receiver_corners could lead to missing off-screen casters.
Suggested Fix: Extend isValid() to check overlap_starts and depth_spans are finite and positive, and that receiver_corners are finite.

[MEDIUM] Issue #903 scope gap - supported entities not added to shadow scene
Confidence: Low
Description: #903's scope includes "Include supported entities in the shadow scene." This diff only extends the World/WorldRenderer shadow path; no non-chunk entity rendering is routed to the shadow pass.
Impact: If the project has non-block entities that should cast shadows, this acceptance criterion is not met.
Suggested Fix: If entity shadows are required, route them through IShadowScene or add an entity shadow pass; otherwise, update #903's scope/acceptance criteria to reflect that this PR does not cover them.

ℹ️ Low Priority Suggestions (Optional)

[LOW] assets/shaders/vulkan/terrain.frag:819-825 - Debug seam channel uses old blend heuristic
Confidence: High
Description: The DEBUG_SEAM_DIAG branch uses nextSplit * 0.8 for blendStart, but the actual cascade blend now uses shadows.overlap_starts[layer + 1].
Impact: Debug visualization does not match the real blend region.
Suggested Fix: Replace nextSplit * 0.8 with shadows.overlap_starts[layer + 1].

[LOW] assets/shaders/vulkan/terrain.frag:35 - shadow_params comment is stale
Confidence: High
Description: The comment says z/w reserved, but global.shadow_params.z is used for shadow strength (e.g., line 726).
Suggested Fix: Update the comment to // x = pcf_samples, y = cascade_blend, z = shadow strength, w = simple_lighting_enabled.

[LOW] modules/world-runtime/src/world.zig:999-1003 - Comment refers to used shadow_config
Confidence: High
Description: The doc comment says "valid view-projection and shadow config", but the function body ignores shadow_config.
Suggested Fix: Update the comment to describe the actual behavior (caster bounds from config, config otherwise unused).

[LOW] modules/world-runtime/src/world_renderer.zig:681 - light_space_matrix is unused
Confidence: High
Description: The parameter is assigned to _ because the new caster-bounds submission no longer performs frustum culling.
Suggested Fix: Remove the parameter if the interface can change, or add a comment that it is retained for API compatibility.

[LOW] modules/engine-graphics/src/csm.zig:130 - Docstring lambda default mismatch
Confidence: High
Description: The comment says lambda=0.92 biases the split scheme, but the actual default is 0.75.
Suggested Fix: Update the docstring to match the envFloat("ZIGCRAFT_CSM_SPLIT_LAMBDA", 0.75) default.

📊 SOLID Principles Score

Principle Score Notes
Single Responsibility 8 CSM math, GPU upload, and scene submission are cleanly separated.
Open/Closed 7 New fields extend structs; test aggregation could be more open.
Liskov Substitution 8 IShadowScene VTable change is propagated across all implementations.
Interface Segregation 8 ShadowParams fields are all consumed by shader/RHI.
Dependency Inversion 8 World renders via IShadowScene; no direct RHI calls from world code.
Average 7.8

🎯 Final Assessment

Overall Confidence Score: 76%

Confidence Breakdown:

  • Code Quality: 80% - Clean, idiomatic Zig, follows existing patterns.
  • Completeness: 72% - Most [Lighting Overhaul][Phase 2] Rewrite cascaded shadows and caster submission #903 scope implemented; entity shadow gap and un-aggregated tests.
  • Risk Level: 75% - Shadow pipeline changes are high-risk, but ABI checks and unit tests pass.
  • Test Coverage: 75% - New inline CSM tests run and pass; shadow_tests.zig tests are not exercised.

Merge Readiness:

  • All critical issues resolved
  • SOLID average score >= 6.0
  • Overall confidence >= 60%
  • No security concerns
  • Tests present and passing (if applicable)

Verdict:

MERGE WITH FIXES

The PR is a solid, well-structured rewrite of the shadow system and is close to ready. The main fixes needed are the stale/outdated tests in modules/engine-graphics/src/shadow_tests.zig, extending ShadowCascades.isValid() to cover the new fields, and clarifying the entity-shadow scope. Addressing those would make this ready to merge with high confidence.

{
  "reviewed_sha": "ce878cc793a4b5c6bcc9dcd3fda8f12acdb25bfa",
  "critical_issues": 0,
  "high_priority_issues": 0,
  "medium_priority_issues": 3,
  "overall_confidence_score": 76,
  "recommendation": "MERGE WITH FIXES"
}

New%20session%20-%202026-07-09T22%3A57%3A46.342Z
opencode session  |  github run

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

📋 Summary

PR #907 rewrites ZigCraft's cascaded shadow pipeline, replacing fixed splits with practical logarithmic splits, adding receiver-volume extrusion for caster bounds, stable texel-snapped projections, alpha-tested cutout shadows, and coherent PCF tiers (hard/4/9/16 taps). It expands the ShadowUniforms ABI and keeps the Vulkan/GLSL layouts consistent. The PR closes issue #903. Most of #903's scope is implemented, but the acceptance item "Include supported entities in the shadow scene" is not visibly addressed for non-chunk entities.

nix develop --command zig build test passes, including shader validation and the new behavioral tests.

📌 Review Metadata

The PR implements the majority of #903's requested scope and includes the required tests. The non-chunk entity shadow acceptance criterion remains unaddressed.

🔴 Critical Issues (Must Fix - Blocks Merge)

None identified.

⚠️ High Priority Issues (Should Fix)

None identified.

💡 Medium Priority Issues (Nice to Fix)

[MEDIUM] modules/engine-graphics/src/shadow_tests.zig:81-414 - isValid failure tests no longer isolate the condition they claim to test
Confidence: High
Description: The second commit added validation of overlap_starts, depth_spans, and receiver_corners to ShadowCascades.isValid(), but several existing tests (non-finite splits, zero texel size, non-increasing splits, zero split) still only populate cascade_splits and texel_sizes, leaving the new fields at their initZero() defaults. Those defaults (depth_spans = 0, overlap_starts = 0) already cause isValid() to return false, so the tests pass for the wrong reason and do not actually exercise the named failure mode.
Impact: Reduced regression coverage; if the tests are "cleaned up" by setting valid auxiliary fields without also fixing the primary invalid condition, the intended failure paths could silently stop being tested.
Suggested Fix: In each of those tests, set valid overlap_starts, depth_spans, receiver_corners, and light_space_matrices before injecting the specific invalid condition (e.g., cascade_splits[1] = nan).

[MEDIUM] Issue #903 scope gap - supported entities not added to shadow scene
Confidence: Low
Description: #903's scope includes "Include supported entities in the shadow scene." This diff only routes chunk geometry through the updated World/WorldRenderer shadow path; no non-chunk entity rendering is submitted to the shadow pass.
Impact: If the project has non-block entities that should cast shadows, this acceptance criterion is not met.
Suggested Fix: If entity shadows are required, route them through IShadowScene or add an entity shadow pass; otherwise, update #903's scope/acceptance criteria to reflect that this PR does not cover them.

ℹ️ Low Priority Suggestions (Optional)

[LOW] modules/engine-graphics/src/shadow_tests.zig:304-318 - ShadowUniforms field offset test omits fade_params
Confidence: High
Description: The offset test verifies matrices, splits, overlap_starts, texel_sizes, depth_spans, and shadow_params, but does not assert the fade_params offset.
Impact: Minor test gap; shadow_uniforms.zig already has a comptime check for this.
Suggested Fix: Add const fade_params_offset = @offsetOf(ShadowUniforms, "fade_params"); and assert matrices_size + @sizeOf([4]f32) * 6 == fade_params_offset.

[LOW] modules/engine-graphics/src/shadow_tests.zig:60-68 - initZero test doesn't verify new fields
Confidence: High
Description: The test checks cascade_splits and texel_sizes are zero but does not check overlap_starts, depth_spans, or receiver_corners.
Impact: Minor; if initZero() is changed to set non-zero defaults for the new fields, the test won't catch it.
Suggested Fix: Add assertions that overlap_starts[i], depth_spans[i], and receiver_corners[i][j] are zero.

✅ Previous Review Fixes Acknowledged

  • [FIXED] Previous issue: shadow_tests.zig outdated fixed-split tests now use practicalSplit.
  • [FIXED] Previous issue: ShadowCascades.isValid() now validates overlap_starts, depth_spans, and receiver_corners.
  • [FIXED] Previous issue: terrain.frag debug seam channel now uses shadows.overlap_starts[layer + 1].
  • [FIXED] Previous issue: terrain.frag shadow_params comment updated to describe current fields.
  • [FIXED] Previous issue: world.zig shadow pass comment updated to describe caster-bound behavior.
  • [FIXED] Previous issue: world_renderer.zig unused light_space_matrix now has an explanatory comment.
  • [FIXED] Previous issue: csm.zig docstring now correctly states the default lambda=0.75.

📊 SOLID Principles Score

Principle Score Notes
Single Responsibility 8 CSM math, GPU upload, and scene submission are cleanly separated.
Open/Closed 7 New fields extend structs; test isolation could be more robust.
Liskov Substitution 8 IShadowScene VTable change is propagated across all implementations.
Interface Segregation 8 ShadowParams fields are all consumed by shader/RHI.
Dependency Inversion 8 World renders via IShadowScene; no direct RHI calls from world code.
Average 7.8

🎯 Final Assessment

Overall Confidence Score: 80%

Confidence Breakdown:

Merge Readiness:

  • All critical issues resolved
  • SOLID average score >= 6.0
  • Overall confidence >= 60%
  • No security concerns
  • Tests present and passing (if applicable)

Verdict:

MERGE WITH FIXES

The shadow rewrite is solid and well-structured. The previous review's medium issues were largely addressed in the follow-up commit. The remaining blockers are the isValid test isolation gap and the unresolved entity-shadow scope item; fixing those would make this ready to merge with high confidence.

{
  "reviewed_sha": "99b6c5bf5308a47fc1ab19c6df54b5ddd528766a",
  "critical_issues": 0,
  "high_priority_issues": 0,
  "medium_priority_issues": 2,
  "overall_confidence_score": 80,
  "recommendation": "MERGE WITH FIXES"
}

New%20session%20-%202026-07-09T23%3A40%3A17.545Z
opencode session  |  github run

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

📋 Summary

PR #907 rewrites ZigCraft's cascaded shadow pipeline, replacing fixed cascade ratios with practical logarithmic splits, adding stable texel-snapped projections, receiver-volume extrusion for caster bounds, explicit overlap bands, per-cascade bias scaling, alpha-tested cutout shadows, and coherent hard/4/9/16-tap PCF tiers. It expands the ShadowUniforms ABI, enables shadow MDI by default, and removes hidden 128/160-unit shadow distance caps. The PR closes issue #903. Most of #903's scope is implemented and tested, but the acceptance item "Include supported entities in the shadow scene" is not visibly addressed for non-chunk entities.

nix develop --command zig build test and nix develop --command zig build -Dskip-present both pass. The known unrelated test-robustness compile failure from the Zig 0.16 std.process.Child.Term.Exited rename remains unchanged.

📌 Review Metadata

The PR implements the majority of #903's requested scope, including the required behavioral tests. The non-chunk entity shadow acceptance criterion remains unaddressed.

🔴 Critical Issues (Must Fix - Blocks Merge)

None identified.

⚠️ High Priority Issues (Should Fix)

None identified.

💡 Medium Priority Issues (Nice to Fix)

[MEDIUM] Issue #903 scope gap - supported entities not added to shadow scene
Confidence: Low
Description: #903's scope includes "Include supported entities in the shadow scene" and acceptance criteria state "entities cast supported shadows." The diff only routes chunk geometry through the updated World/WorldRenderer shadow path; no non-chunk entity rendering is submitted to the shadow pass.
Impact: If the project has non-block entities that should cast shadows, this acceptance criterion is not met.
Suggested Fix: Either route supported entity meshes through IShadowScene or update issue #903's scope/acceptance criteria to reflect that this PR is limited to chunk and cloud shadows.

ℹ️ Low Priority Suggestions (Optional)

None identified.

✅ Previous Review Fixes Acknowledged

  • [FIXED] Previous issue: shadow_tests.zig outdated fixed-split tests now use practicalSplit.
  • [FIXED] Previous issue: ShadowCascades.isValid() now validates overlap_starts, depth_spans, and receiver_corners.
  • [FIXED] Previous issue: shadow_tests.zig isValid failure tests now isolate the intended condition via validCascades().
  • [FIXED] Previous issue: shadow_tests.zig initZero test now verifies new fields.
  • [FIXED] Previous issue: shadow_tests.zig ShadowUniforms offset test now includes fade_params.
  • [FIXED] Previous issue: terrain.frag debug seam channel now uses shadows.overlap_starts[layer + 1].
  • [FIXED] Previous issue: terrain.frag shadow_params comment updated to describe current fields.
  • [FIXED] Previous issue: world.zig shadow pass comment updated to describe caster-bound behavior.
  • [FIXED] Previous issue: world_renderer.zig unused light_space_matrix now has an explanatory comment.
  • [FIXED] Previous issue: csm.zig docstring now correctly states the default lambda=0.75.

📊 SOLID Principles Score

Principle Score Notes
Single Responsibility 8 CSM math, GPU upload, and scene submission are cleanly separated.
Open/Closed 7 New fields extend structs; test isolation is now robust.
Liskov Substitution 8 IShadowScene VTable change is propagated across all implementations.
Interface Segregation 8 ShadowParams fields are all consumed by shader/RHI.
Dependency Inversion 8 World renders via IShadowScene; no direct RHI calls from world code.
Average 7.8

🎯 Final Assessment

Overall Confidence Score: 85%

Confidence Breakdown:

Merge Readiness:

  • All critical issues resolved
  • SOLID average score >= 6.0
  • Overall confidence >= 60%
  • No security concerns
  • Tests present and passing (if applicable)

Verdict:

MERGE WITH FIXES

The shadow rewrite is solid and well-structured. The previous review's test issues were fully addressed in the latest commit. The remaining item is the #903 entity shadow scope gap; clarifying or implementing that would make this ready to merge with high confidence.

{
  "reviewed_sha": "65b4089b59869fef318120019113605df76d3c5b",
  "critical_issues": 0,
  "high_priority_issues": 0,
  "medium_priority_issues": 1,
  "overall_confidence_score": 85,
  "recommendation": "MERGE WITH FIXES"
}

New%20session%20-%202026-07-09T23%3A51%3A42.386Z
opencode session  |  github run

@github-actions

Copy link
Copy Markdown
Contributor

📋 Summary

PR #907 rewrites ZigCraft's cascaded shadow pipeline and closes issue #903. The current commit (0e2fbe9) adds ECS entity shadow rendering, completing the remaining acceptance item "Include supported entities in the shadow scene." The PR now covers practical logarithmic cascade splits, receiver-volume extrusion, stable texel-snapped projections, alpha-tested cutout chunk shadows, coherent PCF tiers (hard/4/9/16 taps), expanded ShadowUniforms ABI, and entity shadow casting via a new shadow_caster_renderer hook.

nix develop --command zig build test and nix develop --command zig build -Dskip-present both pass. The unrelated test-robustness compile failure from the Zig 0.16 std.process.Child.Term.Exited rename remains unchanged.

📌 Review Metadata

The PR fully implements #903's requested scope, including the entity shadow acceptance criterion that was outstanding in previous reviews.

🔴 Critical Issues (Must Fix - Blocks Merge)

None identified.

⚠️ High Priority Issues (Should Fix)

None identified.

💡 Medium Priority Issues (Nice to Fix)

None identified.

ℹ️ Low Priority Suggestions (Optional)

None identified.

✅ Previous Review Fixes Acknowledged

  • [FIXED] Previous issue: shadow_tests.zig outdated fixed-split tests now use practicalSplit.
  • [FIXED] Previous issue: ShadowCascades.isValid() now validates overlap_starts, depth_spans, and receiver_corners.
  • [FIXED] Previous issue: shadow_tests.zig isValid failure tests now isolate the intended condition via validCascades().
  • [FIXED] Previous issue: shadow_tests.zig initZero test now verifies new fields.
  • [FIXED] Previous issue: shadow_tests.zig ShadowUniforms offset test now includes fade_params.
  • [FIXED] Previous issue: terrain.frag debug seam channel now uses shadows.overlap_starts[layer + 1].
  • [FIXED] Previous issue: terrain.frag shadow_params comment updated to describe current fields.
  • [FIXED] Previous issue: world.zig shadow pass comment updated to describe caster-bound behavior.
  • [FIXED] Previous issue: world_renderer.zig unused light_space_matrix now has an explanatory comment.
  • [FIXED] Previous issue: csm.zig docstring now correctly states the default lambda=0.75.
  • [FIXED] Previous issue: Issue [Lighting Overhaul][Phase 2] Rewrite cascaded shadows and caster submission #903 scope gap — supported entities are now rendered into the shadow scene via RenderSystem.renderShadowCasters and the SceneContext.shadow_caster_renderer hook.

📊 SOLID Principles Score

Principle Score Notes
Single Responsibility 8 CSM math, GPU upload, scene submission, and entity shadow casting are cleanly separated.
Open/Closed 7 New fields extend structs; entity shadow hook is optional and doesn't break existing code.
Liskov Substitution 8 IShadowScene VTable change is propagated across all implementations.
Interface Segregation 8 ShadowParams and SceneContext optional fields are all consumed.
Dependency Inversion 8 World and ECS render via IShadowScene / RHI abstractions; no direct RHI calls from world code.
Average 7.8

🎯 Final Assessment

Overall Confidence Score: 88%

Confidence Breakdown:

  • Code Quality: 90% - Clean, idiomatic Zig; follows existing patterns; previous review issues addressed.
  • Completeness: 90% - [Lighting Overhaul][Phase 2] Rewrite cascaded shadows and caster submission #903 scope is fully implemented, including entity shadows.
  • Risk Level: 80% - Shadow pipeline changes are inherently high-risk, but ABI checks and unit tests pass.
  • Test Coverage: 85% - New CSM/ABI/entity shadow tests pass; shadow_tests.zig is aggregated.

Merge Readiness:

  • All critical issues resolved
  • SOLID average score >= 6.0
  • Overall confidence >= 60%
  • No security concerns
  • Tests present and passing

Verdict:

MERGE

The shadow pipeline rewrite is complete, well-structured, and addresses all outstanding review items including entity shadow rendering.

{
  "reviewed_sha": "0e2fbe9e5fdfe4d60ba7f896d887409f85d759ec",
  "critical_issues": 0,
  "high_priority_issues": 0,
  "medium_priority_issues": 0,
  "overall_confidence_score": 88,
  "recommendation": "MERGE"
}

New%20session%20-%202026-07-10T00%3A40%3A16.038Z
opencode session  |  github run

@github-actions
github-actions Bot merged commit 296220f into dev Jul 10, 2026
23 of 26 checks passed
@MichaelFisher1997
MichaelFisher1997 deleted the feature/lighting-phase2-shadows branch July 10, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation engine shaders

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Lighting Overhaul][Phase 2] Rewrite cascaded shadows and caster submission

1 participant