Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions lib/PixelCanvas.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-- Render targets measured in real framebuffer PIXELS.
--
-- love.graphics.newCanvas defaults its `dpiscale` to
-- love.graphics.getDPIScale(), so on a highdpi surface the texture it
-- allocates is NOT the size it was asked for -- newCanvas(2752, 2064) on a
-- panel reporting a DPI scale of 2 asks the driver for 5504x4128.
--
-- Every target in this mod is already counted in framebuffer pixels: the
-- free-roam scene canvas is love.graphics.getPixelDimensions() (see
-- sceneSize in main.lua, and the 1/dpi blit the engine composites it with),
-- the shadow map is a resolution rung, the blur pairs are the size of the
-- image they were handed. Letting LOVE scale them a second time is the DPI
-- factor applied twice.
--
-- On an iPad at DPI scale 2 that took the scene canvas past the driver's
-- maximum texture size. newCanvas threw, beginScene returned false,
-- drawWorld returned nil -- and returning nil IS the 2D fallback, so the
-- engine quietly kept drawing the flat world. Every switch said the mode was
-- on (the OPTIONS row, the mod manager, the hotkey) and nothing ever
-- appeared. Desktop never saw it: dpiscale is 1 there.
--
-- getWidth()/getHeight() always report the REQUESTED size, so pinning the
-- scale changes only the resolution of the target -- no geometry, no UV, no
-- compositing scale anywhere moves, and the FX overlay's projected pixel
-- coordinates finally land on the pixels they name. The engine's own render
-- targets do this for the same reason (src/render/PixelCanvas.lua).

-- the mod namespace (see main.lua)
local V = ...

local PixelCanvas = {}

-- One framebuffer pixel per w/h, always. Returns ok, canvas -- the shape the
-- pcall-guarded call sites already branch on, so a driver that refuses the
-- allocation still degrades instead of erroring.
function PixelCanvas.new(w, h)
return pcall(love.graphics.newCanvas, w, h, { dpiscale = 1 })
end

return PixelCanvas
4 changes: 3 additions & 1 deletion lib/ShadowMap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ end
local function getCanvas(res)
if canvas == false then return nil end
if canvas and canvasRes == res then return canvas end
local ok, c = pcall(love.graphics.newCanvas, res, res)
-- pixel-exact: `res` IS the texel count the filter's sunTexel is derived
-- from, so the texture must be exactly that big (see lib/PixelCanvas.lua)
local ok, c = V.require("PixelCanvas").new(res, res)
if not (ok and c) then
canvas = false
return nil
Expand Down
10 changes: 8 additions & 2 deletions lib/TiltShift.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
-- failure -- headless, no shader support) apply() hands the canvas back
-- untouched, so every other path is byte-for-byte what it always was.

-- the mod namespace (see main.lua): V.require loads a sibling module
local V = ...

local TiltShift = {}

TiltShift.level = 0
Expand Down Expand Up @@ -85,9 +88,12 @@ end

local function getCanvases(w, h)
if not ping or cw ~= w or ch ~= h then
local ok, a = pcall(love.graphics.newCanvas, w, h)
-- pixel-exact: w and h come from the scene canvas this pass was handed,
-- which is already counted in framebuffer pixels (see lib/PixelCanvas.lua)
local PixelCanvas = V.require("PixelCanvas")
local ok, a = PixelCanvas.new(w, h)
if not ok then return nil end
local okB, b = pcall(love.graphics.newCanvas, w, h)
local okB, b = PixelCanvas.new(w, h)
if not okB then return nil end
-- the gaussian's fractional tap offsets need linear filtering
a:setFilter("linear", "linear")
Expand Down
4 changes: 3 additions & 1 deletion lib/Voxel3D.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ local WorldCurve = V.require("WorldCurve")
local Sky = V.require("Sky")
local DayNight = V.require("DayNight")
local GlassMask = V.require("GlassMask")
local PixelCanvas = V.require("PixelCanvas")

local Voxel3D = {}

Expand Down Expand Up @@ -540,7 +541,8 @@ function Voxel3D.beginScene(w, h, cx, cy, vw, vh, sky, slot)
local name = slot or "world"
local held = slots[name]
if not (held and held.w == w and held.h == h) then
local ok, c = pcall(love.graphics.newCanvas, w, h)
-- pixel-exact: w and h are framebuffer pixels already (see PixelCanvas)
local ok, c = PixelCanvas.new(w, h)
if not ok then return false end
c:setFilter("nearest", "nearest")
if held and held.canvas and held.canvas.release then
Expand Down