BlockRenderLayerMap does not support custom render layers
Pyrofab opened this issue ยท 3 comments
If BlockRenderLayerMap#putBlock
is called with a render layer that is not used with blocks in vanilla, the game eventually crashes with an NPE in ChunkBuilder#render
. This seems to happen because BlockBufferBuilderStorage
builds its own Map<RenderLayer, BufferBuilder>
before client initializers are called, resulting in it only having buffer builders for vanilla block render layers.
One solution would be to update the latter alongside RenderLayers.BLOCKS
in our BlockRenderLayerMap
implementation.
Minimal code:
public void onInitializeClient() {
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.GRASS_BLOCK, RenderLayer.getEntityGlint());
}
Crash report: https://gist.github.com/Pyrofab/f2524f9b77db0e62bdfd993b16908aa4
The problem is much deeper than ChunkBuilder. The four terrain rendering layers are hard-coded into WorldRenderer. The translucent layer in particular requires special casing in multiple locations.
And if more than one translucent-like layer were to exist all quads from such layers must be rendered sorted back-to-front independent of render layers. This greatly complicates chunk buffering and drawing and will kill performance if many alternating blocks with different layers occur in the same chunk due to frequent GL state changes. A consolidated translucency shader may help here but that goes way beyond Fabric API scope and could still be problematic for performance .
Even limiting the feature to non-blended layers would require big changes to chunk buffering and drawing.
FREX/Canvas V0 allow this behavior via custom per-material shaders as an extension of RenderMaterial. FREX also allows renderers to implement and expose special materials with namespaces identifiers to provide access to effects while hiding the implementation.
V1 may allow for some Gl state changes like those in RenderLayer (setting up decal rendering, for example, would be nice) but given how brittle and dangerous direct render state changes can be it's more likely to be abstracted somehow.
Even these lesser features of named materials and/or abstracted state changes limited to non-translucent layers are probably well beyond the scope of the default renderer. When I imaging getting something like that into a shape that is compact and clean enough to fit into official API I am filled with dread.