Skip to content
Draft
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
33e1e9a
begin porting
sylv256 Feb 15, 2026
27e9b00
refactor!: `RenderType` in `QuadView` & update `EncodingFormat`
sylv256 Feb 16, 2026
adffa1a
refactor!: `FabricMaterialBaker` :3
sylv256 Feb 19, 2026
639fbe3
fix: everything
sylv256 Feb 19, 2026
04d1ff6
Merge remote-tracking branch 'origin/26.1' into rendering-1
sylv256 Feb 19, 2026
9d916ea
fix: some style and mixinextras being mad at me
sylv256 Feb 19, 2026
959487b
fix!: minor issues
sylv256 Feb 20, 2026
da01daf
fix: the `BakedQuadOutput` crisis of 2026
sylv256 Feb 21, 2026
fca1cb7
refactor!: remove `ItemRenderTypeGetter`
sylv256 Feb 21, 2026
35d8de6
docs: fix `ModelModifier` `ModelBaker#sprites` -> `#materials`
sylv256 Feb 21, 2026
37642a7
docs: `MutableQuadView` missing reference
sylv256 Feb 21, 2026
4470e79
fix: forgot to set `itemRenderType` to null by default
sylv256 Feb 21, 2026
df13e0a
fix: set `chunkLayer` and `itemRenderType` in `#fromBakedQuad`
sylv256 Feb 21, 2026
37ad034
fix: nullability issues in `EncodingFormat` w/ `itemRenderType`
sylv256 Feb 21, 2026
4c00b49
fix: nullability issues in `EncodingFormat` w/ `itemRenderType` pt 2
sylv256 Feb 21, 2026
6df8101
fix: recalculate transparency instead of storing in QVs
sylv256 Feb 21, 2026
5cdecb7
fix: get or find chunk layer (not item render types)
sylv256 Feb 22, 2026
440abec
Fix testmod and use getOrResolveItemRenderType in ItemRenderContext
PepperCode1 Feb 22, 2026
e723894
Fixes and improvements
PepperCode1 Feb 22, 2026
7f28d9c
Some doc fixes
PepperCode1 Feb 22, 2026
a35cea9
style: chain `QuadEmitter` calls
sylv256 Feb 22, 2026
8a71c9c
docs: prefer using this method 😇 -> use this method 😡
sylv256 Feb 23, 2026
37ebbae
docs(javadoc): omg pls build successfully thx
sylv256 Feb 23, 2026
6b86771
Merge branch '26.1' of github.com:FabricMC/fabric into rendering-1
BluSpring Mar 11, 2026
2339bb1
Large port for 26.1-pre-1
BluSpring Mar 11, 2026
989f130
Uncomment mixin for BlockFeatureRenderer
BluSpring Mar 11, 2026
42964bf
fix mixins JSON
BluSpring Mar 11, 2026
cc1c1bb
Merge pull request #1 from BluSpring/rendering-1
sylv256 Mar 13, 2026
08b4eff
Merge branch '26.1' into rendering-1
sylv256 Mar 13, 2026
7afbd86
Merge remote-tracking branch 'origin/26.1' into rendering-1
Rigner Mar 21, 2026
467948c
Fixed many compile errors in model-loading-api and renderer apis
Rigner Mar 21, 2026
5f76a86
fix: use BlockState random in SimpleBlockRenderContext#bufferModel
sylv256 Mar 23, 2026
a2ff2da
general changes and add FabricBlockFeatureRenderer
sylv256 Mar 23, 2026
643a47b
refactor: fix some mixins, some new stuff
sylv256 Mar 24, 2026
4860522
fix: use seed 42 in simple block contexts
sylv256 Mar 24, 2026
285eac6
feat: mesh thingy in `BlockModelRenderState`
sylv256 Mar 24, 2026
8d612d2
Work
PepperCode1 Mar 26, 2026
d2385c9
Work II
PepperCode1 Mar 27, 2026
d9423de
Remove QuadConsumers.ValidateAtlasUsage and promote one TODO to FIXME
PepperCode1 Mar 27, 2026
2062429
Merge remote-tracking branch 'origin/26.1' into rendering-1
sylv256 Mar 27, 2026
3ba4d87
fix: crash when mannequin is present
sylv256 Mar 27, 2026
b469a2f
docs: some docs, I guess
sylv256 Mar 27, 2026
fc2513c
fix: apply mixin suggestions
sylv256 Mar 27, 2026
0e0bf83
feat: `QuadView#animated`
sylv256 Mar 27, 2026
0a9b004
chore: docs
Kilip1000 Mar 27, 2026
f7d6c95
chore: fix checkstyle
Kilip1000 Mar 28, 2026
067f483
Docs
PepperCode1 Mar 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ interface Context {

/**
* The baker being used to bake this model. It can be used to
* {@linkplain ModelBaker#getModel get resolved models} and {@linkplain ModelBaker#sprites get sprites}. Note
* {@linkplain ModelBaker#getModel get resolved models} and {@linkplain ModelBaker#materials get materials}. Note
* that retrieving a model which was not previously
* {@linkplain ResolvableModel.Resolver#markDependency discovered} will log a warning and return the missing
* model.
Expand Down Expand Up @@ -182,7 +182,7 @@ interface Context {

/**
* The baker being used to bake this model. It can be used to
* {@linkplain ModelBaker#getModel get resolved models} and {@linkplain ModelBaker#sprites get sprites}. Note
* {@linkplain ModelBaker#getModel get resolved models} and {@linkplain ModelBaker#materials get materials}. Note
* that retrieving a model which was not previously
* {@linkplain ResolvableModel.Resolver#markDependency discovered} will log a warning and return the missing
* model.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,22 @@

import java.util.function.BiFunction;

import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.BlockStateModel;
import net.minecraft.client.renderer.block.model.SimpleModelWrapper;
import net.minecraft.client.renderer.block.model.SingleVariant;
import net.minecraft.client.renderer.block.model.TextureSlots;
import net.minecraft.client.resources.model.BlockModelRotation;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.QuadCollection;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.resources.Identifier;

import net.fabricmc.fabric.api.client.renderer.v1.model.MeshQuadCollection;
import net.fabricmc.fabric.api.client.renderer.v1.model.ModelHelper;
import net.fabricmc.fabric.api.client.renderer.v1.sprite.SpriteFinder;

/**
* A {@link UnbakedExtraModel} that loads a single model.
*
Expand Down Expand Up @@ -76,10 +82,36 @@ public static SimpleUnbakedExtraModel<BlockStateModel> blockStateModel(Identifie
public static SimpleUnbakedExtraModel<BlockStateModel> blockStateModel(Identifier model, ModelState settings) {
return new SimpleUnbakedExtraModel<>(model, (baked, baker) -> {
TextureSlots textures = baked.getTopTextureSlots();
QuadCollection quads = baked.bakeTopGeometry(
textures,
baker,
settings
);

final boolean[] hasTranslucency = {false};

if (quads instanceof MeshQuadCollection meshQuads) {
meshQuads.getMesh().forEach(quad -> {
SpriteFinder spriteFinder = baker.materials().spriteFinder(quad.atlas());
hasTranslucency[0] |= ModelHelper.computeSpriteInfo(spriteFinder.find(quad), quad)
.layer()
.translucent();
});
} else {
// SimpleModelWrapper#bake does this as well
for (BakedQuad quad : quads.getAll()) {
if (quad.spriteInfo().layer().translucent()) {
hasTranslucency[0] = true;
break;
}
}
}

return new SingleVariant(new SimpleModelWrapper(
baked.bakeTopGeometry(textures, baker, settings),
quads,
baked.getTopAmbientOcclusion(),
baked.resolveParticleSprite(textures, baker)
baked.resolveParticleMaterial(textures, baker),
hasTranslucency[0]
));
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

import net.minecraft.client.renderer.block.model.BlockModelPart;
import net.minecraft.client.renderer.block.model.BlockStateModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.block.model.Material;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
Expand Down Expand Up @@ -57,8 +57,8 @@ public List<BlockModelPart> collectParts(RandomSource random) {
}

@Override
public TextureAtlasSprite particleIcon() {
return wrapped.particleIcon();
public Material.Baked particleMaterial() {
return wrapped.particleMaterial();
}

@Override
Expand All @@ -73,7 +73,12 @@ public Object createGeometryKey(BlockAndTintGetter level, BlockPos pos, BlockSta
}

@Override
public TextureAtlasSprite particleIcon(BlockAndTintGetter level, BlockPos pos, BlockState state) {
return wrapped.particleIcon(level, pos, state);
public Material.Baked particleMaterial(BlockAndTintGetter level, BlockPos pos, BlockState state) {
return wrapped.particleMaterial(level, pos, state);
}

@Override
public boolean hasTranslucency() {
return wrapped.hasTranslucency();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

import net.minecraft.client.renderer.block.model.BlockModelPart;
import net.minecraft.client.renderer.block.model.BlockStateModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.block.model.Material;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
Expand All @@ -46,10 +46,22 @@ public class CompositeBlockStateModelImpl implements CompositeBlockStateModel {
private final BlockStateModel[] models;
@UnmodifiableView
private final List<BlockStateModel> modelsView;
private final boolean hasTranslucency;

public CompositeBlockStateModelImpl(BlockStateModel[] models) {
this.models = models;
modelsView = Arrays.asList(models);

boolean hasTranslucency = false;

for (BlockStateModel model : this.models) {
if (model.hasTranslucency()) {
hasTranslucency = true;
break;
}
}

this.hasTranslucency = hasTranslucency;
}

public static CompositeBlockStateModelImpl of(List<BlockStateModel> models) {
Expand Down Expand Up @@ -118,13 +130,18 @@ record Key(List<Object> subkeys) {
}

@Override
public TextureAtlasSprite particleIcon() {
return models[0].particleIcon();
public Material.Baked particleMaterial() {
return models[0].particleMaterial();
}

@Override
public boolean hasTranslucency() {
return this.hasTranslucency;
}

@Override
public TextureAtlasSprite particleIcon(BlockAndTintGetter level, BlockPos pos, BlockState state) {
return models[0].particleIcon(level, pos, state);
public Material.Baked particleMaterial(BlockAndTintGetter level, BlockPos pos, BlockState state) {
return models[0].particleMaterial(level, pos, state);
}

public record Unbaked(@Unmodifiable List<BlockStateModel.Unbaked> models) implements CompositeBlockStateModel.Unbaked {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void submit(PoseStack poseStack, SubmitNodeCollector nodeCollector, int l
poseStack.translate(-0.5F, 0.75F + aboveHead, -0.5F);
// FIXME 1.21.9
// FabricBlockModelRenderer.render(matrices.peek(), RenderLayerHelper.entityDelegate(bufferSource), model, 1, 1, 1, light, OverlayTexture.DEFAULT_UV, EmptyBlockRenderView.INSTANCE, BlockPos.ORIGIN, Blocks.AIR.getDefaultState());
nodeCollector.order(0).submitBlockModel(poseStack, Sheets.cutoutBlockSheet(), model, 1, 1, 1, light, OverlayTexture.NO_OVERLAY, 0);
nodeCollector.order(0).submitBlockModel(poseStack, Sheets.cutoutBlockSheet(), model, -1, light, OverlayTexture.NO_OVERLAY, 0);
poseStack.popPose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.jspecify.annotations.Nullable;

import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.BakedQuadOutput;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.block.model.BlockStateModel;
Expand All @@ -43,7 +44,6 @@
import net.fabricmc.fabric.api.client.renderer.v1.render.FabricBlockRenderDispatcher;
import net.fabricmc.fabric.api.client.renderer.v1.render.FabricLayerRenderState;
import net.fabricmc.fabric.api.client.renderer.v1.render.FabricModelBlockRenderer;
import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter;
import net.fabricmc.fabric.impl.client.renderer.RendererManager;

/**
Expand All @@ -55,15 +55,15 @@
* {@link SectionCompiler} in vanilla; this code is not patched automatically. Renderers must also ensure that the
* following vanilla methods support {@link BlockStateModel#emitQuads}; these methods are not patched automatically.
*
* <ul><li>{@link ModelBlockRenderer#renderModel(PoseStack.Pose, VertexConsumer, BlockStateModel, float, float, float, int, int)}
* <ul><li>{@link ModelBlockRenderer#renderModel(PoseStack.Pose, BakedQuadOutput, BlockStateModel, int, int, int)}
*
* <li>{@link BlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer)}
*
* <li>{@link BlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, int, int)}</ul>
*
* <p>All other places in vanilla code that invoke {@link BlockStateModel#collectParts(RandomSource, List)},
* {@link BlockStateModel#collectParts(RandomSource)}, or
* {@link ModelBlockRenderer#renderModel(PoseStack.Pose, VertexConsumer, BlockStateModel, float, float, float, int, int)}
* {@link ModelBlockRenderer#renderModel(PoseStack.Pose, BakedQuadOutput, BlockStateModel, int, int, int)}
* are, where appropriate, patched automatically to invoke the corresponding method above or the corresponding method in
* {@link FabricModelBlockRenderer} or {@link FabricBlockRenderDispatcher}.
*/
Expand Down Expand Up @@ -96,26 +96,26 @@ static Renderer get() {
void tesselateBlock(ModelBlockRenderer blockRenderer, BlockAndTintGetter level, BlockStateModel model, BlockState state, BlockPos pos, PoseStack poseStack, BlockMultiBufferSource bufferSource, @Nullable Predicate<ChunkSectionLayer> layerFilter, boolean cull, long seed, int overlay);

/**
* @see FabricModelBlockRenderer#renderModel(PoseStack.Pose, BlockMultiBufferSource, Predicate, BlockStateModel, float, float, float, int, int, BlockAndTintGetter, BlockPos, BlockState)
* @see FabricModelBlockRenderer#renderModel(PoseStack.Pose, BlockMultiBufferSource, Predicate, BlockStateModel, int, int, int, BlockAndTintGetter, BlockPos, BlockState)
*/
@ApiStatus.OverrideOnly
void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, @Nullable Predicate<ChunkSectionLayer> layerFilter, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state);
void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, @Nullable Predicate<ChunkSectionLayer> layerFilter, BlockStateModel model, int tint, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state);

/**
* @see FabricBlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, Predicate, int, int, BlockAndTintGetter, BlockPos)
* @see FabricBlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer)
*/
@ApiStatus.OverrideOnly
void renderSingleBlock(BlockRenderDispatcher renderDispatcher, BlockState state, PoseStack poseStack, MultiBufferSource bufferSource, @Nullable Predicate<ChunkSectionLayer> layerFilter, int light, int overlay, BlockAndTintGetter level, BlockPos pos);
void renderBreakingTexture(BlockRenderDispatcher renderDispatcher, BlockState state, BlockPos pos, BlockAndTintGetter level, PoseStack poseStack, VertexConsumer vertexConsumer);

/**
* @see FabricLayerRenderState#emitter()
* @see FabricBlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, Predicate, int, int, BlockAndTintGetter, BlockPos)
*/
@ApiStatus.OverrideOnly
QuadEmitter getLayerRenderStateEmitter(ItemStackRenderState.LayerRenderState layer);
void renderSingleBlock(BlockRenderDispatcher renderDispatcher, BlockState state, PoseStack poseStack, MultiBufferSource bufferSource, @Nullable Predicate<ChunkSectionLayer> layerFilter, int light, int overlay, BlockAndTintGetter level, BlockPos pos);

/**
* @see FabricLayerRenderState#setRenderTypeGetter(ItemRenderTypeGetter)
* @see FabricLayerRenderState#emitter()
*/
@ApiStatus.OverrideOnly
void setLayerRenderTypeGetter(ItemStackRenderState.LayerRenderState layer, ItemRenderTypeGetter renderTypeGetter);
QuadEmitter getLayerRenderStateEmitter(ItemStackRenderState.LayerRenderState layer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@
import org.jspecify.annotations.Nullable;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.renderer.rendertype.RenderType;
import net.minecraft.client.renderer.texture.SpriteContents;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;

import net.fabricmc.fabric.api.client.renderer.v1.render.FabricLayerRenderState;
import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter;
import net.fabricmc.fabric.api.client.renderer.v1.model.ModelHelper;
import net.fabricmc.fabric.api.client.renderer.v1.sprite.SpriteFinder;
import net.fabricmc.fabric.api.util.TriState;
import net.fabricmc.fabric.impl.client.renderer.QuadSpriteBaker;

Expand Down Expand Up @@ -188,7 +188,7 @@ default MutableQuadView uv(int vertexIndex, Vector2fc uv) {
*/
default MutableQuadView spriteBake(TextureAtlasSprite sprite, int bakeFlags) {
QuadSpriteBaker.bakeSprite(this, sprite, bakeFlags);
QuadAtlas atlas = QuadAtlas.of(sprite.atlasLocation());
QuadAtlas atlas = QuadAtlas.ofLocation(sprite.atlasLocation());

if (atlas == null) {
atlas = QuadAtlas.BLOCK;
Expand Down Expand Up @@ -278,18 +278,65 @@ default MutableQuadView normal(int vertexIndex, Vector3fc normal) {
MutableQuadView cullFace(@Nullable Direction face);

/**
* Controls how this quad's pixels should be blended with the scene.
* Controls how this quad's pixels should be blended with the scene in block form.
*
* <p>If set to {@code null}, {@link ItemBlockRenderTypes#getChunkRenderType(BlockState)} will be used to retrieve
* the {@linkplain ChunkSectionLayer chunk layer} in block contexts. Set to another value to override this behavior.
*
* <p>In block contexts, a non-null value will be used directly. In item contexts, any value will be converted to a
* {@link RenderType} using {@link FabricLayerRenderState#setRenderTypeGetter(ItemRenderTypeGetter)}.
* <p>If set to {@code null}, {@link ModelHelper#computeSpriteInfo(TextureAtlasSprite, QuadView)} will be used to retrieve
* the {@linkplain ChunkSectionLayer chunk layer}. Set to another value to override this behavior.
*
* <p>The default value is {@code null}.
*
* <p>This property is respected only in block contexts. It will not have an effect in other contexts.
*/
MutableQuadView chunkLayer(@Nullable ChunkSectionLayer layer);

/**
* When computing a value, this method also sets the {@link #chunkLayer()} value.
*
* @return this quad's {@link ChunkSectionLayer} or a default determined by the sprite's
* {@linkplain SpriteContents#computeTransparency(float, float, float, float) transparency}.
* @see #chunkLayer()
*/
default ChunkSectionLayer getOrResolveChunkLayer(SpriteFinder spriteFinder) {
if (chunkLayer() == null) {
ChunkSectionLayer layer = ModelHelper.computeSpriteInfo(spriteFinder.find(this), this)
.layer();
chunkLayer(layer);
return layer;
}

return chunkLayer();
}

/**
* Controls how this quad should be rendered in item form.
*
* <p>If set to {@code null}, {@link ModelHelper#computeSpriteInfo(TextureAtlasSprite, QuadView)} will be used to retrieve
* the {@linkplain RenderType item RenderType}. Set to another value to override this behavior.
*
* <p>The default value is {@code null}.
*
* <p>This property is respected only in item contexts. It will not have an effect in other contexts.
*/
MutableQuadView itemRenderType(@Nullable RenderType renderType);

/**
* When computing a value, this method also sets the {@link #itemRenderType()} value.
*
* @return this quad's {@linkplain RenderType item RenderType} or a default determined by the sprite's
* {@linkplain SpriteContents#computeTransparency(float, float, float, float) transparency}.
* @see #itemRenderType()
*/
default RenderType getOrResolveItemRenderType(SpriteFinder spriteFinder) {
if (itemRenderType() == null) {
RenderType renderType = ModelHelper.computeSpriteInfo(spriteFinder.find(this), this)
.itemRenderType();
itemRenderType(renderType);
return renderType;
}

return itemRenderType();
}

/**
* When true, this quad will be rendered at full brightness.
* Lightmap values provided via {@link QuadEmitter#lightmap(int)} will be ignored.
Expand Down Expand Up @@ -358,7 +405,7 @@ default MutableQuadView normal(int vertexIndex, Vector3fc normal) {
* Sets the {@linkplain QuadAtlas atlas texture} used by this quad.
*
* <p>In block contexts, this property must be {@link QuadAtlas#BLOCK}. In item contexts, this property will be
* converted to a {@link RenderType} using {@link FabricLayerRenderState#setRenderTypeGetter(ItemRenderTypeGetter)}.
* converted to a {@link RenderType} using {@link #getOrResolveItemRenderType(SpriteFinder)}.
*
* <p>The default value is {@link QuadAtlas#BLOCK}.
*
Expand Down
Loading
Loading