Skip to content

Downsample zoom levels from the finer tile in linear light - #629

Merged
jpenilla merged 1 commit into
masterfrom
feat/chained-zoom-resampling
Oct 21, 2026
Merged

jpenilla merged 1 commit into
masterfrom
feat/chained-zoom-resampling

Conversation

@jpenilla

Copy link
Copy Markdown
Owner

Coarser zoom levels were point-sampled from each region's new pixels, taking the top-left block of every 2^k square, which made thin features break up and shading alias when zoomed out. Each level is now built from the finished tile one level finer with a 2×2 box filter in linear light. Colors are weighted by alpha and alpha is set to coverage, so edges against void or unrendered areas fade out instead of darkening. Because the whole finer tile is used, areas rendered earlier are included.

Overworld at zoom 0, before and after

The End at zoom 0, before and after

Both are zoom 0 (8 blocks per pixel) at native size from the demo world. Before is the demo site's existing tiles, after is zoom 0 rebuilt from the same max zoom tiles.

Saving

A region's save is now a chain: its max zoom tile is patched and written, then each parent is read, the written child is downsampled into its quadrant, and the parent is written, up to zoom 0. A failed write ends that region's chain.

Updates to the same tile run one at a time in the order they became ready, using a new KeyedSerialExecutor that queues waiting tasks per key instead of holding a thread, so only real dependencies are waited on. A parent update is queued before its child's tile is released, so updates to a shared parent run in the order their sources were written.

Tile file reading and writing moved from RegionImage to TileImages, leaving RegionImage with only the region's pixels. Queue capacity and shutdown use one lock and condition: shutdown rejects new saves, waits for in-flight chains, including parent updates they queue while finishing, then stops the workers. Checkpoints still count a region as done once queued, and max-pending-images still limits whole region saves.

Upgrading

Existing coarse tiles keep their point-sampled content until a region under them is saved again. A full render updates them all.

Coarser zoom levels were point-sampled from each region's new pixels,
taking the top-left block of every 2^k square, which made thin
features break up and shading alias when zoomed out. Each level is
now built from the finished tile one level finer with a 2×2 box
filter in linear light. Colors are weighted by alpha and alpha is set
to coverage, so edges against void or unrendered areas fade out
instead of darkening. Because the whole finer tile is used, areas
rendered earlier are included.

A region's save is now a chain: its max zoom tile is patched and
written, then each parent is read, the written child is downsampled
into its quadrant, and the parent is written, up to zoom 0. A failed
write ends that region's chain. Updates to the same tile run one at a
time in the order they became ready, using a new KeyedSerialExecutor
that queues waiting tasks per key instead of holding a thread, so
only real dependencies are waited on. A parent update is queued
before its child's tile is released, so updates to a shared parent
run in the order their sources were written.

Tile file reading and writing moved from RegionImage to TileImages,
leaving RegionImage with only the region's pixels. Queue capacity and
shutdown use one lock and condition: shutdown rejects new saves,
waits for in-flight chains, including parent updates they queue
while finishing, then stops the workers. Checkpoints still count a
region as done once queued, and max-pending-images still limits whole
region saves.

Existing coarse tiles keep their point-sampled content until a region
under them is saved again. A full render updates them all.
@jpenilla
jpenilla merged commit 2e158c2 into master Oct 21, 2026
2 checks passed
@jpenilla
jpenilla deleted the feat/chained-zoom-resampling branch October 21, 2026 23:09
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.

1 participant