-
-
Notifications
You must be signed in to change notification settings - Fork 151
Geckolib 5 Changes
GeckoLib5 was once again a substantial overhaul of the entire library. Unlike GeckoLib4 however, this one was prompted by Mojang's extensive internal rendering pipeline changes; forcing GeckoLib to adapt and change.
Fundamentally, these changes may feel like a slight downgrade to the developer experience, but this was a requirement of Mojang's new rendering changes, and ultimately represents a significant improvement to performance and capability in the future as Mojang moves to things like native shaders, multi-threaded rendering, and more.
- Conceptual Changes
- Asset Changes
- Changes Summary
- RenderStates
- AnimationState and AnimationTest
- GeoModel Asset Paths
- GeoRenderer Generic Types
- Glowmasks
- Molang Variables
- 'Dynamic' Renderers
- TextureLayerGeoLayer
Note
This page does not constitute a complete list of all changes. It merely lists the bulk of them, aiming to cover critical or notable changes especially.
Beginning in 1.21, Mojang began to make moves towards separating the game thread from the render thread. This meant that at the time of rendering an object, the object did not exist. For example; if you were rendering an entity, the entity was not known to the renderer at all, at any stage of the rendering process.
The reason for this was somewhat unclear at the beginning, although eagle-eyed developers could see the direction it was heading.
This continued to expand in scope throughout the various 1.21 version updates. At first, GeckoLib obscured the changes, by simply ignoring vanilla and holding onto the entity throughout the process. It has become increasingly clear however that Mojang intends to not only continue with this change, but expand it into other rendering areas.
GeckoLib, for its part, had to acknowledge Mojang's move to a separate rendering pipeline. This was problematic however, as GeckoLib was built from the ground up on the idea that the renderer always had ownership of the object it was rendering, at all times. Everything right down from the renderer itself, to the way GeckoLib parsed Molang, operated on the paradigm of render target ownership.
To ready itself for the incoming changes, and adapt to Mojang's current pipeline plans, 5.0 makes a few notable conceptual changes:
- All renderers now operate on the principle that the rendered object is not accessible at the time of rendering. This means that all renderers operate on a RenderState, which caches the data extracted from the rendered object, before leaving that object behind.
- All renderers, aswell as the Molang and animation pipelines all operate as instanced, disallowing any perpetual state management between render passes
- All render data for rendering (including Molang queries and associated data) must be pre-computed before being passed to the render.
For the most part, there's really only one key change you need to be aware of and adapt to: the RenderState. Now, for each renderer, there's two stages:
- RenderState extraction
- Rendering
At the start of each render pass, GeckoLib will create and fill a GeoRenderState with the data necessary for rendering. By default, GeckoLib will provide a suite of existing data for you to use and re-use as needed, however you may want to add more for your own purposes. You can do this in #addRenderData
This data will then be what gets passed through to the renderer for the rendering process. The animatable object (such as an Entity) will be forgotten immediately after this step, and will be unavailable to the renderer.
All GeoModels, GeoRenderLayers, and other Renderers give access to the RenderState at fill time, to add additional data as needed.
More information can be found in the RenderStates section
After extracting and filling the RenderState, the renderer will then move on to actually rendering. It will use the information given to it in the RenderState to perform all rendering operations, including animation handling and processing.
This stage is mostly unchanged, with the exception that the animatable is no longer available.
Important
With the move to GeckoLib5, the decision was made to move GeckoLib's assets into its own directory, to prevent the recurring issue of asset location clashes. As of 5.0, you will need to move your assets as below:
- Models (geo.json):
/assets/<modid>/geckolib/models/ - Animations (.animation.json):
/assets/<modid>/geckolib/animations/
Where /assets/<modid>/ is your mod's normal assets location
-
Keyframes->KeyframeMarkers -
GeckoLibCache->GeckoLibResources -
GeoEntityRenderState->GeoRenderState
EntityModelDataDeferredGeoRenderProviderInternalUtilFileLoaderColorDynamicGeoBlockRendererDynamicGeoEntityRendererDynamicGeoItemRendererAnimationPointQueue
The below classes were not removed, but had their package location changed
AnimatableManagerContextAwareAnimatableManagerAnimationControllerAnimationProcessorAnimationStateAutoPlayingSoundKeyframeHandlerGeoRendererGeckoLibItemSpecialRenderer
-
AnimatableManager#setData->AnimatableManager#setAnimatableData -
AutoGlowingTexture#getEmissiveResource->AutoGlowingTexture##getOrCreateEmissiveTexture -
AnimationController#process->AnimationController#startTick
RenderStates are Minecraft's way of storing information relating to an object being rendered, without holding onto the object itself. The idea behind this is that all information stored in a RenderState is a thread-safe snapshot of the object being rendered, so that rendering itself can be performed on another thread entirely.
GeckoLib jumps on this concept, extending it to all of its renderers. All of GeckoLib's renderers now utilise a GeoRenderState. This operates on a DataTicket basis.
Prior to passing the renderer off to render, each GeoRenderer calls to #captureDefaultRenderData, which fills in the default DataTickets for that renderer to operate. Additionally, it calls to #addRenderData, which is where you would add your own DataTickets as necessary.
After that, it additionally checks each added GeoRenderLayer for additional data, the GeoModel, and also fires the an event/callback for external handling.
As of 1.21.5, vanilla only does RenderStates for Entity rendering, beginning with EntityRenderState, although they have explicitly stated they plan to bring them to all other areas of rendering in the near future.
GeckoLib injects GeoRenderState into all EntityRenderStates, meaning that if you are using a GeoEntityRenderer, your GeoRenderState is also an EntityRenderState, and vice-versa. You can safely cast between the two as needed, since EntityRenderState has additional values that might be useful.
Additionally, GeoEntityRenderer will automatically implement a LivingEntityRenderState instead, if your animatable is a LivingEntity.
In vanilla, Mojang extends EntityRenderState with subclasses (LivingEntityRenderState, etc) to add more variables. GeckoLib also supports this, though it doesn't recommend you do so.
The reason for this is simple:
GeoRenderStates are indefinitely extendable, as their data is simply a map of DataTickets to their values. Using DataTickets rather than a custom class means that other mods can soft-depend on you much easier, and not have to worry about classloading, generic-type resolution, or casting.
In GeckoLib4, users would take an instance of AnimationState in their controller predicates, using it to handle the animation stages and playstate. This caused issues with users confusing the class with the vanilla AnimationState class, and it also posed a problem when introducing the RenderState object.
To rectify these issues, the AnimationController predicate will now provide an instance of AnimationTest. It works mostly the same way, but splitting it into its own object meant I could hide away the parts that aren't relevant to you at the time of the predicate, eliminate some naming confusion.
Note
AnimationState still exists, but it has been moved and repurposed. It is now an internal class used for handling the animation state for the render pass. You generally shouldn't need to interact with it outside of custom Molang queries.
Traditionally with GeoModels, you would either use one of the Defaulted variants, or override the getModelResource and getAnimationResource methods to return your asset paths.
For example, you may have had something like the below:
@Override
public ResourceLocation getModelResource(GeoRenderState renderState) {
return ResourceLocation.fromNamespaceAndPath(MyMod.MOD_ID, "geckolib/animations/my_model.geo.json");
}As of 5.0, GeckoLib no longer expects you to acknowledge either the asset location prefix, or the file suffixes. What this means is that the expected format is now like so:
@Override
public ResourceLocation getModelResource(GeoRenderState renderState) {
return ResourceLocation.fromNamespaceAndPath(MyMod.MOD_ID, "my_model");
}The benefit to this is that neither GeckoLib nor the users need to ensure they match the correct prefix path, or the file suffixes. GeckoLib assumes all json files in the animations or models directories are animations or models respectively, and so it no longer needs you to explicitly define them, making your paths look cleaner and easier to read, and more flexible.
Warning
This does not apply to getTextureResource, as vanilla uses this for its own purposes, and still expects the prefix and suffix
Traditionally, GeckoLib's GeoRenderer has a single generic type - the type of animatable it renders.
With 5.0 and the advent of RenderStates, this changed. Now, GeoRenderers have 3 generic types:
-
T: The type of animatable it renders -
O: The type of associated data the renderer uses when extracting the render state (orVoidif not applicable) -
R: The base type of RenderState the renderer uses
This also extends to GeoRenderLayers, and so it can pay to be wary of the generic types that the base renderers use.
As of 5.0, GeckoLib no longer supports mcmeta-based glowmasks. This was a rarely used and inefficient system anyway, and has been fully superceded by the tetxure-based glowmask.
Additionally, GeckoLib5 no longer modifies the base texture when using an emissive texture. This means that you can selectively/conditionally/dynamically apply a glowmask without having missing chunks of your texture.
See the Emissive Textures page for more details
With the change to the render pipeline in 5.0, Molang Variables had to change. Previously, queries could be defined and updated at any time during the render process. This was a problem with a new instance-based rendering pipeline, because there's no animatable during rendering.
To combat this, Molang Variables, and by extension all MathValues, have been converted from a DoubleSupplier to a ToDoubleFunction, taking in the AnimationState from the current render pass. This allows for queries to be dynamic whilst still supporting an instance-based render pipeline.
In GeckoLib4, GeckoLib expanded upon its 'Dynamic' Renderers - a special renderer that allows for quickly swapping out textures or rendertypes for individual bones. With 1.21, this became impractical due to the changes in the way Mojang handled buffers.
GeckoLib patched this in an incredibly ugly way to attempt to keep the functionality while a better solution was being devised, but with 5.0 this became impractical to keep.
Instead, GeckoLib now has CustomBoneTextureGeoLayer. This is a GeoLayer that can be applied to any GeoRenderer, and allows for dynamic rendering of bones in much the same way that the previous DynamicRenderers worked, but in a much more efficient and stable manner.
New to GeckoLib5 is a a built-in helper GeoLayer called TextureLayerGeoLayer.
This is a quick render layer that allows you to define a second render pass for the same model, rendering a second pass with minimal additional effort.
This is useful for things like secondary texture layers.
Geckolib 3
Geckolib 4
- Installation
- Getting Started
- Upgrading from GeckoLib 3.1.x to 4.0
- Updating to GeckoLib 4.5
- Basic
- Advanced
- Miscellaneous
Geckolib 5
See the New Wiki!
Package repository hosting is graciously provided by Cloudsmith.
Cloudsmith is the only fully hosted, cloud-native, universal package management solution that enables your organization to create, store and share packages in any format, to any place, with total confidence.