Skip to content

fix: shadow map under LÖVE 12 — clip z onto [0,1], probe the canvas y-orientation - #75

Open
luisgonzaleznf wants to merge 1 commit into
DramaticShape:devfrom
luisgonzaleznf:fix/shadowmap-love12-clip-conventions
Open

fix: shadow map under LÖVE 12 — clip z onto [0,1], probe the canvas y-orientation#75
luisgonzaleznf wants to merge 1 commit into
DramaticShape:devfrom
luisgonzaleznf:fix/shadowmap-love12-clip-conventions

Conversation

@luisgonzaleznf

@luisgonzaleznf luisgonzaleznf commented Aug 3, 2026

Copy link
Copy Markdown

Fixes #74.

The sun pass bypasses transform_projection and hand-rolls LÖVE 11 clip conventions: Mat4.ortho emits clip z in [-1, 1] (its own comment says so), and fit() applies Mat4.scale(1, -1, 1) to compensate 11's canvas-bound y-flip. LÖVE 12 changed both, on every backend — love2d/love@7bfbd647 notes that projection matrices "no longer need to be flipped when rendering to a canvas versus the main screen", and closes with "custom projection matrices might need to be altered to account for the more consistent range".

So under 12 the map comes back with the near half of the light frustum missing, and what does land is read vertically mirrored — the giant detached slabs in #74. The iOS shell runs LÖVE 12 while desktop runs 11.5, which is why it never showed up on desktop, and why it is latent for desktop and Android the day those move to 12.

Two changes, one file:

  • Z01 — the light projection's clip z lands on [0, 1]. This is what restores coverage. [0, 1] sits inside the legacy clip volume too, and the packed depth the readers compare is bit-identical under 11 (vDepth reads clip z where it used to compute the same number from [-1, 1]), so 11.x cannot change by construction.
  • probeVSign() — the reader's v-axis direction is measured once with a 4x4 draw through the pass's own shader, rather than assumed from a version or platform list. This is what restores placement. Any probe failure answers +1, which is exactly today's behaviour.

No OS or version checks.

Each half was confirmed by running it alone under LÖVE 12: Z01 on its own gives a full map with the shadows still misplaced, probeVSign on its own the reverse. (Also ruled out on the way: not Metal-specific — it reproduces on LÖVE 12 + OpenGL — and not canvas dpiscale, since the LÖVE 11.5 control ran with the same px 4096 inflation and stayed clean.)

Validated on:

  • LÖVE 11.5 / OpenGL (gen1recomp desktop build) — control, unchanged
  • LÖVE 12.0 nightly / OpenGL and Metal on macOS — broken before, clean after
  • iPhone 15 Pro Max / iOS 27.0, gen1recomp v0.1.56 and v0.1.59 iOS IPA — broken before, clean after

Now that #48 is merged, this drops the iOS available() gate it added: with the pass itself LÖVE 12-correct, iOS gets working shadows rather than none. PixelCanvas is adopted here in getCanvas; the rest of #48 is untouched.

Not addressed here, both noted in #74: the water shader fails to compile under LÖVE 12 + Metal, so lakes draw flat; and the scene camera's own bypass projection has the same latent y issue, but is currently compensated engine-side on iOS (bryanthaboi/gen1recomp#582), so it needs to move in step with the engine rather than in this PR.

love.graphics.setOrthoProjection is probably the idiomatic endgame for all of this once the supported floor is LÖVE 12; this keeps the mod running identically on 11 and 12 today.

…rientation

The sun pass bypasses transform_projection and hand-rolls LOVE 11 clip
conventions -- Mat4.ortho emits z in [-1,1], and fit() flips y to
compensate 11's canvas-bound orientation.  LOVE 12 changed both on every
backend, so the map came back with the near half of the light frustum
missing and the rest read vertically mirrored: the giant detached slabs
seen on iOS, whose shell runs 12 while desktop runs 11.5.

Z01 restores coverage, probeVSign restores placement -- isolated
separately on LOVE 12 Metal and OpenGL, with LOVE 11.5 as the control.
The packed depth is bit-identical under 11, so it cannot change there.

Removes the iOS available() gate from DramaticShape#48, which is no longer needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shadow map breaks under LÖVE 12 (any backend): near half of the light frustum missing, and the map read vertically mirrored

1 participant