Community listing page, reviews here may not be monitored by the author.
OptiFabric Reforged
No reviews yet
OptiFine on Fabric, with Fabric API loaded alongside.
Community voices
Reviews
No reviews yet. Be the first to review this project!
Get it on
Available Platforms
About
Project Details
For authors
Embed Badge
If you're the author of this project, you can embed a live badge anywhere that supports HTML or Markdown. It updates automatically whenever ratings change.
Use HTML for any page that supports it, or Markdown for README files and Markdown-based descriptions.
Identifiers
Platform IDs
Resources
External Links
About
Description
OptiFabric — OptiFine on Fabric
A Fabric mod that brings OptiFine to Fabric. Put OptiFabric and your own OptiFine jar into mods/ and it takes care of the rest — no jar patching by hand, no OptiFine installer to run, no Forge.
ℹ️ OptiFine is not bundled or redistributed. Get the build that matches your Minecraft version from the official site — 1.20.6 and 26.1.2 have preview builds only so far.
OptiFabric is developed as one project per release line; the jars are not interchangeable, and each one carries the Minecraft version in its file name:
| Line | Minecraft | Jar | Loader | Java |
|---|---|---|---|---|
| 1.20.6 | 1.20.6 | <button class="_fileMention_177e0_288" title="OptiFabric-1.0.0+mc1.20.6.jar" type="button" aria-label="打开 OptiFabric-1.0.0+mc1.20.6.jar">OptiFabric-1.0.0+mc1.20.6.jar</button> |
≥ 0.19.3 | 21+ |
| 1.21.x | 1.21 – 1.21.11 (ten releases) | <button class="_fileMention_177e0_288" title="OptiFabric-1.1.2+mc<version>.jar" type="button" aria-label="打开 OptiFabric-1.1.2+mc<version>.jar">OptiFabric-1.1.2+mc<version>.jar</button> (1.21 / 1.21.1 are <button class="_fileMention_177e0_288" title="1.1.0" type="button" aria-label="打开 1.1.0">1.1.0</button>) |
≥ 0.19.5 | 21+ |
| 26.x | 26.1.2 | <button class="_fileMention_177e0_288" title="OptiFabric-Reforged-2.0.0+mc26.1.2.jar" type="button" aria-label="打开 OptiFabric-Reforged-2.0.0+mc26.1.2.jar">OptiFabric-Reforged-2.0.0+mc26.1.2.jar</button> |
≥ 0.19.5 | 25 |
Why it is needed
OptiFine is built for vanilla (and Forge): its patches are compiled against the official obfuscated names, while Fabric runs in the intermediary namespace. Fabric API also injects into many of the same classes. Put together, the two disagree in ways that are hard to diagnose — different constructor shapes, different synthetic field names, helper methods inlined away, object creation replaced by OptiFine's own subclasses, and so on.
The disagreements are not cosmetic. Remapping without the game on the remapper's classpath silently left 35 methods unmapped in a single class, which showed up as 281 broken abstract contracts and 254 lost virtual overrides. OptiFine's recompiler turns vanilla methods into thin shells that forward to its own overloads — which moves Fabric API's injection points out from under it, and Mixin then fails the whole class at load. OptiFine also replaces classes wholesale (its ChunkOF chunk, its video-settings screen including the superclass) and rewrites the lambda bodies Fabric matches injection points against.
On the 26.x line the problem changes shape: Minecraft 26.1 and newer is unobfuscated — the official names are the runtime names, and there is no yarn and no real intermediary to remap through (26.1.2 publishes only the 0.0.0 placeholder). So that line takes no mappings at all, runs in the official namespace, and carries its own mod id (optifabric_reforged), because some mods declare "breaks": {"optifabric": "*"} and Fabric Loader matches that by id — a display-name change would not be enough.
What it does
At the earliest point of startup (the loader's preLaunch), OptiFabric will:
- run OptiFine's own installer to extract its patches for the game classes (since 1.21.6 the patches travel as xdelta diffs;
optifine.Patcheris used the same way); - drop the volde-ification, and rebuild the lambdas whose targets OptiFine moved (
LambdaRebuilder); - remap the patches from official to intermediary — with the game jar in the remapper's classpath and inputs, so members inherited from a supertype keep their mapped names;
- repair the known structural conflicts between OptiFine and Fabric API, each one traced down to the bytecode level;
- split the result in two: OptiFine's own classes and resources go on the game class path, the patched
net/minecraft/**classes go into aClassCache; - hand the repaired classes to Fabric Loader's own
GameTransformerand cache everything under<game dir>/.optifine/<OptiFine version>/, so later launches reuse it instead of doing the work again (1–2 seconds instead of 5–7).
Steps 2 and 3 are skipped on the 26.x line, which is the whole reason it exists as a separate project.
Replacement happens before Mixin: when a Minecraft class is about to be loaded, Loader asks the game provider's GameTransformer.transform(...) for ready-made bytecode. What OptiFabric hands over is therefore Mixin's input, not its output — which is why other mods' mixins against those same classes keep working. There is one hard constraint that follows from this: before the classes are handed over, nothing may reflect on game classes — a single Class.getMethods() loads every type in those method signatures and pins the class to vanilla for the rest of the session.
The cache directory holds cache-format.txt (currently 26; a mismatch rebuilds everything), Optifine-mapped.jar (OptiFine without MC classes, i.e. what goes on the class path) and Optifine.classes.gz (the patched MC classes).
Installation
- Install a client for your Minecraft version with Fabric Loader (≥ 0.19.3 for 1.20.6, ≥ 0.19.5 for 1.21.x and 26.x), on Java 21+ — or Java 25 for 26.1.2, which is the game's own requirement.
- Put OptiFabric and your own OptiFine jar for that exact version into that instance's
mods/folder. Dropping the OptiFine installer jar in is enough — you do not need to run its installer first (an already-extracted OptiFine withnotch/classes works too). Do not install two OptiFine jars (the game reportsDUPLICATED), and do not mix jars from two lines. - Start the game with the Fabric profile — not a launcher-made
1.21.x-OptiFine_xxxprofile, which injects OptiFine itself. The OptiFine version appears in the top left of the title screen when it works, and its options appear in video settings.
Fabric API can be loaded alongside (this port is adapted for it specifically). With version isolation enabled (PCL2 / HMCL), the game directory and mods/ live under versions/<name>/, and the .optifine/ cache is created there too.
Requirements
| 1.20.6 | 1.21.x | 26.x | |
|---|---|---|---|
| Minecraft | 1.20.6 | 1.21 – 1.21.11 (one jar each) | 26.1.2 |
| Fabric Loader | 0.19.3 or newer | 0.19.5 or newer | 0.19.5 or newer |
| Java | 21+ (tested on 25) | 21+ (tested on 25) | 25 |
| Side | client | client | client |
| OptiFine | <button class="_fileMention_177e0_288" title="preview_OptiFine_1.20.6_HD_U_I9_pre1.jar" type="button" aria-label="打开 preview_OptiFine_1.20.6_HD_U_I9_pre1.jar">preview_OptiFine_1.20.6_HD_U_I9_pre1.jar</button> (preview only) |
your own build, exact version match | <button class="_fileMention_177e0_288" title="preview_OptiFine_26.1.2_HD_U_K1_pre2" type="button" aria-label="打开 preview_OptiFine_26.1.2_HD_U_K1_pre2">preview_OptiFine_26.1.2_HD_U_K1_pre2</button> (preview only) |
| Optional | Fabric API (supported) | Fabric API (supported) | Fabric API (tested 0.155.3+26.1.2) |
What was verified
Every release is checked by one command, in a single loader, the same way the game loads those classes: the JVM verifier plus an ASM data-flow verifier over every patched class and every OptiFine class, followed by five scanners (mixin member references, @At injection points, abstract contracts / lost virtual overrides / unresolvable references, invokedynamic handles, local-variable captures).
| Minecraft | Patched game classes (JVM) | OptiFine classes (JVM) | ASM verifier | Scanners |
|---|---|---|---|---|
| 1.20.6 | 425 / 425 | — | 0 problems | clean |
| 1.21.3 / 1.21.4 | 440 / 440 · 474 / 474 | 816 / 816 · 812 / 812 | 0 | only the disabled-Indigo @At misses |
| 1.21.6 / 1.21.7 / 1.21.8 | 487 / 487 · 500 / 500 · 516 / 516 | 820 / 820 · 823 / 823 · 831 / 831 | 0 | same |
| 1.21.9 / 1.21.10 / 1.21.11 | 519 / 519 · 553 / 553 · 570 / 570 | 832 / 832 · 836 / 836 · 874 / 874 | 0 | same |
| 26.1.2 | 567 / 567 | 879 / 879 | 0 | all columns 0 (this line declares no contains_renderer, so Indigo is live) |
In game: startup, title screen, single-player, multiplayer servers, block/chunk/item and entity rendering, shaders (verified with ComplementaryReimagined), anti-aliasing on 1.21.3 – 1.21.11, F3 debug screen, with [ERROR]-free sessions and no crash reports. On 26.1.2 Indigo registers its own renderer and mods that generate geometry per block position (LambdaBetterGrass' better grass, connected textures) render correctly with shaders on.
Compatibility issues that are fixed
All of these were found through real crashes and traced to the bytecode:
- Fabric API's
ShaderProgramMixininjected beforesuper()→ OptiFine's delegating constructor is rewritten, and the inlined identifier creation now copies the game's ownIdentifier.ofVanilla(...)call (the wrapper targets exactly that call, andnew Identifier(...)bypassed it); - fields OptiFine left obfuscated with a mismatching descriptor (e.g. the particle factory table) → realigned by name, type and stored value, following the inheritance hierarchy to find the override;
- private helpers OptiFine inlined away while recompiling → the vanilla method body is restored so injections have a target again;
- methods OptiFine turned into forwarders to its own overloads (chunk building, model baking, block outline, item models) → vanilla bodies restored — this was behind "every model fails to bake" and invisible blocks;
- object creation OptiFine redirects to its own subclass (the
ChunkOFchunk object) → an inert marker puts Fabric'sNEWinjection point back; - a ported fixer that dropped a field initialisation together with the constructor it replaced → the constructor is no longer replaced (this one disconnected multiplayer sessions after two seconds);
- lambda bodies recompiled under a different name and signature (
lambda$addMainPass$1grew an argument) → vanilla bodies restored; where OptiFine replaced method references with its own lambdas,LambdaMethodRefFixrenames them back to the method name, because that release's Fabric API matches custom injection points by bootstrap handle; - a region constructor that never stored the section position (
ChunkCacheOF.renderStart()then NPEs inside a null region) → the fixer calls the six-argument constructor and derives its argument from the packed long the method already has — the 1.21 – 1.21.4 shape takes aChunkSectionPosobject instead, and both shapes are handled; - a Fabric hook whose context OptiFine's render-pass structure never fills in (
BEFORE_BLOCK_OUTLINE) →StubInjectionTargetFixrenames the target and leaves a same-named copy, so the hook injects into code nobody calls: the crash is gone and the block outline is still drawn by OptiFine; - the same trick failing for the moving-blocks renderer hook, whose caller lives in another class and was reaching the injected copy →
CallSiteRedirectFixredirects that call site too (without it, multiplayer clients crashed ~30 seconds in); - F3 crashing while nothing was registered as the renderer — declaring
contains_rendereronly makes Indigo step aside; Fabric's own debug entries still callRenderer.get()→RendererApiFallbackregisters an inert placeholder renderer; - the placeholder's first version breaking the whole session — it read the Fabric API interface with
Class.getMethods(), which loaded game classes before the patched ones were handed over and pinned them to vanilla forever → the placeholder is now generated with ASM from the interface's class file alone (no type resolution), registered throughMethodHandles.findStatic, and only after the classes are in place; on 26.1.2 the renderer API had also moved toapi.client.renderer.v1, where the old lookup failed silently; - classes no fixer modifies no longer get their stack frames recomputed — the global override fixer always reports a change, so recomputing every patched class degenerated merged local types to
java.lang.Objectand the game rejected the class withVerifyError: Bad type on operand stack; - 26.x: OptiFine's thin shells leave two same-named methods, while Fabric API names its targets without descriptors → each site is disambiguated (delete the overload nobody calls; rename the one that is still called with
CallSiteRedirectFixfollowing its callers). Getting this wrong shows up asLVTGeneratorError: Could not locate method metadata …or asScanned 0 target(s); - 26.x: models that emit their own quads silently vanished — Fabric's terrain hook injects into the
BlockPos.betweenClosedloop of the vanilla chunk build, and OptiFine's own compile overload has no such loop, so the hook ran nowhere.FrapiTesselateBridgeFix+OptifineFrapiBridgeroute that one tessellation call through Fabric's renderer and hand the quads to OptiFine's ownBlockQuadOutput, so vertex format, layers, lighting and shader attributes stay OptiFine's; only models whoseemitQuadsis declared outsidenet.minecraft.are routed (vanilla models stay on OptiFine's path, or shaders lose OptiFine's extra vertex attributes); - anti-aliasing: the FXAA chain is resolved by the game's post-chain loader from
post_effect/, so an earlier build of this mod that "helpfully" deleted that file made every resource reload logResource not found: minecraft:post_effect/fxaa_of_2x.jsonand every anti-aliasing toggle fail withFailed to load post chain. OptiFine's own chain files are now left exactly as they ship, and on 1.21.9 / 1.21.10 — whose post pipeline draws an attribute-less fullscreen triangle fromgl_VertexIDwhile OptiFine'sfxaa_of_*.vshstill reads thePositionattribute (this was the "antialiasing turns the screen black" bug) — the two vertex shaders are rewritten accordingly.
The full list (symptom / cause / fix) is in the changelog, with the per-round evidence in docs/DEVELOPMENT.md (and docs/PORT_26.x.md for the unobfuscated line).
Known issues
- Conflicts with Sodium — both are renderers; do not install them together.
- Incompatible with RyoamicLights — OptiFine replaces the whole video settings screen (including its superclass), which makes that mod's injection fail and crashes as soon as the screen is opened. OptiFine has built-in dynamic lights (Video Settings → Quality → Dynamic Lights), so it is not needed.
- Mods that rely on FRAPI/indigo no longer get indigo's custom rendering on 1.20.6 and 1.21.x; terrain is rendered by OptiFine and
Renderer.get()returns an inert placeholder (F3 showsOptifineRendererPlaceholder). On 26.1.2 the opposite is true — Indigo registers its own renderer and that geometry renders. - Two Fabric API hooks are intentionally inert (the
BEFORE_BLOCK_OUTLINEevent does not fire; the moving-block FRAPI path is bypassed). Both paths still render correctly through vanilla/OptiFine. - 1.21.6 / 1.21.7 crash as soon as shaders are enabled (
NullPointerException … "multiTex" is nullinShadersTex.initDynamicTextureNS). It is not the shader pack (three unrelated packs crash identically, and stripping a pack's custom textures does not help) and not this mod: OptiFine's own preview builds for those two releases inject a call into the first texture creation without thesetParentTextureassociation the later builds perform. All seven OptiFine builds available for them crash the same way. Without shaders both releases start and play. - 26.1.2 needs Java 25 — starting it on Java 21 fails before the window appears. That is the game's requirement, not this mod's.
- OptiFine cannot see resources inside Fabric mods — you will see
Unknown resource pack type: ...ModNioResourcePackin the log. This is a limitation on OptiFine's side. - Shader packs that do not match your OptiFine version log
[Shaders] Invalid program name: ...,Unknown macro value: IRIS_VERSIONorParseException: Model variable not found: …; those come from the shader pack. - Only the releases listed above are covered — other Minecraft versions need their own pass, and OptiFine has published no build at all for 1.21.2 / 1.21.5 or for anything after 26.1.2.
Troubleshooting
Where is the cache / how do I force a rebuild? <game dir>/.optifine/<OptiFine version>/. Delete the .optifine/ folder to force a rebuild — the cache format (26) normally rebuilds it by itself after an upgrade.
Why can't I find [OptiFabric] in the log? Its output goes to the launcher console, not to logs/latest.log; the loader only writes log4j output there. Filtering for [OptiFabric] shows how many classes were prepared and how many Loader took over.
The game jar cannot be found / I want to point at it manually — add -Doptifabric.mc-jar=<path to the vanilla client jar>.
I want to inspect the patched classes — add -Doptifabric.extract=true; the remapped OptiFine classes are unpacked to .optifine/<version>/optifine-classes/.
Stuck on the loading screen — take two thread dumps (jstack <pid>, ~15 seconds apart) and compare them. Identical stacks with flat CPU means a real stall; a stack sitting in a native call (glfwSwapBuffers) is a presentation problem, and do not minimise the window while loading (with vsync on the render thread blocks there).
Models/items/textures disappearing wholesale (a log full of Unable to bake … model) — a Fabric mixin failed to transform that class; the outermost message usually hides the real cause. OptiFine turning vanilla methods into forwarders is the usual reason the injection point moved.
Warnings that are normal and can be ignored — [OptiFine] (Reflector) Class not present: net.minecraftforge.* / sun.misc.SharedSecrets (OptiFine probing for Forge and old JDKs), Failed to locate initialiser injection point in <init>(class_2591,…) (the price of applying OptiFine's BlockEntity patch), [OptiFabric] Resource not found: minecraft:shaders/post/fxaa_of_{2,4}x.json (OptiFine probing its pre-1.21.6 chain location; the chain in use lives in post_effect/), and Skipping bad option: lastServer.
Reporting a problem
Please attach:
logs/latest.log(plus the matching file fromcrash-reports/if it crashed — it ends with an-- OptiFabric --section listing the OptiFine version, jar status and remapped jar path);- your
mods/folder listing; - your OptiFine version (e.g.
OptiFine_1.21.11_HD_U_J9) and which Minecraft version you run.
License and credits
A port of Chocohead/OptiFabric by Modmuss50 and Chocohead, licensed under MPL-2.0; ported files keep their origin headers. OptiFine itself is neither included nor redistributed — it is sp614x's work, get it from the official site. This is a community port and is not affiliated with, endorsed by or supported by the OptiFine, Fabric or Mojang teams.
Screenshots
Gallery
Versions
Files
Relations
Project Relations
More like this
Similar Mods
Suggestions use data such as tags, dependencies, dependents, descriptions, titles, and more to rank how much they overlap with this mod.
On ModDex
Community snapshot
By the numbers
Statistics
Want to reach Minecraft players?
We're looking for a server hosting partner to feature here and other parts of the site. Interested? Send us a message!
Get in touchGet it on
Available Platforms
On ModDex
Community snapshot
By the numbers
Statistics
Resources