Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Submit phases and feature renderers

Verified against Minecraft 26.2 · Reference · Hand-kept from SubmitNodeCollection and the FeatureRenderDispatcher constructor.

Everything an entity, block entity, particle or debug renderer draws in a level arrives as a submit node — the sky, the clouds, the weather and the world border are drawn by their own renderers in their own frame-graph passes, and terrain by its chunk sections. SubmitNodeCollection sorts those nodes into fifteen named phases as they come in, and thirteen feature renderers turn them into vertices. The lecture that frames both is entity rendering, which names four of the phases and one of the renderers. Three more renderers are named elsewhere — TextFeatureRenderer and NameTagFeatureRenderer on text and fonts, QuadParticleFeatureRenderer on particles — and everything else here is only here.

The fifteen phases

In declaration order, which is also the order of SubmitNodeCollection.allPhases. It is not the order they are drawn in, and neither is the last column: FeatureRenderDispatcher.PreparedFrame.executeTranslucent alone makes three separate sweeps over every order bucket, so the phases it drains are numbered by sweep — but within a sweep the order is the one the sweep’s own statements run in, not the order of the rows. Sweep 1 drains shadows, then translucent models, then see-through name tags, then name tags, then texts, then translucent custom geometry — so a see-through name tag is drawn before the opaque one, which is the row order reversed.

Three phases are a TranslucentFeatureRenderPhase and the other twelve a SimpleFeatureRenderPhase. The simple phase groups its nodes by feature type and then by batch key — which only two of the thirteen submit kinds have, a model and a piece of custom geometry, everything else grouping by adjacency — and leaves RenderTypeFeatureRenderer.Group free to fold a node’s geometry into any earlier draw of the same render type, not only the adjacent one. The translucent phase keeps every node, sorts them back to front by squared distance to the camera, and marks the group strictly ordered. That does not stop merging: consecutive submits of one render type still share a draw, on a test that never consults the flag. What it stops is the fold into a non-adjacent earlier draw — the one merge that would move geometry ahead of the draws between it and its target, and so undo the sort. A render type whose primitives are chained opts out of both, through RenderType.canConsolidateConsecutiveGeometry.

#phasewhat lands in itdrained by
1SubmitNodeCollection.solidthe opaque default: models and block models whose RenderType does not blend, moving blocks whose model does not declare the translucent material flag, items with no translucent quad, custom geometry that neither blends nor outlines, the opaque half of every quad-particle group, plus every flame and every leash.executeSolid
2SubmitNodeCollection.shadowsone node per SubmitNodeCollection.submitShadow, carrying the radius and the EntityRenderState.ShadowPiece list sampled at extract.executeTranslucent, sweep 1
3SubmitNodeCollection.nameTagsevery name tag gets a node here, see-through or not — a see-through one lands with an emission bump on its light, opaque white, and no background.executeTranslucent, sweep 1
4SubmitNodeCollection.seeThroughNameTagsthe second node a see-through name tag emits, in Font.DisplayMode.SEE_THROUGH with the background restored.executeTranslucent, sweep 1
5SubmitNodeCollection.textsworld-space text that is not a name tag, from SubmitNodeCollection.submitText.executeTranslucent, sweep 1
6SubmitNodeCollection.shapeOutlinesVoxelShape edge outlines submitted without the after-terrain flag.executeTranslucent, sweep 2
7SubmitNodeCollection.translucentBlocksAndItemsitems with a translucent quad, block models whose render type blends, and moving blocks whose model declares the translucent material flag.executeTranslucent, sweep 3
8SubmitNodeCollection.translucentModelsentity models whose RenderType blends.executeTranslucent, sweep 1
9SubmitNodeCollection.translucentCustomGeometrycustom geometry whose RenderType blends — a simple phase in spite of the name, so it is not distance-sorted.executeTranslucent, sweep 1
10SubmitNodeCollection.gizmosdebug primitive groups submitted without the on-top flag.executeTranslucent, sweep 2
11SubmitNodeCollection.breakingOverlaythe crumbling decal: a model submitted with a ModelFeatureRenderer.CrumblingOverlay whose render type admits one, and every SubmitNodeCollection.submitBreakingBlockModel.executeTranslucent, sweep 3
12SubmitNodeCollection.waterMaskmodels submitted with the water-mask render type.executeTranslucent, sweep 3
13SubmitNodeCollection.afterTerrainoutlines flagged after-terrain, plus the translucent half of every quad-particle group.executeTranslucentAfterTerrain
14SubmitNodeCollection.alwaysOnTopgizmo groups flagged on top.executeAlwaysOnTop
15SubmitNodeCollection.outlinea second copy of a model, block model, moving block or item whose outline colour was non-zero — a model or block model only where its render type has an outline variant, and a moving block or item with its ordinary type, re-typed inside the feature renderer or dropped there — plus custom geometry, which is not a second copy at all: an outline render type routes the only copy here.executeOutline, which FeatureRenderDispatcher.renderAllFeatures never calls — LevelRenderer does, into its own target

Two rows are worth reading twice. A quad-particle group is submitted once and lands in two phases at once, solid and afterTerrain, with a flag that picks which of its layers each half draws. And outline is not simply solid submitted twice: the glow is a second submission for a model, a block model, a moving block or an item, but flames, leashes and quad particles never reach it at all, a blending model pairs its outline copy with translucentModels rather than solid, and custom geometry goes to one phase or the other and never both.

The thirteen feature renderers

In the order FeatureRenderDispatcher’s constructor registers them. All but one extend RenderTypeFeatureRenderer, which owns the shared StagedVertexBuffer draw and the merging of consecutive same-render-type geometry.

feature rendererwhat it writes
ShadowFeatureRendererfour vertices per EntityRenderState.ShadowPiece onto one shared shadow render type, with the piece’s alpha as the colour and UVs derived from its bounds and the shadow radius
FlameFeatureRenderera stack of fire quads scaled to the entity’s bounding box, alternating two block-atlas sprites and flipping their U every other pair, at full block light
ModelFeatureRendererthe entity models: Model.setupAnim and then Model.renderToBuffer over the ModelPart tree, into a buffer optionally wrapped for a sheeted decal or a single sprite
NameTagFeatureRendererthe glyph quads and background of a name tag, prepared through Font at the submitted pose and display mode
TextFeatureRendererarbitrary world-space text, with an eight-direction outline pass and a polygon-offset second pass when an outline colour is set
LeashFeatureRenderera ribbon between the two ends of an EntityRenderState.LeashState, walked twice — twenty-four steps out and twenty-four back for its two faces, a hundred vertices in all — with its light interpolated between the endpoints and its colour alternating per step
ItemFeatureRendereritem quads, in two passes over the same submits — geometry first, then the enchantment foil for every submit that has one
CustomFeatureRenderernothing of its own: it hands the caller’s SubmitNodeCollector.CustomGeometryRenderer a vertex consumer for the requested render type
BlockModelFeatureRendererthe quads of a BlockStateModelPart list, in Direction order, at one fixed light and overlay coordinate for the whole submit
MovingBlockFeatureRenderera whole block state re-tesselated through ModelBlockRenderer — pistons and falling blocks — honouring the ambient-occlusion and cutout-leaves options
QuadParticleFeatureRendererthe only one outside RenderTypeFeatureRenderer: it appends particle draws to the StagedVertexBuffer per SingleQuadParticle.Layer and opens its own RenderPass to issue them
ShapeOutlineFeatureRenderertwo line vertices per edge of a VoxelShape, each carrying a per-vertex line width
GizmoFeatureRendererthe debug vocabulary: quads, triangle fans, lines, texts and points out of a DrawableGizmoPrimitives.Group, camera-relative

That list is the answer to what can be drawn in a level. Anything a mod or a renderer wants that is not one of the other twelve has to go through CustomFeatureRenderer.


Rules: names, never code · how the system works, not how the code reads · newest version only · every backticked name passes tools/verify_names.py.