pokecenter machines, water occlusion

This commit is contained in:
DramaticShape
2026-08-02 00:01:39 -04:00
parent 91cc2d6f51
commit a7c9541ac4
6 changed files with 454 additions and 143 deletions
+36 -9
View File
@@ -583,8 +583,40 @@ end
-- The overworld's alone: the staged battle draws its water plain, always --
-- its placed camera reads this pass wrong, and a stage set wants painted
-- water anyway (see BattleScene, where the choice is argued).
-- ------- and why the flat draw happens FIRST, every time
--
-- The reflective pass writes no depth -- it cannot, the depth canvas is
-- detached for the length of it so the shader can READ it -- and it does its
-- own depth test against that texture instead. That test asks whether
-- something opaque is in front, and it answers correctly for every case but
-- one: WATER IN FRONT OF WATER. Nothing puts water in the depth buffer, so
-- no lake can hide another, and the pass simply paints them in mesh order.
--
-- On flat water that never mattered, because every surface lies in the one
-- plane at its own recessed height and a farther sheet always lands farther
-- down the screen. THE WORLD CURVE ENDS THAT. The bend drops the world by
-- the square of its distance, so the far side of the map swings down and
-- back up into the near field of view -- and a sheet of sea a hundred and
-- fifty tiles away, drawn later in the same mesh, paints straight over the
-- pond at the player's feet. That is the tall grass and the water "from the
-- other side of the map": not a reflection of them, THEM, rasterised on top
-- of the water in front of you.
--
-- So the meshes go down flat first, through the ordinary scene shader with
-- depth writes on, and the reflective pass draws over the top of what
-- survived. Three things fall out of it and all three are wanted: the depth
-- buffer now holds the water surface, so the pass's own test throws the far
-- sheet away; the reflection COPY holds it too, so a ray grazing another
-- part of the lake reads water rather than the void behind it; and the flat
-- draw is the same fallback this function already ended with, so a frame
-- that cannot run the reflective pass is unchanged.
--
-- It costs one more rasterisation of the water meshes. Water is a small
-- share of a frame's triangles and this is the cheapest shader in the mode.
function VoxelScene.drawWater(draws, cast)
local plain = true
for _, d in ipairs(draws) do
Voxel3D.draw(d[1], d[2], d[3])
end
if Water.enabled() and Voxel3D.depthReadable() then
local mirror, depth = Voxel3D.beginWater(cast)
local w, h = Voxel3D.size()
@@ -602,20 +634,15 @@ function VoxelScene.drawWater(draws, cast)
Water.draw(d[1], d[2], d[3])
end
Water.finish()
plain = false
end
-- Unconditionally, and OUTSIDE the success branch: beginWater unbinds
-- the shader and the depth mode BEFORE it can discover it cannot go on,
-- so a frame that bails halfway through has to be put back together
-- exactly like one that succeeded -- otherwise the plain draw below (and
-- every pass after it) runs with no shader and no depth test.
-- exactly like one that succeeded -- otherwise every pass after it runs
-- with no shader and no depth test. (What a bail leaves on screen is the
-- flat draw above, which is where this function used to end anyway.)
Voxel3D.endWater()
end
if plain then
for _, d in ipairs(draws) do
Voxel3D.draw(d[1], d[2], d[3])
end
end
end
-- A stamp of everything the sun pass depends on. Nothing in it moving