🤖 Agent: Merged by Ludovic's AI agent (Claude, contrib-gate-19). Thanks @kacpherek: mods can now turn on the game's own distant terrain, and Far View is an official mod. I merged main into the branch. render.set-far-terrain is now API level 7, because main added levels 4 to 6 (world, recipes, browser) in the meantime. The horizon-mods sandbox tests (32), the far-view wasm build, and clippy with the mods feature all pass. Without the mods feature, the LOD path is unchanged.
A mod can now turn on the game's distant terrain (LOD) with
render.set-far-terrain: a distance of 64 to 1024 chunks and Far Detail's
Reduced. The game builds and draws the tiles as it does for the LOD
Distance setting, which wins while it is on. One far terrain shows at a
time, the first loaded mod's. API level 4.
mods/official/far-view is the official mod on it: Distance (256 chunks by
default) and Far detail on its settings page, kept in its storage.
HDR10 is what games usually present and what the display receives: a
compositor composes in it or converts to it anyway. The NVIDIA driver
offers it on Wayland next to scRGB. A 10-bit swapchain also halves the
last pass's bandwidth; the frame before it is 8-bit, so nothing is lost.
hdr.wgsl converts the same linear light to BT.2020 (BT.2087) and encodes
it with the ST 2084 curve. HORIZON_HDR_OUTPUT=pq or scrgb allows only
that one, for comparing them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EMISSIVE_LAYER took bit 14 of TerrainVertex::layer, halving the sprite
layers terrain vertices can index (32768 to 16384) and leaving no flag
bit free. The colour's alpha byte was always 0xFF: its low four bits now
hold 15 minus the light level the face emits (EMISSION_BITS), so 0xFF
still means none and the other four bits stay free. terrain.wgsl takes
only the colour's rgb and passes the level on; Java shader packs get
alpha 1; the section mesh fixture restores vanilla's 0xFF.
The HDR pass still lifts any emitting face the same way; the level is
there for scaling the lift by it later.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HDR (Graphics > Display, off by default) presents to an scRGB swapchain
where the surface offers it. The frame is drawn as in SDR, in vanilla's
gamma space; a last pass decodes it at the Paper White and lifts light
sources (blocks that emit light, lava, the sun and the moon) evenly
towards the Peak Brightness.
The mesher marks emitting faces with EMISSIVE_LAYER (bit 14 of the
layer); the frame's alpha carries the mark to the HDR pass, which lifts
only pixels that still show the world before the hand and HUD.
horizon-hdr sends HDR metadata through VK_EXT_hdr_metadata, which wgpu
doesn't: without it KWin clips scRGB content above 1.0 (80 nits).
Part of #1441.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A developer of Iris showed that Horizon's shader pack code was written from
Iris's source. This removes it: the horizon-shaderpack crate, Java pack
loading and its render stages, Horizon's own WGSL packs and the example
packs, the Shader Packs screen and its option, the launcher's shader pack
browsing and installing, and the docs about them. Shader packs may come
back later as a clean-room rewrite.
The vanilla renderer and its post-processing (resolution scale, FXAA) are
unchanged. Options files that name a pack load and drop the key; the
launcher reads manifests that list a shader pack, and files in
`shaderpacks/` are never deleted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pause menu's Friends icon is recorded as a widget, so a controller
reaches it and the control socket names it. The sharing screen's long help
URL ran off the screen: a Troubleshooting... button beside Done opens it,
and the hint drops out when it would reach the footer. The graphics docs
say what the two Horizon screens hold (vanilla's own settings stay on Video
Settings).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the Horizon menu style (options_horizon.rs, front.rs, the live title
backdrop and its post grade, the launcher's menu-style setting, CLI and MCP
tool). Every screen is vanilla's. Horizon's own settings hang off vanilla's
Options the way mods add theirs: Horizon Settings... and Mods... take the
Telemetry/Credits slots, and Horizon Settings opens Graphics, Advanced
Graphics, Shader Packs, Controller Settings, Extras and Mods, each a vanilla
options list with tooltips. Play with friends moves behind vanilla's Friends
buttons: the pause menu's opens Play with Friends (share, copy, stop), the
title screen's opens Join a Friend, and Direct Connection takes a full code.
Old files load as before: horizon.txt's menuStyle line and
horizon-graphics.txt's level line are ignored.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HORIZON_SPIKES spans keep the thread's CPU time beside their wall time,
and the slow-frame line gives the render thread's CPU time in the frame.
A span that mostly waited (for the GPU, a lock or a core) prints both
(`submit 30.2/0.1`), so a frame that waited reads apart from one that
worked. Found the cause of #678's long frames: the render thread losing
its core in queue.submit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured on an Intel HD 620 (#897): rain and snow cost about 3 ms of GPU
per frame there, most of it from the weather radius; FXAA about 0.8 ms;
cave culling saves about 0.6 ms; mipmaps cost nothing measurable and
clouds about 0.1 ms. A new Cost::Saves tag ("Saves time", in the success
colour) marks a setting that makes frames faster when on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The soft 4 ms yield per frame (also with Unlimited budgets) made a saved
RD32 world reach full render distance about 1 s later on the Mac mini
(streaming time after launch, 4 alternating pairs: main 1.9 s mean, yield
2.8 s; t100 from a first batch of 3 pairs: 6.1 s vs 7.1 s) without better
loading frame times (max 133-210 ms vs 31-150 ms). Without a budget every
finished mesh uploads at once again, as on main. The budgeted path keeps
this branch's fixes: only loaded chunks' sections wait, and sizes count the
24-byte terrain vertex.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With an explicit Present Mode (Mailbox, Immediate), the VSync option did
nothing: the setting replaced vanilla's choice even with VSync on, so a
window kept running uncapped. Vanilla's VSync means Fifo, in a window and in
fullscreen alike. Now VSync on always presents with Fifo, and the Present
Mode setting chooses only while VSync is off (Auto keeps vanilla's choice:
Immediate, else Mailbox, else Fifo). The choice is one tested function,
window::chosen_present_mode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Horizon graphics setting (Performance, off by default, batteryMode in
horizon-graphics.txt): at most 60 frames per second in a world, 30 in menus
without a world or behind other windows, and half the automatic worker
threads. It only changes when frames are drawn; ticks and what frames show
are untouched.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At render distance 32 the single section arena grew past the 4 GiB buffer
limit and the renderer panicked. Sections now live in pages of at most
256 MiB (or the device's buffer limit); draws keep their order and bind each
page once per run of consecutive draws in it, so translucent sections stay
back to front. docs/graphics.md describes the settings, the benchmark and
what changed; graphics_bench.py --compare prints a before/after table and
keeps each game's log.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>