Minecraft comparison captures¶
tools/goanna-render minecraft captures Minecraft Java and Goanna from the
same local Minecraft server.
BridgeTest translates the connection
into the ordinary Luanti protocol for Goanna. --native also captures the
native Luanti client through the same bridge, sequentially.
This gives shader investigations a shared world, textures, camera position and field of view. It does not require a Mineclonia world import. Importing existing worlds and a block-state fidelity backlog remain separate work.
Pinned environment¶
| Component | Version or revision |
|---|---|
| Minecraft Java client and server | 26.2, protocol 776 |
| Java | 25 |
| Fabric Loader | 0.19.5 |
| Iris | 1.11.4+26.2-fabric |
| Sodium | mc26.2-0.9.2-fabric |
| BridgeTest | 093807327ea75fbaff91ee3f5dc56c83dbe2efdd |
| Rust toolchain | nightly-2026-10-14 |
| minecraft-data | 46b78398b6f351958e02fbd266424f0ee0ab138b |
The installer downloads the official client, server, libraries and assets,
plus the pinned Fabric, Iris and Sodium components. It verifies published
checksums where supplied and records downloaded library hashes. Generated
files and downloaded game assets stay in ignored build/minecraft/.
The bridge build uses a separate checkout under build/minecraft/sources/.
Its locked minecraft-data-rs dependency supplies old item data. Without
an alias from minecraft:scute to minecraft:turtle_scute, the bridge panics
while preparing definitions. The helper applies that alias to the build
copy, records it in bridge-build.json, and leaves the owner's clone alone.
This fixes the observed join failure; it does not establish modern inventory
or item-ID compatibility.
The build also replaces three placeholder node base colours, RGB
100, 70, 85, with white. Node colour multiplies the texture independently
of explicit tile and biome tints. The placeholders made both Luanti clients
darker and purple. Explicit tints and underwater post-effect colours remain
intact. The build manifest records the corrected base colour.
BridgeTest reserves node ID 120 for bridgetest:glowing_air. The build adds
the ordinary node group goanna_sky_mirror_x to that definition. Goanna
checks its name and group after content becomes ready, then reflects the
sun and moon across X to match the bridge's world transform. Unmarked
servers keep their original orbit. This uses normal node metadata over the
unmodified Luanti protocol; the Luanti engine is not patched. Native Luanti
does not interpret this group, so its celestial direction remains different.
During a capture the service sets GOANNA_COMPARISON_CAMERA=1. This grants
the native Luanti client fly and noclip, so it can hold the spectator
camera position. All comparison players use spectator mode in the local
comparison world. These privileges are recorded
in the build manifest and belong to this test installation.
It retains Minecraft server teleports but disables periodic position
reconciliation from Azalea's simulated player, which otherwise pulls the
native camera towards the ground even while the world is frozen. This bridge
mode is a camera instrument for the local stage. Without that environment
variable the bridge retains its upstream privileges and reconciliation.
The flag also disables clock extrapolation and advertises zero time speed,
matching the comparison world's frozen clock. Ordinary launches keep the
bridge's upstream clock behaviour.
Setup¶
Use a Java 25 JDK, including javac, and Rust installed through rustup. The
bridge also needs the normal native Rust build dependencies, including a C
compiler, OpenSSL development libraries and pkg-config.
python tools/minecraft/setup.py --java /path/to/jdk-25/bin/java --accept-eula
python tools/minecraft/build_helper.py
rustup toolchain install nightly-2026-10-14 --profile minimal
python tools/minecraft/build_bridge.py
Pass --accept-eula only after accepting the
Minecraft EULA. The isolated server uses
local test identities, binds to 127.0.0.1:25585, and disables online
authentication. BridgeTest binds to 127.0.0.1:30985. The launcher does not
read the owner's Minecraft account tokens or alter their launcher profiles.
All three setup helpers accept --root DIR. build_bridge.py also accepts
--cargo PATH and --jobs N. The installed JDK for the initial run is at
build/minecraft/jdk/jdk-25.0.4.1+1/.
Capture¶
The output directory must be empty. Pass --out DIR, or copy the job and
change out, for each run. Add --native for the native Luanti reference,
or use --only minecraft, --only goanna or --only vanilla to capture one
client. The native client
uses the existing Flatpak launcher. Its poses must share one FOV.
The service starts its own local server, builds a small calibration stage
in the dedicated comparison world, freezes world ticks, and runs
one GPU client at a time. It takes the GPU lock and checks for other clients
throughout the run. The clients stay inside headless gamescope. Minecraft's
small Fabric helper handles camera positioning and screenshots inside its
own client; Goanna uses its existing control channel. The native client is
framed by server teleport commands and photographed through gamescope.
Each Goanna run has a fresh user directory and disables its terrain store,
so cached terrain from earlier bridge definitions cannot enter a comparison.
The native client retains its HUD, including bridge inventory warnings.
time_ticks selects the Minecraft clock phase, from 0 to 23999. Its default
is 6000, noon; dusk is 12000 and midnight is 18000. The stage disables clock
advancement before briefly unfreezing to deliver camera and clock packets.
Minecraft's helper records the actual clock and sun angle; Goanna records
its sky and shader lighting state. Mismatched capture clocks are rejected.
The stage contains coloured pillars, stone, wood, glass, leaves, water, an emissive node, an oriented log, stairs and a slab. The stage commands clear and rebuild their area in this dedicated world. Do not point this server installation at an existing world that you want to preserve.
Camera pos is the Minecraft eye position in block units. look_at, or
Minecraft yaw and pitch, sets its direction. fov is the vertical FOV.
BridgeTest mirrors X and offsets cube centres by half a block; Goanna also
mirrors Z when moving into Godot coordinates. The service applies both
transforms. size sets image dimensions and settle_seconds records a fixed
wait before capture, rather than claiming streaming has completed.
{
"out": "build/minecraft/my-comparison",
"size": [1280, 720],
"settle_seconds": 20,
"time_ticks": 6000,
"shader_pack": "/path/to/shaderpack.zip",
"shader_options": {"SSAO_ENABLED": false},
"resource_pack": "/path/to/texturepack.zip",
"poses": [
{"name": "calibration", "pos": [8.5, 106, 24.5],
"look_at": [8.5, 101.5, 6.5], "fov": 70}
]
}
Omit the pack fields for a default-texture, shader-free baseline. Packs can be directories or zip archives. Shader options use the pack's actual option names. The profile copies one shader source and the same explicit options into both Iris paths. The native Luanti client supplies an engine reference; it does not run the Minecraft shader pack.
--build /path/to/checkout selects the Goanna build and records that
checkout's commit and dirty state. It needs a matching compiled extension.
The default remains the main checkout.
Texture profiles overlay the same Minecraft texture names into the bridge's
media and Goanna's texture override path. Normal and specular maps are also
copied. Resource packs need pack.mcmeta at their root. Packs which alter
models/ or blockstates/ are rejected because BridgeTest's geometry mapping
is built into its binary. High resolution animation, custom models and
resource pack extensions have not been verified. The initial texture test
uses ordinary 16-pixel textures.
The comparison profile resets Minecraft to four mipmap levels and texture
filtering NONE. Imported shader-pack terrain samples nearest texels with
blended mipmap levels and no anisotropy, matching this baseline. Native
Goanna terrain retains its anisotropic sampler. The Minecraft sidecar records
its live filtering option, mipmap count and block-atlas sampler. Anisotropic
Minecraft profiles and exact mipmap generation equivalence are not supported
by this baseline.
Each run writes PNGs, frame JSON sidecars, server and bridge logs,
result.json and an index.html gallery. The result records component and
pack hashes, options, camera transforms, observed client state, shader
translation reports, the Goanna commit and whether its checkout was dirty.
Disconnected Minecraft captures and Goanna captures with no meshed terrain
are rejected. Failed runs record ok: false and an error. The service stops
its own processes on success, failure or interruption.
Qualify the Minecraft reference¶
An active shader flag and a small image difference establish that clients agree with a shader's output. They do not establish that the reference output is correct. Before treating appearance as a calibration target, capture shader-free noon and midnight controls with the same camera and check the recorded clocks. Inspect the pack's source, configuration and advertised game versions when the shader result looks implausible.
Keep diagnostic edits in separate pack copies, record the exact change and source hashes, and use the same copy in both clients. A diagnostic can isolate a broken input without qualifying the whole third-party pack. Retain the original captures as evidence and label suspect references explicitly in comparison galleries and reports.
Lighting input probe¶
The authored diagnostic pack writes four inputs before lighting or post-processing: raw texture RGB, vertex colour, light coordinates and encoded view-space sun direction. Its sun path rotation is -40 degrees, matching the Eclipse pack used in the initial comparison. The same pack source runs in both clients.
tools/goanna-render minecraft tools/minecraft/light-inputs.json
python tools/minecraft/light_metrics.py build/minecraft/light-inputs \
--inputs --out build/minecraft/light-inputs/metrics.json
Minecraft's upper row shows texture and vertex colour; its lower row shows light coordinates and sun direction. Goanna's current screen-space UV convention swaps those rows. The measurement script pairs the same buffers explicitly. This is a recorded compatibility difference, not an input colour correction.
The geometry programs retain explicit biome tints. They disable old face
lighting, so a neutral block should have white vertex colour. Light channels
encode block and sky coordinates directly. Sun RGB encodes its normalised
view-space direction as direction * 0.5 + 0.5.
For Eclipse captures, omit --inputs to measure the stage's floor, wood,
red, blue, gold and glass surfaces, the sky and the wood's right side. The
side sample detects opposite sunlight directions which front-facing samples
can miss.
The script requires Pillow and the standard 1280x720 calibration camera.
The input probe samples both near and distant floor albedo. RGB standard
deviation records local texture contrast, so equal mean colours cannot hide
an overly sharp distant texture.
It records mean RGB differences and pixel RGB mean absolute error without
altering screenshots. Mean colour agreement in these areas does not establish
whole-frame equivalence. Animated gold and emissive effects, geometry edges,
sky, water and foliage need separate inspection.
Goanna applies a pack's sunPathRotation to terrain, shadows, sky and
screen-space uniforms together. sunAngle follows the celestial orbit;
worldTime retains the server's clock. Luanti's orbit curve approximates
Minecraft's curve between the matched noon and midnight positions.
Observed runs¶
On 14 October 2026, Minecraft Java 26.2's unmodified dedicated server served the calibration world to Minecraft and Goanna through the pinned BridgeTest build. Goanna used the pinned Luanti 5.17.0 client code and Godot 4.5.1 on the GPU in headless gamescope. This was a live Minecraft world, with no Luanti game installed behind the proxy.
The default-texture stage aligned visually between the two cameras. With Eclipse loaded from the same archive, Minecraft reported an active Iris shader pack, and Goanna reported translated terrain and water programs plus three compiled post-processing passes. Goanna drew substantially darker terrain; sky, water, foliage and animated emissive textures differed. These captures are evidence for shader debugging, not a claim of renderer parity.
The final shader-free texture gallery is in build/minecraft/texture-final/.
Minecraft, native Luanti 5.17.0 and Goanna showed the calibration stage with
the same stone-brick, diamond and birch texture substitutions. Native Luanti
held the camera with the comparison flag enabled. Its HUD and inventory
warning remain visible; its colour and lighting differ from Minecraft's.
Goanna's terrain store had to be disabled to keep earlier bridge terrain
out of the frame.
The Eclipse gallery is in build/minecraft/eclipse-final/; the local repeat
job is build/minecraft/eclipse-job.json. Capture records include the dirty
checkout used for each run. Headless frame rates are relative observations
only. Software rendering, normal play, Microsoft authentication,
inventory equivalence, entities and arbitrary existing worlds were not
tested by this workflow.
Lighting corrections¶
Further live captures on the same server and GPU, using Godot 4.5.1 and the
dirty checkout based on a83278e1 and 39fc90f7, isolated the bridge's base
colour and the shader's sun direction. The dusk input probe measured:
| Input | Maximum mean RGB channel difference, out of 255 |
|---|---|
| Raw stone texture | 0.50 |
| Neutral vertex colour | 0.00 |
| Block and sky light coordinates | 0.06 |
| Encoded view-space sun direction | 1.00 |
These corrections remove the broad darkening and purple tint. Unmodified Eclipse, with its default effects enabled, gave the following maximum mean channel differences over the floor, wood, red, blue and wood-side samples:
| Clock phase | Maximum sampled difference |
|---|---|
| Noon | 6.31 |
| Dusk | 2.70 |
| Midnight | 1.16 |
At noon, disabling SSAO_ENABLED and SOFT_SHADOWS in both clients reduced
the floor's maximum mean channel difference from 6.31 to 1.68. Other
surface samples differed by up to 4.59 with those options disabled, so this
does not establish full lighting equivalence. The dusk side sample confirms
that sunlight now reaches the same side of the wood in both clients.
Both clients' recorded clock phases matched the job exactly.
The gold sample differed by up to 9.17 at dusk. Emissive animation and shader animation timers are not synchronised by freezing world ticks. Sky, glass, water, foliage, ambient occlusion and shadow details remain visibly different. The input probe's row orientation also remains different.
The galleries and numerical reports are under
build/minecraft/lighting-parity/: inputs-dusk-fixed/, final-day/,
final-dusk/, final-night/ and final-no-occlusion/. Each directory has
its original screenshots, capture sidecars and metrics.json.
The shader contracts, clock and tint checks, native light and shadow checks,
and strict documentation build passed. A joining-time crash during an
earlier capture also led to guarding node-name queries until content is
ready; its local UDP regression test and subsequent captures passed.
Further captures based on 99827bb7 identified an unbound cloudTex
sampler in Eclipse's basic sky program. The diagnostic copy sampled that
texture directly: Minecraft's resulting sky was near white, while Goanna's
was black. GLSL initialises unassigned samplers to texture unit zero
(GLSL specification).
The observed Iris basic sky path binds white there. Goanna now uses white
for otherwise unbound 2D samplers on that basic sky path, including samplers
passed through helper functions. Assigned colortex bindings remain intact.
Custom sky texture bindings and non-2D fallback behaviour were not verified.
With the original Eclipse pack restored, the sampled sky's maximum mean
channel difference fell to 4.94. Minecraft's cloud geometry is still absent
from Goanna's pack sky. Blended glass had been using Goanna's native material
instead of the pack's translucent program. Routing blended glass and ice
through that program, with their own block IDs, reduced the glass sample's
maximum mean channel difference from 77.16 to 21.47. Glass remains different;
ice was not present in the live stage. The latest gallery is
build/minecraft/lighting-parity/sky-glass-corrected/, and the combined
interactive comparison is build/minecraft/lighting-parity/index.html.
Sky sampler regression checks and shader contracts passed. The earlier
lighting and joining changes were also rebuilt from the clean committed
checkout, reusing unchanged dependency objects after source verification;
the clean checkout's shader and joining regressions passed.
Audit the white sky reference¶
The earlier white-sky match was agreement with a suspect reference, not
evidence of a correct sky. On 14 October 2026, the captured Eclipse source
was verified against the author's SHA-512-checked
Eclipse 1.0 release.
Both source trees had fingerprint
eadf7fcb8c856e478b7dd4f19f77227f6c06229686f3ce9d918db52064b4f65d.
That release advertises support through Minecraft 1.21.8, without 26.2 in
its compatibility list.
Its basic sky shader mixes in cloudTex at 80% of the sample's alpha.
The published archive contains no shaders.properties binding for that
sampler or definitions for its cloud animation uniforms. The observed
white sample therefore washes out the sky through day and night on this
capture stack. Goanna's white fallback reproduces the observed Iris
binding; that compatibility behaviour does not qualify Eclipse's sky
appearance as a calibration target.
Live shader-free controls on the same unmodified Minecraft Java 26.2 dedicated server produced a blue daytime sky and a dark midnight sky. A disposable Eclipse copy omitted only this line:
Both clients then produced a blue day and a darker blue night, with no exposure change. Terrain lighting, the sun rotation and post-processing remained intact. A fixed near-horizon sample measured these Minecraft RGB means, out of 255:
| Reference | Noon | Midnight |
|---|---|---|
| Shader-free control | 178, 206, 254 | 9, 11, 17 |
| Published Eclipse 1.0 | 241, 246, 250 | 215, 216, 219 |
| Diagnostic without cloud blend | 200, 232, 250 | 70, 84, 104 |
Goanna's diagnostic sample was 201, 235, 255 at noon and 74, 90, 111
at midnight. The earlier opaque surface measurements were unchanged by
removing this sky blend. The tint, light-coordinate, clock and celestial
direction probes remain evidence for those inputs, independently of the
suspect sky reference.
These new captures used the dirty checkout based on e219204b, Goanna's
Luanti 5.17.0 core, BridgeTest protocol 52, no Luanti game, Godot 4.5.1 and
RTX 3090 in headless gamescope. Both clocks matched the requested phase.
The side-by-side audit, source provenance, exact diagnostic change and
measurement report are in build/minecraft/sky-reference-audit/.
The earlier comparison viewer now labels original Eclipse captures as
suspect and offers the explicitly modified diagnostic views.
This isolates the washout on the 26.2 stack. It is not an official Eclipse repair or proof of correct rendering for the whole pack. An Eclipse run on its advertised supported game version and an alternative supported third-party shader reference were not tested. Foliage, glass, cloud geometry, ambient occlusion, shadows and animation remain open comparisons.
Run the camera, capture rejection and profile isolation checks with:
Terrain filtering and colour controls¶
On 15 October 2026, paired raw-texture captures identified anisotropy in
Goanna's imported terrain sampler as a source of excess distant detail.
Minecraft reported filtering NONE, four mipmap levels and a nearest
block-atlas sampler with maximum anisotropy 1. Removing anisotropy from the
imported albedo array reduced distant floor pixel error from 4.52 to 2.39 RGB
levels. Raw texture contrast, measured as standard deviation, changed from
11.33 to 8.50 against Minecraft's 8.02. The near-floor input was unchanged.
Both raw floor inputs remained neutral grey; the residual distant mean
albedo difference was 0.75 levels. Mipmap generation differs between the
engines and was not changed.
The lit comparison used the same diagnostic Eclipse copy described above, with only its suspect unbound cloud blend omitted. Matching terrain filtering did not remove the sampled floor's blue colour discrepancy. Disabling SSAO alone left the floor difference at 6.31 levels but reduced the glass sample's maximum mean channel difference from 21.57 to 2.65. Disabling soft shadows alone reduced the floor difference to 1.68; glass still differed by 18.27. These controls isolate the dominant floor error to soft-shadow sampling and the dominant glass error to the AO path. They do not establish the underlying causes or justify tint, exposure or shadow-strength adjustments.
Runs used the dirty checkout based on a9044c80, the unmodified Minecraft
Java 26.2 dedicated server, BridgeTest protocol 52, no Luanti game, Goanna's
Luanti 5.17.0 core, Godot 4.5.1 and RTX 3090 in headless gamescope. Captured
clocks were 6000. The captures, filtering metadata, input metrics and
interactive before/after gallery are under build/minecraft/filtering-audit/.
Foliage transparency, mipmap alpha coverage, soft-shadow depth and noise,
glass AO inputs and baseline cloud geometry remain to be investigated.