Table of Contents

Rendering in Fabric (DRAFT)

IMPORTANT: This documentation describes upcoming features in the process of being added to Fabric. These feature are not yet available and subject to change. The documentation is being posted now to help the developer community evaluate and improve the proposed features before adoption.

Introduction

The Fabric Rendering API

The Rendering API specifies interfaces and creates hooks for the implementation of a Renderer. An implementation will provide the following features:

The API is flexible so that Renderer implementations can introduce novel lighting, special effects and performance optimization with excellent compatibility for models that depend on the API. Some renderer implementations may focus on aesthetics and some may focus on performance, and others may try to balance both.

This freedom is achieved through two key design decisions:

First, Fabric delegates most of the functionality to the Renderer implementation itself - Fabric includes very few patches as part of the API.

Second, the API specification hides vertex formats, vertex data structures, and other implementation details from models using the API - models are not expected to provide or manipulate raw vertex data. Instead, the API defines lightweight interfaces for obtaining materials and building/outputting model content. Mod authors who use these interfaces can be assured their content will render well across a diverse range of implementation approaches.

Audience

Mod Developers

Many mod authors will use a 3rd-party library to create or load models. However, many features of the API are likely to be useful or even necessary when using a library. If this describes you, this wiki should be a useful reference, but you don't need to read and understand every part of it.

Model Loader Developers

The Fabric Rendering API was designed to be a suitable back-end for practically any type of model loader but does not specify or implement any model formats. Creating a model loader is a great way to contribute to Fabric development! If you want to create a model loader, you should review the entire API and all of the sections below.

Model Library Developers

The Rendering API provides only the most basic primitives for model creation. Creating a library for procedural model generation and transformation is another good way to contribute to Fabric development. If you want to create a model library, you'll need to review the entire API and all of the sections below.

Caution: If your library will be used to generate models a run time (after Minecraft is loaded) then you should also have a good working understanding of the potential negative impacts on game performance and be familiar with techniques to avoid them.

Renderer Developers

The Rendering API is only as good as the available implementations. Creating and maintaining a new Renderer is likely to be a large and complex effort. Before you begin, consider the following questions:

Still want to create a renderer? This wiki and the links below will help you get started. And please post in Discord so we know to include your implementation in the links section!

Getting Started

You'll need to include the Fabric API in your development environment - the Rendering API is part of it. See Setting up a mod development environment for step-by-step instructions.

Fabric is distributed with a default Renderer implementation providing most of the features defined in the API. (It doesn't handle emissive item rendering,). The default renderer offers excellent compatibility, vanilla aesthetics and good performance for most use cases.

If the features provided in the core API are sufficient, the default renderer is all you need. Players or pack makers may render your content with other render implementations to get better performance or a different look (ie. shader packs).

Only one Renderer implementation can be active in a game session. When a non-default Renderer implementation mod is present, it needs to disable the default Renderer. This can be done by adding the following lines to your fabric.mod.json.

{
  [...]
  "custom": {
    "fabric-renderer-api-v1:contains_renderer": true
  }
}

If two (non-default) implementations are present, Minecraft will crash during startup when the second implementation tries to register itself.

Some renderer implementations may offer an expanded feature set. If you create mods with a hard dependency on those features, be sure to state that clearly for anyone using your mod. In that case, your audience will be limited to players and pack makers who use renderers supporting those expanded features.

Getting the Renderer Instance

To use the features of this API, you'll need a reference to the Renderer instance. Getting the instance is easy:

RendererAccess.INSTANCE.getRenderer()

It is safe to retain a reference to the Renderer instance.

The renderer instance will be reliably non-null unless Fabric was somehow distributed without the default renderer or with the default renderer disabled. (This would not be normal.) If your mod depends on features defined in the API, then your mod should simply crash when no Renderer is active.

Materials

Every quad sent through the rending API has an associated RenderMaterial. Materials give you control over texture blending and lighting. In future API extensions, materials will be the attachment point for other behaviors. Many of the effects you will want to achieve can be accomplished by material selection.

Obtaining Materials

Use Renderer.materialFinder() to get a MaterialFinder reference. It's safe to retain the resulting reference. Use the finder to specify the properties you want for your material and then use MaterialFinder.find() to get a RenderMaterial instance that will communicate those choices to the renderer.

Tip: Calling find() doesn't change any attributes of the finder. This behavior is useful when you want several materials with similar properties. If instead you want very different materials, call MaterialFinder.clear() to reset the finder instance to default values before specifying your next material.

Material instances are immutable and opaque once retrieved. Materials with identical properties may or may not pass == and .equals() tests. They exist only to efficiently communicate material properties to the renderer - they aren't meant to be analyzed by models. This affords renderer implementations maximum flexibility for material handling.

Named Materials

Materials can be registered with a name-spaced identifier using Renderer.registerMaterial() and retrieved using Renderer.materialById(). This can be useful if you publish a mod that allows third-party extensions and you want to give those extensions a supported way to use consistent materials. In that case, your mod should register materials with identifiers that are visible to extensions.

Named materials can also be used by Renderer implementations to expose custom materials that provide special effects not possible with the standard materials. Renderers that provide custom materials are responsible for declaring and exposing the identifiers used to retrieve them.

Named materials will not be present unless a mod/renderer that registers them is also present. If your mod relies on named materials, you should either make your mod explicitly depend on the providing implementation(s) or check for the presence of the material at run time and use a fallback material when the named material is not available.

Material Properties

When selecting a material, you can choose from materials with the following attributes:

Blend Mode

Diffuse Shading On/Off

Ambient Occlusion Shading On/Off

Emissive Rendering On/Off

Sprite Depth

Color Index On/Off

Meshes

Render Contexts

Dynamic Rendering

How To

Implementation Advice

Rendertime Mesh Generation

Necessary Hooks

Optimization Opportunities

Future Direction

Implementations

Extensions

Sample Usage

Model Libraries

Model Loaders