promotional bannermobile promotional banner

Vitrail Shaders

OptiFine-format shader packs, on Minecraft's native Vulkan renderer
Back to Files

v0.9.0-beta (Neo/Fabric)

File namevitrail-0.9.0-beta+mc26.2.jar
Uploader
avpbynfavpbynf
Uploaded
Sep 1, 2026
Downloads
102
Size
1.4 MB
Mod Loaders
FabricNeoForge
File ID
8783013
Type
B
Beta
Supported game versions
  • 26.2

Curse Maven Snippet

Fabric

modImplementation "curse.maven:vitrail-shaders-1649385:8783013"

NeoForge

implementation "curse.maven:vitrail-shaders-1649385:8783013"

Learn more about Curse Maven

What's new

Added

  • A Cache Cap slider on the video settings page, how much compiled-shader disk this engine may keep, 128 to 2048 mebibytes in steps of 128. 512 MiB is the old hardcoded ceiling and the default. Moving it applies at once, with no pack reload: lowering may drop unused cached shaders. Written in vitrail/module-cache-ceiling.txt.

  • A Shadow Map Scale slider under Video Settings, on the mod's page beside Max Shadow Distance. The shadow map is drawn at the chosen fraction of the resolution the pack asked for, 25 to 100 percent, and the setting outlives whichever pack is chosen. Moving it reloads the pack, which is what lets the pack be told the smaller number instead of being left to work against a map it cannot see.

    It is a setting of its own rather than something the FSR Render Scale takes along with it, because of what it does to the picture. The pack works out its shadow blur, its shadow bias and where it reads the map from the size it was given, so a smaller map is a less defined shadow, softer where the pack smooths its own and coarser where it does not, and an image the pack's author never saw. That is a trade worth offering and not worth making on somebody's behalf, so at 100 percent, which is where it starts, the pack gets exactly the map it asked for and nothing of the setting runs. The engine says at load when the setting is in force.

    What the render scale reaches and what it leaves alone is now written down, in docs/render-scale.md.

  • A switch that fills the shadow map from a box around you rather than the tight silhouette. An empty file vitrail/box-shadow-cull in the game folder, or -Dvitrail.boxShadowCull=true. The silhouette stays the default, which is what other loaders draw. The box was tried as the default, to stop leaf blocks popping at the sun's edge as you move, and measuring it is why it did not stay: on one wooded scene it drew 875 sections where the silhouette draws 322, and the frame ran twelve to twenty-eight percent slower depending on how much stood around. It also stops bounding anything at all once Shadow Distance reaches your render distance, which is where the slider sits at its maximum.

    What the box covers up is a defect of this engine and the switch is not its fix: leaves can go a frame without their shadow while you walk, if you run a mod that narrows what the game considers visible. That is being fixed at its cause instead.

  • A switch that hands every sine and cosine a pack writes back to the graphics driver. An empty file vitrail/driver-trig in the game folder, or -Dvitrail.driverTrig=true. They are normally replaced at load with a helper that keeps its accuracy over a whole world coordinate, where a driver's own can shed the low bits and show as shimmer. The switch exists so the two can be compared in one world rather than across two builds, and the log says which of them a pack load ended up with either way. A pack that defines its own sine keeps it in both states.

Changed

  • Compute shaders now hit the compiled-module cache on a pack reload. They used to miss every time because the disk key hashed the load number the debug name carries. That number is out of the key. Computes are compiled by this engine, not by the game's shader compiler; what is kept is the compiled module and its bind table, the same files graphics shaders already write under vitrail/modules. Vulkan pipelines are built each load as before.

  • F3 names the pack the way Iris does. The profile line is the scanned name or Custom, with how many options sit outside it, and the shadow line is Sodium's C: a/b D: d without this engine's own cull dialect.

  • The compiling overlay no longer covers F3. While the debug screen is open, "Compiling shaders..." rides the Vitrail F3 line instead of the corner. Close F3 and the corner overlay is as it was.

  • Video-settings labels tell the truth about reload. Titles are shorter so they fit the row. Each tooltip says whether the change applies at once, at the next frame, or reloads the pack.

  • Loading a pack a second time no longer compiles its shaders again. The compiled module and the table of what it binds are kept under vitrail/modules in the game folder and read back when the same shader comes round again, so a warm load does no compiling and no inspecting at all. Editing a shader or moving a pack setting changes what is asked for, and so does updating the mod, the game or the loader, and anything that has changed is built from scratch as before. Each release keeps its own folder and takes the older ones away with it, the whole thing is capped, and the log says how many shaders came off the disk, how many were built and how much is stored.

    It removes work rather than time. Measured on one machine: a warm load compiles none of the two hundred odd shaders a cold one compiles, and the wait before the pack draws is the same to the second. What a pack load really costs sits somewhere neither this nor the log line is looking.

  • Loading a pack again no longer rewrites its shaders from scratch. Turning a pack's GLSL into the dialect this backend speaks is one of the three things a pack load pays for, and it is the same answer every time the same pack comes back. What it came to is kept under vitrail/translations in the game folder and read back instead. Editing a shader, moving a pack setting, changing the shadow map scale, updating the mod or the game, or switching one of the mod's own measurement switches all change what is asked for, and anything that has changed is rewritten as before. Each version keeps its own folder and takes the older ones away with it, the whole thing is capped at a quarter of a gigabyte, and the log says how many programs came off the disk and how many were rewritten. It removes work rather than time: the wait before a pack draws is the same, and what changes is that none of it is spent here.

  • A shadow lookup a pack asks the hardware to compare is now compared by the hardware. A pack declaring sampler2DShadow used to have that comparison rebuilt in shader arithmetic on every tap, a dozen instructions where a comparison sampler pays one, and a shadow's blur loop makes many taps per pixel. The comparison now rides the sampler, the pair Iris binds when a pack asks for its hardware shadow filtering, which every pack that declares the type does; the picture it computes is the same blend of the same four texels. For a machine where the sampler road is suspected of a wrong image, a file vitrail/soft-shadow-compare in the game directory, or -Dvitrail.softShadowCompare=true, puts the arithmetic back in one launch, and removing it again takes a pack reload.

  • A patch of this mod that stops fitting the game now refuses to start it, instead of drawing a wrong picture. Those patches used to be dropped without a word when a game or Sodium update moved what they attach to, and what reached the screen was an effect quietly missing or a surface lit by the wrong program, with nothing in the log pointing at it. The failure now names itself at launch. The one exception is the line this mod adds to the F3 overlay, which is allowed to go missing because nothing on screen depends on it.

  • A texture's chain of shrunken copies is rebuilt only when its base has changed. Packs that blur or expose through those copies asked for the whole chain to be rebuilt before every pass that reads one, even when nothing had touched the image in between; two readers in a row now pay one rebuild instead of two. The copies read are the same ones. Not measured, so this says work removed and not frames gained.

  • Two pieces of per-frame work on the graphics card are gone, and the picture is the same. The far terrain's own depth image is emptied by the pass that draws into it rather than by a command of its own, which also spares the full stop of the card that such a command carries. The voxel volumes that follow the camera now copy only the part of themselves that survives the move, where they used to copy the whole volume. Neither has been measured, so this says work removed and not frames gained.

  • A handful of values handed to shaders are worked out once a frame instead of once for every program that asks for them. Where the sun and the moon are, which way is up, the End's flash, and the two matrices a pack multiplies its vertices by were all rebuilt from scratch each time a shader asked, which for a large pack is dozens of times a frame out of numbers that had not moved in between. They are kept and reused until something they are built from actually changes. The values handed over are the same ones, to the bit, and this has not been measured either, so again it is work removed rather than frames gained.

  • The same picture with less repeated work inside the frame. A pack's geometry program re-bound every texture it declares for every chunk region, mob piece and particle batch it drew, where only the two to four that follow the image in hand can change inside one pass; the rest are now written once, when the pass opens. Beside it: the far terrain's sections are collected into a list sized from the count Distant Horizons gives rather than grown into one, and handed on without a copy; a vertex format is searched for this engine's own elements only until the first one it has not got; and a pass is asked for its name only once everything cheaper about it has already matched. Whether the frame rate moves is a machine's to measure.

Fixed

  • AstraLex night skies are round again. A pack that interpolates a 3x3 matrix between vertex and fragment, AstraLex's planet among them, was stretched into an oval: this backend numbers varyings by count, and a matrix occupies several slots. Each matrix is now split into one vector per column before compile. Complementary never declared one, so it did not show the oval.

  • Turning Distant Horizons on reloads Complementary and then draws it. The pack used to be reread with Distant Horizons present and then refused, because four uniforms stayed outside a block, so the world dropped to vanilla. The machine symbols are now installed before the pack is opened, so those uniforms enter the block and the reload draws the pack. The toggle still reloads; it does not keep the pack on without one.

  • The button that opens a pack's settings is no longer dead until the pack has been loaded once. It was live only while a pack was already drawing, so the first pack anybody picks on a fresh install could not be configured at all: the only way in was to load it at whatever profile its author shipped, which on a small machine is the one launch that hurts. It is now live for the pack the list has selected, and pressing it reads that pack, which is parsing and no work on the graphics card, and puts its settings on screen while the loaded pack goes on drawing. Setting a heavy pack to its low profile before ever loading it now costs one load instead of two. A pack that lays no settings out says so instead of opening an empty page.

  • Breaking a block no longer paints flat black cracks over it. The overlay that spreads as a block is mined was left to the game, and it multiplies its texture onto what is already drawn; it was landing on an empty layer instead of on the picture, so every crack came out opaque black from the first stage rather than darkening the face as it broke. It is drawn through the pack now, on gbuffers_damagedblock and its fallback onto the terrain, which is what a pack expects to be asked for.

  • A pack written with the old shadow lookups could be translated wrong, without a word. Wrapping those lookups shifted the translator's own note of which words are macro names, which could rename one of them or leave a local variable reading a global value instead. Nothing in the tested packs reached it.

  • A pack that changes with how humid a biome is no longer sees a desert everywhere. The rainfall value handed to shaders was always nought, so puddles, wetness and fog that scale with humidity stayed at their driest in a swamp and a jungle alike.

  • Changing shaderpack without restarting no longer leaves the buffers of the pack before it in play. The names a pack gives its bufferObject blocks were remembered for the whole session rather than for the pack that wrote them, so a pack loaded after another could have a block bound to a buffer the earlier one had declared, at whatever size and contents that one asked for, or keep a program running against a block nothing binds at all. Complementary Ultra with world-space reflections on is the pack that declares such a block, and quitting the game between two packs was the only thing that cleared it.

  • A shadow compute pass that leaves its size to the engine now covers the screen. A pack can say how much work such a program does in several ways, and only the one where it writes the count out itself was read. A program using any other ran as a single small tile: it filled a few hundred texels, and everything past them kept whatever the frame before had left, so the effect showed up in one square at the corner and was stale over the rest of the picture. Every pack tested here writes the count out, so only packs outside that set could see it. Two smaller things come with it: a pack asking for no work at all, which is how one of those forms switches a pass off, now dispatches nothing rather than one tile, and a program whose size cannot be read at all is left out with a line in the log naming it, rather than guessed at.

  • The log says why a pack is drawing the world with the game's own terrain shader. When nothing of the pack reaches the chunk mesh, three quite different things can have happened: the pack was read and asks for none of the extra vertex data, or its load never got as far as its chunk programs, or the mesh was built before the pack had been read. All three used to share one line that named none of them, and the third only showed itself a world later, as an error about two lists of attributes that said nothing about the order that made them differ. Each now says which one it was, where it happened.

  • The game no longer crashes when AsyncParticles draws its GPU-accelerated particles under a shaderpack. AsyncParticles can move its particles to the GPU and record their draws itself, into the very pass this mod had opened over the pack's colour targets, with pipelines built for a single target: the frame died on a colour attachment count mismatch a few seconds into the world. Those draws now take the pack's own particle programs, rebuilt over AsyncParticles' vertex layout, which is what Iris draws them with as well.