16.666667 steps a 60 fps clock. STEP_MS is a finite number more than 0,
and the reply gives it back as given.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
screenshot-sequence FRAMES STEP_MS PATH, under HORIZON_STILL with the world
frozen, makes the running pack start over and draws FRAMES frames on a
scripted clock: frame n is n frames and (n - 1) x STEP_MS milliseconds in,
STEP_MS after the frame before (0 on frame 1). The last is written as
screenshot PATH writes it, its -hdr.png too under HDR output, and the reply
names the pack and the last frame's clock. The same build, GPU and driver
write the same bytes every run, for shaders/ packs, Horizon's own and none.
Sequence frames are submitted inline and waited for on the GPU, so each
reads the centre depth the one before left, or the sequence fails; a frame
the surface refused is drawn again. It refuses to start with far terrain,
TAA, frame generation, chunk fade or the shadow cache on, refuses commands
that would change the scene while it runs, and ends with an error when the
camera, world, settings, pack or window size change. cancel stops it, quit
still quits. Documented in agent-control.md's STILL section, shaders.md and
api/shaders.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The graphics screen gets a Shaders page between Performance and Advanced:
Shader Packs... opens the pack list (Horizon's .hshader packs and shaders/
folder ones, with the picked pack's options), and Shadow Cache moves there
from Performance. Horizon Settings loses its Shader Packs button, so the
list has one way in, beside the other graphics settings, as Iris hangs
off Sodium's video screen.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
🤖 Agent: a drag saves the option and rebuilds the pack once, on release, not on every pointer move; the manifest already refuses min >= max and step <= 0, so slider_position and slider_value cannot divide by zero.
`[shadow] option` names the option the map is drawn while it is not 0: off,
there is no map, no shadow pass and `has_shadow` reads 0, as `[reflection]
option` does for the water mirror. `resolution_option` and `distance_option`
name an int option, or a choice whose values are numbers, whose value replaces
`resolution` or `distance`, checked against the same ranges; changing one
rebuilds the map, as any option change reloads the pack. The options sizing
the map need no `override`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On a Horizon pack's options page a float or int option is a slider, as FOV
is, where it was a button stepping through every value. A float takes the
nearest step from its minimum (the last slot its maximum), an int whole
numbers, rounded to the f32 the pack's override gets so a slider back in the
middle is the default exactly. The value is saved, and the pack rebuilt, once
when the slider is let go, and only if it changed. Shift-click puts it back
to its default; Tab, Enter and the arrows work it as they do vanilla's
sliders, a step at a time and stopping at the ends. Bool and choice options
stay buttons.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The stage wrote alpha 1, so with a pack's material no light source on terrain shone.
It now writes the mark as fs_solid does, from the sprite before the pack's material.
Its emission also read a tier that shines all over as the top tier.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PRs before this one in the series, merged in order with their conflicts resolved,
so this branch merges cleanly once #5681 has.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PRs before this one in the series, merged in order with their conflicts resolved,
so this branch merges cleanly once #5663 has.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PRs before this one in the series, merged in order with their conflicts resolved,
so this branch merges cleanly once #5652 has.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PRs before this one in the series, merged in order with their conflicts resolved,
so this branch merges cleanly once #5658 has.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Block light has a brightness but no colour, so a pack can't make a soul torch blue. Section meshes now
list their light sources, and a 3D grid around the camera holds the colour reaching each cell, read
through block_light_color. Block light keeps its own brightness, which walls stop, so the grid only
tints it and needs no occlusion of its own.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EBqm1v5zTsDGwuZF6XKFjL
Noise, lookup tables and the like had to be computed in WGSL. A pack can now ship up to eight PNGs,
which the check decodes and every stage reads as <id> and <id>_sampler.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EBqm1v5zTsDGwuZF6XKFjL
A native pack had no way to light or tint weather, so vanilla's streaks stood out against a pack's
own lighting. Horizon still places and animates the streaks; the pack only returns their colour.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EBqm1v5zTsDGwuZF6XKFjL
A pack with dozens of options needs them in categories. The first page is the one the button opens,
"page:<id>" opens another, "" leaves a slot empty and columns = 1 gives full-width buttons. Every page
has to be reached from the first and every option has to be on a page, or the check refuses the pack.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EBqm1v5zTsDGwuZF6XKFjL
A Horizon pack declares options, but they stayed at their defaults: the player had no way to set them.
The picked pack now gets the same Shader Options... button as a shaders/ pack, and its values live in
shaderpacks/<pack>.txt, the file that kind already uses. A saved value counts as a change to the pack,
so it reloads with it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EBqm1v5zTsDGwuZF6XKFjL
A pack treats hundreds of kinds of surface differently, where [[tags]] hold 32 sets. Each sprite takes
the id of the first [[materials]] entry that names it, as MaterialInput.material, through the same
generated switch as the tags. [shadow] solid_materials draws those ids into the map without their
cutouts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EBqm1v5zTsDGwuZF6XKFjL
The depth range now reaches past the build height below the camera and shadow_position clamps z,
so a point past the far end stays lit, the blank map included. The light's box culls the native
lists instead of a section radius that lost casters at low sun. The native camera's snap is
euclidean, the resolution is clamped once, and the distortion and the camera each live in one
place. The generated reference lists the shadow helpers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EBqm1v5zTsDGwuZF6XKFjL
Hovering an option, a screen or the profile button shows what the pack's lang file says of it
(option.NAME.comment, screen.NAME.comment, profile.comment). Shift-click puts one option
back at the pack's default. A label wider than its button shortens the option's name, never
its value, and the whole label shows on hover.
The options a pack lists in sliders are sliders, each step one of the option's values. const
bool declarations (const bool shadowHardwareFiltering = true;) are switches too; as they are
as often the pack's own settings, they show where a screen names them, not with *.
The options a pack declares (switches, values with their lists, consts) on the screens
shaders.properties lays out, with the names its lang files give them, its profiles, and
Reset. Choices are saved to shaderpacks/<pack>.txt and applied to the pack's sources as
they are read; leaving the page loads the pack again with them.
Packs declare [[tags]] of block sprites (glass, say) and read them as
MaterialInput.tags; the frame gains precipitation, temperature, downfall
and wetness (rain smoothed as the shaders/ format's).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XnU6QS9x9HatX1QRXMqxeb
A pack's `fn material(input: MaterialInput) -> Surface` now gives the lit
colour of every terrain surface: sections and distant tiles, solid,
cutout and translucent, in both the instanced and the flat draws. Terrain
keeps Horizon's meshes, culling and draw lists; only its pipelines change.
Their shader is the pack's stage, a prefixed copy of terrain.wgsl's
terrain section, and entries that hand the pack the texture, the vertex
tint, the light levels and the lightmap's colour apart, then apply the
alpha test and fog as `fs_solid` and `fs_translucent` do.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A pack's `sky` function gets vanilla's colour along each view ray and draws
where the vanilla sky dome draws, under the sun, moon, stars and clouds. The
pipeline's shader is the pack's checked stage (`CheckedStage::source`, new)
followed by a copy of terrain.wgsl's sky with every name prefixed
`horizon_sky_`, so none can meet a pack's; terrain.wgsl's `fs_sky` now calls
`sky_along_ray`, the same code as before.
A running pack is one `NativePack`: the frame every stage reads (written once
a frame), its sky and post stages and its pass timer. In a frame F3 times, the
sky draws in a pass of its own so the overlay can show its time; otherwise it
stays in the world's pass.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Mods page gets a fourth kind, Shader packs, which searches Horizon's
registry and installs a `.hshader` into `shaderpacks/` once
`index::check_file` has run the game's own `horizon_shader_api::check`.
Modrinth and CurseForge answer that tab with a pointer to the registry:
their shader packs are the shaders/ format and are not offered.
The sample index lists a shader pack (`glow`, made with
`horizon-shader new` and `pack`), so the registry build, check_file and
the launcher's install are tested on a real file. A file of the same
name the registry didn't put in place is no longer called a mod.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The page lists the packs in shaderpacks/: Horizon's own, marked (Horizon) and
named by their manifest, then packs in the shaders/ format. One runs at a
time: clicking a pack picks it, clicking the picked one turns it off, and
Open Pack Folder opens the folder. The pick is saved in horizon-graphics.txt
under a new key (pickedShaderPack), so the shaderPack value older versions
saved stays ignored. A new pick drops the running pack and loads the new one
in the next frame; HORIZON_SHADER_PACK still wins, for development.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
While the F3 overlay is open, the running pack's passes are timed on the GPU,
a shaders/ pack's or a native pack's, and the overlay lists the pack's total
and its costliest passes (the median of the last 15 timed frames). The timer
never waits: a timed frame's stamps are resolved once the GPU has finished it
and read back once mapped, then the next frame is timed. A native pack's first
pass counts from a mark that ends with the world's draws, so it does not carry
the time it waited for them. HORIZON_SHADER_PACK_TIMING still logs the medians.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A native pack named by HORIZON_SHADER_PACK (a folder with horizon-shaders.toml
or a .hshader in shaderpacks/) is checked, then its post passes run over the
world's own target, the one a shaders/ pack reads: no second target and no
extra pass, and without a pack the frame only tests one Option. The pack is
looked at twice a second; a saved file is checked and rebuilt in place, and a
version that fails is refused in the chat while the last good one keeps
drawing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The SDK's tool, in horizon-shader-api: `horizon-shader new <dir> --template
post|sky|material` makes a pack that passes the check, `check <pack>...
[--json]` runs the check the game, the launcher and the registry run and
prints each stage's cost and the pack's SHA-256 or every problem at its
file:line:column, and `pack <dir>` checks then writes the reproducible
.hshader. Golden Hour, the example pack, warms the sky around a low sun and
adds a soft glow and a colour grade, with five options. docs/shaders.md is the
authors' guide.
Co-Authored-By: Claude Opus 5.5 <[email protected]>