diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java index 65e2fd9223..fbb932224c 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java @@ -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. @@ -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. diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/SimpleUnbakedExtraModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/SimpleUnbakedExtraModel.java index 7be91f8af5..dd175ac59f 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/SimpleUnbakedExtraModel.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/SimpleUnbakedExtraModel.java @@ -18,22 +18,40 @@ import java.util.function.BiFunction; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.mojang.logging.LogUtils; +import org.apache.commons.lang3.mutable.MutableBoolean; +import org.apache.commons.lang3.mutable.MutableObject; +import org.slf4j.Logger; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.BlockModelPart; import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.block.model.Material; 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.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; 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.mesh.QuadAtlas; +import net.fabricmc.fabric.api.client.renderer.v1.model.MeshQuadCollection; + /** * A {@link UnbakedExtraModel} that loads a single model. * * @param The type of the baked model, for instance {@link BlockStateModel}. */ public final class SimpleUnbakedExtraModel implements UnbakedExtraModel { + private static final Logger LOGGER = LogUtils.getLogger(); + private final Identifier model; private final BiFunction bake; @@ -69,19 +87,68 @@ public static SimpleUnbakedExtraModel blockStateModel(Identifie /** * Create a {@link SimpleUnbakedExtraModel} for a {@link BlockStateModel}. * - * @param model The location of the model to load. - * @param settings The settings to bake the geometry with. + * @param model The location of the model to load. + * @param state The state to bake the geometry with. * @return The unbaked extra model. */ - public static SimpleUnbakedExtraModel blockStateModel(Identifier model, ModelState settings) { - return new SimpleUnbakedExtraModel<>(model, (baked, baker) -> { - TextureSlots textures = baked.getTopTextureSlots(); - return new SingleVariant(new SimpleModelWrapper( - baked.bakeTopGeometry(textures, baker, settings), - baked.getTopAmbientOcclusion(), - baked.resolveParticleSprite(textures, baker) - )); - }); + public static SimpleUnbakedExtraModel blockStateModel(Identifier model, ModelState state) { + return new SimpleUnbakedExtraModel<>(model, (baked, baker) -> new SingleVariant(bakeResolved(baker, baked, state))); + } + + // TODO: expose this as a public utility + // Mirror of SimpleModelWrapper#bake (with FRAPI's mixin) that accepts a ResolvedModel instead of an Identifier + private static BlockModelPart bakeResolved(final ModelBaker modelBakery, final ResolvedModel model, final ModelState state) { + TextureSlots textureSlots = model.getTopTextureSlots(); + boolean hasAmbientOcclusion = model.getTopAmbientOcclusion(); + Material.Baked particleMaterial = model.resolveParticleMaterial(textureSlots, modelBakery); + QuadCollection geometry = model.bakeTopGeometry(textureSlots, modelBakery, state); + boolean hasTranslucency = false; + Multimap forbiddenSprites = null; + + if (geometry instanceof MeshQuadCollection meshQuadCollection) { + MutableBoolean hasTranslucencyRef = new MutableBoolean(hasTranslucency); + MutableObject> forbiddenSpritesRef = new MutableObject<>(forbiddenSprites); + + meshQuadCollection.getMesh().forEach(quad -> { + if (quad.atlas() != QuadAtlas.BLOCK) { + Multimap forbiddenSprites1 = forbiddenSpritesRef.get(); + + if (forbiddenSprites1 == null) { + forbiddenSprites1 = HashMultimap.create(); + forbiddenSpritesRef.setValue(forbiddenSprites1); + } + + TextureAtlasSprite sprite = modelBakery.materials().spriteFinder(quad.atlas()).find(quad); + forbiddenSprites1.put(sprite.atlasLocation(), sprite.contents().name()); + } + + hasTranslucencyRef.setValue(hasTranslucencyRef.booleanValue() | quad.chunkLayer().translucent()); + }); + + hasTranslucency = hasTranslucencyRef.booleanValue(); + forbiddenSprites = forbiddenSpritesRef.get(); + } + + for (BakedQuad bakedQuad : geometry.getAll()) { + TextureAtlasSprite sprite = bakedQuad.spriteInfo().sprite(); + + if (!sprite.atlasLocation().equals(TextureAtlas.LOCATION_BLOCKS)) { + if (forbiddenSprites == null) { + forbiddenSprites = HashMultimap.create(); + } + + forbiddenSprites.put(sprite.atlasLocation(), sprite.contents().name()); + } + + hasTranslucency |= bakedQuad.spriteInfo().layer().translucent(); + } + + if (forbiddenSprites != null) { + LOGGER.warn("Rejecting block model {}, since it contains sprites from outside of supported atlas: {}", model.debugName(), forbiddenSprites); + return modelBakery.missingBlockModelPart(); + } else { + return new SimpleModelWrapper(geometry, hasAmbientOcclusion, particleMaterial, hasTranslucency); + } } @Override diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBlockStateModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBlockStateModel.java index bcada8f96d..c3bedc3587 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBlockStateModel.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBlockStateModel.java @@ -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; @@ -57,8 +57,8 @@ public List collectParts(RandomSource random) { } @Override - public TextureAtlasSprite particleIcon() { - return wrapped.particleIcon(); + public Material.Baked particleMaterial() { + return wrapped.particleMaterial(); } @Override @@ -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(); } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/CompositeBlockStateModelImpl.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/CompositeBlockStateModelImpl.java index de344a2e40..f0c15eed1a 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/CompositeBlockStateModelImpl.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/CompositeBlockStateModelImpl.java @@ -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; @@ -46,10 +46,22 @@ public class CompositeBlockStateModelImpl implements CompositeBlockStateModel { private final BlockStateModel[] models; @UnmodifiableView private final List 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 models) { @@ -118,13 +130,18 @@ record Key(List 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 models) implements CompositeBlockStateModel.Unbaked { diff --git a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelRenderLayer.java b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelRenderLayer.java index 4f92befbd5..80d423ab8f 100644 --- a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelRenderLayer.java +++ b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelRenderLayer.java @@ -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(); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/Renderer.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/Renderer.java index 9d0160323e..d227de09d6 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/Renderer.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/Renderer.java @@ -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; @@ -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; /** @@ -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. * - *
  • {@link ModelBlockRenderer#renderModel(PoseStack.Pose, VertexConsumer, BlockStateModel, float, float, float, int, int)} - * - *
  • {@link BlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer)} - * - *
  • {@link BlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, int, int)}
+ *
  • {@link BlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, int, int)}
* *

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 BlockStateModel#collectParts(RandomSource)}, + * {@link BlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, BakedQuadOutput)}, + * {@link BlockRenderDispatcher#renderBatched(BlockState, BlockPos, BlockAndTintGetter, PoseStack, BakedQuadOutput, boolean, List)}, + * {@link ModelBlockRenderer#tesselateBlock(BlockAndTintGetter, List, BlockState, BlockPos, PoseStack, BakedQuadOutput, boolean, int)}, + * or + * {@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}. */ @@ -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 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 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 layerFilter, BlockStateModel model, int tintColor, 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 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 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); } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/MutableQuadView.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/MutableQuadView.java index 78573cd2fd..55798a482e 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/MutableQuadView.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/MutableQuadView.java @@ -23,8 +23,9 @@ import org.jspecify.annotations.Nullable; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.item.ItemStackRenderState; import net.minecraft.client.renderer.rendertype.RenderType; @@ -32,8 +33,8 @@ 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; @@ -54,25 +55,25 @@ public interface MutableQuadView extends QuadView { /** * When enabled, causes texture to appear with no rotation. This is the default and does not have to be specified * explicitly. Can be overridden by other rotation flags. - * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * Pass in bakeFlags parameter to {@link #materialBake(Material.Baked, int)}. */ int BAKE_ROTATE_NONE = 0; /** * When enabled, causes texture to appear rotated 90 degrees clockwise. - * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * Pass in bakeFlags parameter to {@link #materialBake(Material.Baked, int)}. */ int BAKE_ROTATE_90 = 1; /** * When enabled, causes texture to appear rotated 180 degrees. - * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * Pass in bakeFlags parameter to {@link #materialBake(Material.Baked, int)}. */ int BAKE_ROTATE_180 = 2; /** * When enabled, causes texture to appear rotated 270 degrees clockwise. - * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * Pass in bakeFlags parameter to {@link #materialBake(Material.Baked, int)}. */ int BAKE_ROTATE_270 = 3; @@ -80,7 +81,7 @@ public interface MutableQuadView extends QuadView { * When enabled, texture coordinates are assigned based on vertex positions and the * {@linkplain #nominalFace() nominal face}. * Any existing UV coordinates will be replaced and the {@link #BAKE_NORMALIZED} flag will be ignored. - * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * Pass in bakeFlags parameter to {@link #materialBake(Material.Baked, int)}. * *

UV lock derives texture coordinates based on {@linkplain #nominalFace() nominal face} by projecting the quad * onto it, even when the quad is not co-planar with it. This flag is ignored if the normal face is {@code null}. @@ -93,7 +94,7 @@ public interface MutableQuadView extends QuadView { * and texture mapping scenarios. Results are different from what * can be obtained via rotation and both can be applied. Any * rotation is applied before this flag. - * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * Pass in bakeFlags parameter to {@link #materialBake(Material.Baked, int)}. */ int BAKE_FLIP_U = 8; @@ -107,7 +108,7 @@ public interface MutableQuadView extends QuadView { * with conventional Minecraft model format. This is scaled to 0-1 during * baking before interpolation. Model loaders that already have 0-1 coordinates * can avoid wasteful multiplication/division by passing 0-1 coordinates directly. - * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * Pass in bakeFlags parameter to {@link #materialBake(Material.Baked, int)}. */ int BAKE_NORMALIZED = 32; @@ -182,19 +183,25 @@ default MutableQuadView uv(int vertexIndex, Vector2fc uv) { } /** - * Sets the texture coordinates for all vertices using the given sprite. Also sets this quad's atlas to the given - * sprite's atlas. Can handle UV locking, rotation, interpolation, etc. Control this behavior by passing additive - * combinations of the BAKE_ flags defined in this interface. + * Sets the texture coordinates for all vertices using the given material's sprite. Also sets this quad's + * {@linkplain #atlas(QuadAtlas) atlas}, {@linkplain #chunkLayer(ChunkSectionLayer) chunk layer}, and + * {@linkplain #itemRenderType(RenderType) item render type} to appropriate values based on the given material. Can + * handle UV locking, rotation, interpolation, etc. Control this behavior by passing additive combinations of the + * BAKE_ flags defined in this interface. */ - default MutableQuadView spriteBake(TextureAtlasSprite sprite, int bakeFlags) { - QuadSpriteBaker.bakeSprite(this, sprite, bakeFlags); - QuadAtlas atlas = QuadAtlas.of(sprite.atlasLocation()); + default MutableQuadView materialBake(Material.Baked material, int bakeFlags) { + QuadSpriteBaker.bakeSprite(this, material.sprite(), bakeFlags); + QuadAtlas atlas = QuadAtlas.ofLocation(material.sprite().atlasLocation()); if (atlas == null) { atlas = QuadAtlas.BLOCK; } atlas(atlas); + // TODO 26.1: allow invoking this separately as a method in this interface + BakedQuad.SpriteInfo spriteInfo = ModelHelper.computeSpriteInfo(material, this); + chunkLayer(spriteInfo.layer()); + itemRenderType(spriteInfo.itemRenderType()); return this; } @@ -252,7 +259,7 @@ default MutableQuadView normal(int vertexIndex, Vector3fc normal) { * but if set, should be the expected value of {@link #lightFace()}. It may be used to shortcut geometric analysis, * if the provided value was correct; otherwise, it is ignored. * - *

The nominal face is also used for {@link #spriteBake(TextureAtlasSprite, int)} with {@link #BAKE_LOCK_UV}. + *

The nominal face is also used for {@link #materialBake(Material.Baked, int)} with {@link #BAKE_LOCK_UV}. * *

When {@link #cullFace(Direction)} is called, it also sets the nominal face. * @@ -278,17 +285,46 @@ default MutableQuadView normal(int vertexIndex, Vector3fc normal) { MutableQuadView cullFace(@Nullable Direction face); /** - * Controls how this quad's pixels should be blended with the scene. + * Sets the {@linkplain QuadAtlas atlas texture} used by this quad. This property is mainly used to retrieve this + * quad's {@linkplain TextureAtlasSprite sprite} via the appropriate atlas' {@link SpriteFinder}. * - *

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. + *

In block contexts, this property must be {@link QuadAtlas#BLOCK}. * - *

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)}. + *

The default value is {@link QuadAtlas#BLOCK}. * - *

The default value is {@code null}. + * @see QuadAtlas + */ + MutableQuadView atlas(QuadAtlas quadAtlas); + + /** + * Controls how this quad should be rendered after buffering in block contexts. + * + *

The default value is {@link ChunkSectionLayer#CUTOUT}. + * + *

This property is respected only in block contexts. It will not have an effect in other contexts. + */ + MutableQuadView chunkLayer(ChunkSectionLayer layer); + + // TODO 26.1: allow using any RenderType + /** + * Controls how this quad should be rendered after buffering in item contexts. The atlas texture used by the set + * render type must match this quad's {@linkplain #atlas(QuadAtlas) atlas}. + * + *

Only the following values are allowed: + *

    + *
  • {@link Sheets#cutoutItemSheet()} + *
  • {@link Sheets#translucentItemSheet()} + *
  • {@link Sheets#cutoutBlockItemSheet()} + *
  • {@link Sheets#translucentBlockItemSheet()} + *
+ * + *

If this method is invoked with any value not in the above list, it will no-op. + * + *

The default value is {@link Sheets#cutoutBlockItemSheet()}. + * + *

This property is respected only in item contexts. It will not have an effect in other contexts. */ - MutableQuadView chunkLayer(@Nullable ChunkSectionLayer layer); + MutableQuadView itemRenderType(RenderType renderType); /** * When true, this quad will be rendered at full brightness. @@ -354,18 +390,6 @@ default MutableQuadView normal(int vertexIndex, Vector3fc normal) { */ MutableQuadView shadeMode(ShadeMode mode); - /** - * Sets the {@linkplain QuadAtlas atlas texture} used by this quad. - * - *

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)}. - * - *

The default value is {@link QuadAtlas#BLOCK}. - * - * @see QuadAtlas - */ - MutableQuadView atlas(QuadAtlas quadAtlas); - /** * Sets the tint index, which is used to retrieve the tint color. * diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadAtlas.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadAtlas.java index dca0f755e0..7d5ecf80d7 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadAtlas.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadAtlas.java @@ -19,29 +19,32 @@ import org.jspecify.annotations.Nullable; import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.data.AtlasIds; import net.minecraft.resources.Identifier; /** * An atlas texture that a {@link QuadView} uses. */ public enum QuadAtlas { - BLOCK(TextureAtlas.LOCATION_BLOCKS), - ITEM(TextureAtlas.LOCATION_ITEMS); + BLOCK(TextureAtlas.LOCATION_BLOCKS, AtlasIds.BLOCKS), + ITEM(TextureAtlas.LOCATION_ITEMS, AtlasIds.ITEMS); - private final Identifier textureId; + private final Identifier textureLocation; + private final Identifier id; - QuadAtlas(Identifier textureId) { - this.textureId = textureId; + QuadAtlas(Identifier textureLocation, Identifier id) { + this.textureLocation = textureLocation; + this.id = id; } /** - * {@return the quad atlas for the given atlas texture ID or null if no corresponding quad atlas exists} + * {@return the quad atlas for the given atlas texture location or null if no corresponding quad atlas exists} */ @Nullable - public static QuadAtlas of(Identifier atlasTextureId) { - if (atlasTextureId.equals(TextureAtlas.LOCATION_BLOCKS)) { + public static QuadAtlas ofLocation(Identifier atlasTextureLocation) { + if (atlasTextureLocation.equals(TextureAtlas.LOCATION_BLOCKS)) { return BLOCK; - } else if (atlasTextureId.equals(TextureAtlas.LOCATION_ITEMS)) { + } else if (atlasTextureLocation.equals(TextureAtlas.LOCATION_ITEMS)) { return ITEM; } else { return null; @@ -49,9 +52,30 @@ public static QuadAtlas of(Identifier atlasTextureId) { } /** - * {@return the atlas texture ID} + * {@return the quad atlas for the given atlas ID or null if no corresponding quad atlas exists} */ - public Identifier getTextureId() { - return textureId; + @Nullable + public static QuadAtlas ofId(Identifier atlasId) { + if (atlasId.equals(AtlasIds.BLOCKS)) { + return BLOCK; + } else if (atlasId.equals(AtlasIds.ITEMS)) { + return ITEM; + } else { + return null; + } + } + + /** + * @return the atlas texture location (ends with {@code .png}) + */ + public Identifier getTextureLocation() { + return textureLocation; + } + + /** + * @return the atlas ID + */ + public Identifier getId() { + return id; } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadEmitter.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadEmitter.java index b2146601a4..91c4bea3b1 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadEmitter.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadEmitter.java @@ -23,9 +23,10 @@ import org.jspecify.annotations.Nullable; import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.core.Direction; import net.fabricmc.fabric.api.util.TriState; @@ -80,8 +81,8 @@ default QuadEmitter uv(int vertexIndex, Vector2fc uv) { } @Override - default QuadEmitter spriteBake(TextureAtlasSprite sprite, int bakeFlags) { - MutableQuadView.super.spriteBake(sprite, bakeFlags); + default QuadEmitter materialBake(Material.Baked material, int bakeFlags) { + MutableQuadView.super.materialBake(material, bakeFlags); return this; } @@ -124,7 +125,13 @@ default QuadEmitter normal(int vertexIndex, Vector3fc normal) { QuadEmitter cullFace(@Nullable Direction face); @Override - QuadEmitter chunkLayer(@Nullable ChunkSectionLayer layer); + QuadEmitter atlas(QuadAtlas quadAtlas); + + @Override + QuadEmitter chunkLayer(ChunkSectionLayer layer); + + @Override + QuadEmitter itemRenderType(RenderType renderType); @Override QuadEmitter emissive(boolean emissive); @@ -141,9 +148,6 @@ default QuadEmitter normal(int vertexIndex, Vector3fc normal) { @Override QuadEmitter shadeMode(ShadeMode mode); - @Override - QuadEmitter atlas(QuadAtlas quadAtlas); - @Override QuadEmitter tintIndex(int tintIndex); diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadView.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadView.java index 6b480d2d71..b624f71614 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadView.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/mesh/QuadView.java @@ -25,6 +25,7 @@ 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.TextureAtlasSprite; import net.minecraft.core.Direction; import net.minecraft.util.LightCoordsUtil; @@ -154,12 +155,21 @@ public interface QuadView { @Nullable Direction cullFace(); + /** + * @see MutableQuadView#atlas(QuadAtlas) + */ + QuadAtlas atlas(); + /** * @see MutableQuadView#chunkLayer(ChunkSectionLayer) */ - @Nullable ChunkSectionLayer chunkLayer(); + /** + * @see MutableQuadView#itemRenderType(RenderType) + */ + RenderType itemRenderType(); + /** * @see MutableQuadView#emissive(boolean) */ @@ -187,11 +197,6 @@ public interface QuadView { */ ShadeMode shadeMode(); - /** - * @see MutableQuadView#atlas(QuadAtlas) - */ - QuadAtlas atlas(); - /** * This method is equivalent to {@link BakedQuad#tintIndex()}. * @@ -210,7 +215,7 @@ public interface QuadView { * @param sprite The sprite is not serialized so it must be provided by the caller. Retrieve it using * {@link SpriteFinder#find(QuadView)} if it is not already known. */ - default BakedQuad toBakedQuad(BakedQuad.SpriteInfo sprite) { + default BakedQuad toBakedQuad(TextureAtlasSprite sprite) { Vector3f position0 = copyPos(0, null); Vector3f position1 = copyPos(1, null); Vector3f position2 = copyPos(2, null); @@ -220,6 +225,8 @@ default BakedQuad toBakedQuad(BakedQuad.SpriteInfo sprite) { long packedUV2 = UVPair.pack(u(2), v(2)); long packedUV3 = UVPair.pack(u(3), v(3)); + BakedQuad.SpriteInfo spriteInfo = new BakedQuad.SpriteInfo(sprite, chunkLayer(), itemRenderType()); + // The light emission is set to 15 if the quad is emissive; otherwise, to the minimum of all four sky light // values and all four block light values. int lightEmission = 15; @@ -250,7 +257,7 @@ default BakedQuad toBakedQuad(BakedQuad.SpriteInfo sprite) { packedUV3, tintIndex(), lightFace(), - sprite, + spriteInfo, diffuseShade(), lightEmission ); diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockModelShaper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockModelShaper.java index f23c4ab305..2519814476 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockModelShaper.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockModelShaper.java @@ -17,7 +17,7 @@ package net.fabricmc.fabric.api.client.renderer.v1.model; import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.EmptyBlockAndTintGetter; @@ -28,20 +28,20 @@ */ public interface FabricBlockModelShaper { /** - * Alternative for {@link BlockModelShaper#getParticleIcon(BlockState)} that additionally accepts a + * Alternative for {@link BlockModelShaper#getParticleMaterial(BlockState)} that additionally accepts a * {@link BlockAndTintGetter} and {@link BlockPos} to invoke - * {@link FabricBlockStateModel#particleIcon(BlockAndTintGetter, BlockPos, BlockState)}. Prefer using this method - * over the vanilla alternative when applicable to correctly retrieve context-aware particle sprites. If level + * {@link FabricBlockStateModel#particleMaterial(BlockAndTintGetter, BlockPos, BlockState)}. Prefer using this method + * over the vanilla alternative when applicable to correctly retrieve context-aware particle materials. If level * context is not available, use the vanilla method instead of passing empty level context to this method. * - * @param state The block state whose model to retrieve the particle sprite from. + * @param state The block state whose model to retrieve the particle material from. * @param level The level in which the block exists. Should not be empty (i.e. not * {@link EmptyBlockAndTintGetter}). * @param pos The position of the block in the level. - * @return the particle sprite + * @return the particle material */ - default TextureAtlasSprite getParticleIcon(BlockState state, BlockAndTintGetter level, BlockPos pos) { - return ((BlockModelShaper) this).getBlockModel(state).particleIcon( + default Material.Baked getParticleMaterial(BlockState state, BlockAndTintGetter level, BlockPos pos) { + return ((BlockModelShaper) this).getBlockModel(state).particleMaterial( level, pos, state); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockStateModel.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockStateModel.java index 71f65c1d46..d092b7a4fa 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockStateModel.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/FabricBlockStateModel.java @@ -23,8 +23,8 @@ import net.minecraft.client.renderer.block.model.BlockModelPart; import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.block.model.multipart.MultiPartModel; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; @@ -122,7 +122,7 @@ default Object createGeometryKey(BlockAndTintGetter level, BlockPos pos, BlockSt } /** - * Extension of {@link BlockStateModel#particleIcon()} that accepts level state. This method will be invoked most + * Extension of {@link BlockStateModel#particleMaterial()} that accepts level state. This method will be invoked most * of the time, but the vanilla method may still be invoked when no level context is available. * *

If your model delegates to other {@link BlockStateModel}s, ensure that it also delegates invocations of @@ -130,11 +130,11 @@ default Object createGeometryKey(BlockAndTintGetter level, BlockPos pos, BlockSt * * @param level The level in which the block exists. * @param pos The position of the block in the level. - * @param state The block state whose model was queried for the particle sprite. This is not guaranteed to be the + * @param state The block state whose model was queried for the particle material. This is not guaranteed to be the * state corresponding to {@code this} model! - * @return the particle sprite + * @return the particle material */ - default TextureAtlasSprite particleIcon(BlockAndTintGetter level, BlockPos pos, BlockState state) { - return ((BlockStateModel) this).particleIcon(); + default Material.Baked particleMaterial(BlockAndTintGetter level, BlockPos pos, BlockState state) { + return ((BlockStateModel) this).particleMaterial(); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/ModelHelper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/ModelHelper.java index 06b385d684..565df91bcf 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/ModelHelper.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/model/ModelHelper.java @@ -20,14 +20,20 @@ import java.util.List; import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.platform.Transparency; import org.jspecify.annotations.Nullable; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.Material; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.Direction; import net.minecraft.data.AtlasIds; import net.fabricmc.fabric.api.client.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.client.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadAtlas; +import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadView; import net.fabricmc.fabric.api.client.renderer.v1.sprite.SpriteFinder; /** @@ -42,6 +48,87 @@ public final class ModelHelper { private ModelHelper() { } + /** + * Computes a {@link BakedQuad.SpriteInfo} for a {@link Material.Baked}. + * + *

Warning: do not call this method while rendering as it does not cache the result. + * This method is meant primarily for baking. + */ + public static BakedQuad.SpriteInfo computeSpriteInfo(Material.Baked material, QuadView quad) { + Transparency transparency = material.forceTranslucent() ? Transparency.TRANSLUCENT : computeTransparency(material.sprite(), quad); + // TODO: Consider interning or some other caching scheme to reduce object churn + return BakedQuad.SpriteInfo.of(material, transparency); + } + + /** + * Computes {@link Transparency} for a {@link TextureAtlasSprite}. + * + *

Warning: do not call this method while rendering as it does not cache the result. + * This method is meant primarily for baking. + */ + public static Transparency computeTransparency(TextureAtlasSprite sprite, QuadView quad) { + // Find the minimum and maximum UV's. + // A simulation of the algorithm is provided in comments below. + float minU = Float.MAX_VALUE; // 7, 7, 5, 3 + float minV = Float.MAX_VALUE; // 9, 8, 8, 8 + float maxU = 0; // 7, 12, 12, 12 + float maxV = 0; // 9, 9, 10, 13 + + // u, v + // 7, 9 + // 12,8 + // 5, 10 + // 3, 13 + + for (int i = 0; i < 4; i++) { + float u = quad.u(i); + float v = quad.v(i); + + if (u < minU) { + minU = u; + } + + if (u > maxU) { + maxU = u; + } + + if (v < minV) { + minV = v; + } + + if (v > maxV) { + maxV = v; + } + } + + // Normalize UVs + // Inverse linear interpolation + // `(t_q - t_0)/Δt` where `t_q` is the value and `t` is `u` or `v` + final float width = 1.0f / (sprite.getU1() - sprite.getU0()); + final float height = 1.0f / (sprite.getV1() - sprite.getV0()); + minU = (minU - sprite.getU0()) * width; + minV = (minV - sprite.getV0()) * height; + maxU = (maxU - sprite.getU0()) * width; + maxV = (maxV - sprite.getV0()) * height; + + // See FaceBakery#computeMaterialTransparency + return sprite + .contents() + .computeTransparency(minU, minV, maxU, maxV); + } + + public static void setSpriteInfo(MutableQuadView quad, Material.Baked material) { + QuadAtlas atlas = QuadAtlas.ofLocation(material.sprite().atlasLocation()); + + if (atlas != null) { + quad.atlas(atlas); + } + + BakedQuad.SpriteInfo spriteInfo = computeSpriteInfo(material, quad); + quad.chunkLayer(spriteInfo.layer()); + quad.itemRenderType(spriteInfo.itemRenderType()); + } + /** * Convenient way to encode faces that may be null. * Null is returned as {@link #NULL_FACE_ID}. diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/ChunkSectionLayerHelper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/ChunkSectionLayerHelper.java index 92dce13566..647407db3c 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/ChunkSectionLayerHelper.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/ChunkSectionLayerHelper.java @@ -16,50 +16,27 @@ package net.fabricmc.fabric.api.client.renderer.v1.render; +import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; -import net.minecraft.client.renderer.rendertype.RenderType; -import net.minecraft.client.renderer.rendertype.RenderTypes; -import net.minecraft.world.level.block.state.BlockState; public final class ChunkSectionLayerHelper { private ChunkSectionLayerHelper() { } - /** - * Same logic as {@link net.minecraft.client.renderer.ItemBlockRenderTypes#getMovingBlockRenderType}, but accepts a {@link ChunkSectionLayer} instead of a - * {@link BlockState}. - */ - public static RenderType getMovingBlockLayer(ChunkSectionLayer layer) { - return switch (layer) { - case SOLID -> RenderTypes.solidMovingBlock(); - case CUTOUT -> RenderTypes.cutoutMovingBlock(); - case TRANSLUCENT -> RenderTypes.translucentMovingBlock(); - }; - } - - /** - * Same logic as {@link net.minecraft.client.renderer.ItemBlockRenderTypes#getRenderType}, but accepts a {@link ChunkSectionLayer} instead of a - * {@link BlockState}. - */ - public static RenderType getEntityBlockLayer(ChunkSectionLayer layer) { - return layer == ChunkSectionLayer.TRANSLUCENT ? Sheets.translucentBlockItemSheet() : Sheets.cutoutBlockSheet(); - } - /** * Wraps the given provider, converting {@link ChunkSectionLayer}s to render types using - * {@link #getMovingBlockLayer(ChunkSectionLayer)}. + * {@link ItemBlockRenderTypes#getMovingBlockRenderType(ChunkSectionLayer)}. */ public static BlockMultiBufferSource movingDelegate(MultiBufferSource bufferSource) { - return layer -> bufferSource.getBuffer(ChunkSectionLayerHelper.getMovingBlockLayer(layer)); + return layer -> bufferSource.getBuffer(ItemBlockRenderTypes.getMovingBlockRenderType(layer)); } /** * Wraps the given provider, converting {@link ChunkSectionLayer}s to render types using - * {@link #getEntityBlockLayer(ChunkSectionLayer)}. + * {@link ItemBlockRenderTypes#getRenderType(ChunkSectionLayer)}. */ public static BlockMultiBufferSource entityDelegate(MultiBufferSource bufferSource) { - return layer -> bufferSource.getBuffer(ChunkSectionLayerHelper.getEntityBlockLayer(layer)); + return layer -> bufferSource.getBuffer(ItemBlockRenderTypes.getRenderType(layer)); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricBlockRenderDispatcher.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricBlockRenderDispatcher.java index 515fd8f4f2..05b75ee939 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricBlockRenderDispatcher.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricBlockRenderDispatcher.java @@ -19,11 +19,15 @@ import java.util.function.Predicate; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator; +import com.mojang.blaze3d.vertex.VertexConsumer; 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.model.BlockStateModel; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.core.BlockPos; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; @@ -33,17 +37,36 @@ import net.fabricmc.fabric.api.client.renderer.v1.Renderer; import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadEmitter; +// TODO 26.1: update docs /** * Note: This interface is automatically implemented on {@link BlockRenderDispatcher} via Mixin and interface injection. */ public interface FabricBlockRenderDispatcher { + /** + * Alternative for + * {@link BlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, BakedQuadOutput)} + * that accepts a {@link VertexConsumer} instead of a {@link BakedQuadOutput}. Use this method instead of the + * vanilla alternative to correctly provide the model with a {@link VertexConsumer}. + * + * @param state The block state. + * @param pos The block position. + * @param level The level in which to render the breaking texture. Can be empty (i.e. {@link EmptyBlockAndTintGetter}). + * @param poseStack The pose stack. + * @param vertexConsumer The vertex consumer. Consider using {@link SheetedDecalTextureGenerator} in + * conjunction with one of {@link ModelBakery#DESTROY_TYPES} where the index is the breaking progress. + */ + default void renderBreakingTexture(BlockState state, BlockPos pos, BlockAndTintGetter level, PoseStack poseStack, VertexConsumer vertexConsumer) { + Renderer.get().renderBreakingTexture((BlockRenderDispatcher) this, + state, pos, level, poseStack, vertexConsumer); + } + /** * Alternative for * {@link BlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, int, int)} that * additionally accepts the {@link BlockAndTintGetter} and {@link BlockPos} to pass to * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)} - * when necessary. Prefer using this method over the vanilla alternative to correctly buffer models that have - * geometry on multiple chunk layers and to provide the model with additional context. + * when necessary. Use this method instead of the vanilla alternative to provide the model with additional + * context. * *

This method allows buffering a block model with minimal transformations to the model geometry. Usually used by * entity renderers. @@ -72,8 +95,8 @@ default void renderSingleBlock(BlockState state, PoseStack poseStack, MultiBuffe * {@link BlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, int, int)} that * additionally accepts the {@link BlockAndTintGetter} and {@link BlockPos} to pass to * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)} - * when necessary. Prefer using this method over the vanilla alternative to correctly buffer models that have - * geometry on multiple chunk layers and to provide the model with additional context. + * when necessary. Use this method instead of the vanilla alternative to provide the model with additional + * context. * *

This method allows buffering a block model with minimal transformations to the model geometry. Usually used by * entity renderers. diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricLayerRenderState.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricLayerRenderState.java index c6f441ee1f..00d9d93095 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricLayerRenderState.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricLayerRenderState.java @@ -20,7 +20,6 @@ import java.util.function.Supplier; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.rendertype.RenderType; import net.fabricmc.fabric.api.client.renderer.v1.Renderer; import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadEmitter; @@ -46,20 +45,4 @@ public interface FabricLayerRenderState { default QuadEmitter emitter() { return Renderer.get().getLayerRenderStateEmitter((ItemStackRenderState.LayerRenderState) this); } - - /** - * Sets the function that chooses the {@link RenderType} for quads added to this layer through {@link #emitter()} - * based on certain quad properties. This method has no effect on how - * {@linkplain ItemStackRenderState.LayerRenderState#prepareQuadList() vanilla quads} are rendered. If this function - * is not set, all non-vanilla quads in this layer will be rendered using this layer's - * {@linkplain ItemStackRenderState.LayerRenderState#setRenderType(RenderType) default render type}. If the - * function returns {@code null} for a certain combination of quad properties, then all non-vanilla quads with - * matching property values will use this layer's default render type. This layer's function will be unset on - * {@link ItemStackRenderState.LayerRenderState#clear()}. - * - * @see ItemRenderTypeGetter - */ - default void setRenderTypeGetter(ItemRenderTypeGetter renderTypeGetter) { - Renderer.get().setLayerRenderTypeGetter((ItemStackRenderState.LayerRenderState) this, renderTypeGetter); - } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricModelBlockRenderer.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricModelBlockRenderer.java index f399dfd6ad..6469d114d7 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricModelBlockRenderer.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricModelBlockRenderer.java @@ -23,6 +23,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +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; @@ -36,20 +37,21 @@ import net.fabricmc.fabric.api.client.renderer.v1.Renderer; import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadEmitter; +// TODO 26.1: update docs /** * Note: This interface is automatically implemented on {@link ModelBlockRenderer} via Mixin and interface injection. */ public interface FabricModelBlockRenderer { /** * Alternative for - * {@link ModelBlockRenderer#tesselateBlock(BlockAndTintGetter, List, BlockState, BlockPos, PoseStack, VertexConsumer, boolean, int)} + * {@link ModelBlockRenderer#tesselateBlock(BlockAndTintGetter, List, BlockState, BlockPos, PoseStack, BakedQuadOutput, boolean, int)} * and - * {@link BlockRenderDispatcher#renderBatched(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer, boolean, List)} + * {@link BlockRenderDispatcher#renderBatched(BlockState, BlockPos, BlockAndTintGetter, PoseStack, BakedQuadOutput, boolean, List)} * that accepts a {@link BlockStateModel} instead of a {@code List} and a - * {@link BlockMultiBufferSource} instead of a {@link VertexConsumer}. Also accepts the random seed. Prefer - * using this method over the vanilla alternative to correctly retrieve geometry from models that implement - * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)} - * and to correctly buffer models that have geometry on multiple {@linkplain ChunkSectionLayer chunk layers}. + * {@link BlockMultiBufferSource} instead of a {@link VertexConsumer}. Also accepts the random seed. Use this method + * instead of the vanilla alternative to correctly retrieve geometry from models that implement + * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)}. + * * *

This method allows buffering a block model in a terrain-like context, which usually includes stages like * culling, dynamic tinting, shading, and flat/smooth lighting. @@ -75,14 +77,14 @@ default void tesselateBlock(BlockAndTintGetter level, BlockStateModel model, Blo /** * Alternative for - * {@link ModelBlockRenderer#tesselateBlock(BlockAndTintGetter, List, BlockState, BlockPos, PoseStack, VertexConsumer, boolean, int)} + * {@link ModelBlockRenderer#tesselateBlock(BlockAndTintGetter, List, BlockState, BlockPos, PoseStack, BakedQuadOutput, boolean, int)} * and - * {@link BlockRenderDispatcher#renderBatched(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer, boolean, List)} + * {@link BlockRenderDispatcher#renderBatched(BlockState, BlockPos, BlockAndTintGetter, PoseStack, BakedQuadOutput, boolean, List)} * that accepts a {@link BlockStateModel} instead of a {@code List} and a - * {@link BlockMultiBufferSource} instead of a {@link VertexConsumer}. Also accepts the random seed. Prefer - * using this method over the vanilla alternative to correctly retrieve geometry from models that implement + * {@link BlockMultiBufferSource} instead of a {@link BakedQuadOutput}. Also accepts the random seed. Use this + * method instead of the vanilla alternative to correctly retrieve geometry from models that implement * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)} - * and to correctly buffer models that have geometry on multiple {@linkplain ChunkSectionLayer chunk layers}. + * * *

This method allows buffering a block model in a terrain-like context, which usually includes stages like * culling, dynamic tinting, shading, and flat/smooth lighting. @@ -106,12 +108,12 @@ default void tesselateBlock(BlockAndTintGetter level, BlockStateModel model, Blo /** * Alternative for - * {@link ModelBlockRenderer#renderModel(PoseStack.Pose, VertexConsumer, BlockStateModel, float, float, float, int, int)} - * that accepts a {@link BlockMultiBufferSource} instead of a {@link VertexConsumer}. Also accepts the + * {@link ModelBlockRenderer#renderModel(PoseStack.Pose, BakedQuadOutput, BlockStateModel, int, int, int)} + * that accepts a {@link BlockMultiBufferSource} instead of a {@link BakedQuadOutput}. Also accepts the * {@link BlockAndTintGetter}, {@link BlockPos}, and {@link BlockState} to pass to * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)} - * when necessary. Prefer using this method over the vanilla alternative to correctly buffer models that have - * geometry on multiple chunk layers and to provide the model with additional context. + * when necessary. Use this method instead of the vanilla alternative to provide the model with additional + * context. * *

This method allows buffering a block model with minimal transformations to the model geometry. Usually used by * entity renderers. @@ -121,9 +123,7 @@ default void tesselateBlock(BlockAndTintGetter level, BlockStateModel model, Blo * @param layerFilter Specifies the chunk layers for which geometry should be buffered ({@code true}) or discarded * ({@code false}). * @param model The model to render. - * @param red The red component of the tint color. - * @param green The green component of the tint color. - * @param blue The blue component of the tint color. + * @param tintColor The tint color. * @param light The minimum light value. * @param overlay The overlay value. * @param level The level in which to render the model. Can be empty (i.e. {@link EmptyBlockAndTintGetter}). @@ -131,22 +131,21 @@ default void tesselateBlock(BlockAndTintGetter level, BlockStateModel model, Blo * * @param state The block state. Should be {@code Blocks.AIR.getDefaultState()} if not applicable. * - * @see FabricOrderedSubmitNodeCollector#submitBlockModel(PoseStack, Function, BlockStateModel, float, float, float, int, int, int, BlockAndTintGetter, BlockPos, BlockState) + * @see FabricOrderedSubmitNodeCollector#submitBlockModel(PoseStack, Function, BlockStateModel, int, int, int, int, BlockAndTintGetter, BlockPos, BlockState) */ - static void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, Predicate layerFilter, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { + static void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, Predicate layerFilter, BlockStateModel model, int tintColor, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { Renderer.get().renderModel( - pose, bufferSource, layerFilter, model, red, green, - blue, light, overlay, level, pos, state); + pose, bufferSource, layerFilter, model, tintColor, light, overlay, level, pos, state); } /** * Alternative for - * {@link ModelBlockRenderer#renderModel(PoseStack.Pose, VertexConsumer, BlockStateModel, float, float, float, int, int)} - * that accepts a {@link BlockMultiBufferSource} instead of a {@link VertexConsumer}. Also accepts the + * {@link ModelBlockRenderer#renderModel(PoseStack.Pose, BakedQuadOutput, BlockStateModel, int, int, int)} + * that accepts a {@link BlockMultiBufferSource} instead of a {@link BakedQuadOutput}. Also accepts the * {@link BlockAndTintGetter}, {@link BlockPos}, and {@link BlockState} to pass to * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)} - * when necessary. Prefer using this method over the vanilla alternative to correctly buffer models that have - * geometry on multiple chunk layers and to provide the model with additional context. + * when necessary. Use this method instead of the vanilla alternative to provide the model with additional + * context. * *

This method allows buffering a block model with minimal transformations to the model geometry. Usually used by * entity renderers. @@ -154,9 +153,7 @@ static void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource * @param pose The pose. * @param bufferSource The buffer source. * @param model The model to render. - * @param red The red component of the tint color. - * @param green The green component of the tint color. - * @param blue The blue component of the tint color. + * @param tintColor The tint color. * @param light The minimum light value. * @param overlay The overlay value. * @param level The level in which to render the model. Can be empty (i.e. {@link EmptyBlockAndTintGetter}). @@ -164,11 +161,10 @@ static void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource * * @param state The block state. Should be {@code Blocks.AIR.getDefaultState()} if not applicable. * - * @see FabricOrderedSubmitNodeCollector#submitBlockModel(PoseStack, Function, BlockStateModel, float, float, float, int, int, int, BlockAndTintGetter, BlockPos, BlockState) + * @see FabricOrderedSubmitNodeCollector#submitBlockModel(PoseStack, Function, BlockStateModel, int, int, int, int, BlockAndTintGetter, BlockPos, BlockState) */ - static void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { + static void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, BlockStateModel model, int tintColor, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { Renderer.get().renderModel( - pose, bufferSource, null, model, red, green, - blue, light, overlay, level, pos, state); + pose, bufferSource, null, model, tintColor, light, overlay, level, pos, state); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricOrderedSubmitNodeCollector.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricOrderedSubmitNodeCollector.java index 5f344ef5a7..2481cbf577 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricOrderedSubmitNodeCollector.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/FabricOrderedSubmitNodeCollector.java @@ -36,6 +36,7 @@ import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadEmitter; +// TODO 26.1: update docs /** * Note: This interface is automatically implemented on {@link OrderedSubmitNodeCollector} via Mixin and interface injection. */ @@ -53,8 +54,8 @@ public interface FabricOrderedSubmitNodeCollector { * * @param poseStack The pose stack. * @param state The block state. - * @param light The minimum light value. - * @param overlay The overlay value. + * @param lightCoords The minimum light value. + * @param overlayCoords The overlay value. * @param outlineColor The outline color. * @param level The level in which to render the model. Can be empty (i.e. {@link EmptyBlockAndTintGetter}). * Must not be mutated after calling this method. @@ -63,13 +64,13 @@ public interface FabricOrderedSubmitNodeCollector { * * @see FabricBlockRenderDispatcher#renderSingleBlock(BlockState, PoseStack, MultiBufferSource, int, int, BlockAndTintGetter, BlockPos) */ - default void submitBlock(PoseStack poseStack, BlockState state, int light, int overlay, int outlineColor, BlockAndTintGetter level, BlockPos pos) { - ((OrderedSubmitNodeCollector) this).submitBlock(poseStack, state, light, overlay, outlineColor); + default void submitBlock(PoseStack poseStack, BlockState state, int lightCoords, int overlayCoords, int outlineColor, BlockAndTintGetter level, BlockPos pos) { + ((OrderedSubmitNodeCollector) this).submitBlock(poseStack, state, lightCoords, overlayCoords, outlineColor); } /** * Alternative for - * {@link OrderedSubmitNodeCollector#submitBlockModel(PoseStack, RenderType, BlockStateModel, float, float, float, int, int, int)} + * {@link OrderedSubmitNodeCollector#submitBlockModel(PoseStack, RenderType, BlockStateModel, int, int, int, int)} * that accepts a {@code Function} instead of a {@link RenderType}. Also accepts the * {@link BlockAndTintGetter}, {@link BlockPos}, and {@link BlockState} to pass to * {@link BlockStateModel#emitQuads(QuadEmitter, BlockAndTintGetter, BlockPos, BlockState, RandomSource, Predicate)} when @@ -83,11 +84,9 @@ default void submitBlock(PoseStack poseStack, BlockState state, int light, int o * @param renderTypeFunction The function to use to convert {@link ChunkSectionLayer}s to {@link RenderType}s. * Must not be mutated after calling this method. * @param model The model to render. - * @param r The red component of the tint color. - * @param g The green component of the tint color. - * @param b The blue component of the tint color. - * @param light The minimum light value. - * @param overlay The overlay value. + * @param tintColor The tint color. + * @param lightCoords The minimum light value. + * @param overlayCoords The overlay value. * @param outlineColor The outline color. * @param level The level in which to render the model. Can be empty (i.e. {@link EmptyBlockAndTintGetter}). * Must not be mutated after calling this method. @@ -95,9 +94,9 @@ default void submitBlock(PoseStack poseStack, BlockState state, int light, int o * Must not be mutated after calling this method. * @param state The block state. Should be {@code Blocks.AIR.getDefaultState()} if not applicable. * - * @see FabricModelBlockRenderer#renderModel(PoseStack.Pose, BlockMultiBufferSource, BlockStateModel, float, float, float, int, int, BlockAndTintGetter, BlockPos, BlockState) + * @see FabricModelBlockRenderer#renderModel(PoseStack.Pose, BlockMultiBufferSource, BlockStateModel, int, int, int, BlockAndTintGetter, BlockPos, BlockState) */ - default void submitBlockModel(PoseStack poseStack, Function renderTypeFunction, BlockStateModel model, float r, float g, float b, int light, int overlay, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { - ((OrderedSubmitNodeCollector) this).submitBlockModel(poseStack, renderTypeFunction.apply(ItemBlockRenderTypes.getChunkRenderType(state)), model, r, g, b, light, overlay, outlineColor); + default void submitBlockModel(PoseStack poseStack, Function renderTypeFunction, BlockStateModel model, int tintColor, int lightCoords, int overlayCoords, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { + ((OrderedSubmitNodeCollector) this).submitBlockModel(poseStack, ItemBlockRenderTypes.getBlockModelRenderType(model), model, tintColor, lightCoords, overlayCoords, outlineColor); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/ItemRenderTypeGetter.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/ItemRenderTypeGetter.java deleted file mode 100644 index f7ec1598a8..0000000000 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/render/ItemRenderTypeGetter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.api.client.renderer.v1.render; - -import org.jspecify.annotations.Nullable; - -import net.minecraft.client.renderer.chunk.ChunkSectionLayer; -import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.rendertype.RenderType; - -import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadAtlas; - -@FunctionalInterface -public interface ItemRenderTypeGetter { - /** - * Gets the {@link RenderType} for the given {@link QuadAtlas} and nullable {@link ChunkSectionLayer}. Quads with - * matching property values will be rendered using the returned render type. - * - *

A return value of {@code null} means that the current item layer's - * {@linkplain ItemStackRenderState.LayerRenderState#setRenderType(RenderType) default render type} will be used. - */ - @Nullable - RenderType renderType(QuadAtlas quadAtlas, @Nullable ChunkSectionLayer sectionLayer); -} diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricSpriteGetter.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricMaterialBaker.java similarity index 69% rename from fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricSpriteGetter.java rename to fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricMaterialBaker.java index 6ef67c5627..fe187bea97 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricSpriteGetter.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricMaterialBaker.java @@ -16,24 +16,24 @@ package net.fabricmc.fabric.api.client.renderer.v1.sprite; -import net.minecraft.client.resources.model.SpriteGetter; +import net.minecraft.client.resources.model.MaterialBaker; import net.minecraft.resources.Identifier; import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadAtlas; /** - * Note: This interface is automatically implemented on {@link SpriteGetter} via Mixin and interface injection. + * Note: This interface is automatically implemented on {@link MaterialBaker} via Mixin and interface injection. */ -public interface FabricSpriteGetter extends SpriteFinderGetter { +public interface FabricMaterialBaker extends SpriteFinderGetter { /** - * {@return the sprite finder for the given atlas texture ID} + * {@return the sprite finder for the given atlas ID} */ - default SpriteFinder spriteFinder(Identifier atlasTextureId) { + default SpriteFinder spriteFinder(Identifier atlasId) { throw new UnsupportedOperationException(); } @Override default SpriteFinder spriteFinder(QuadAtlas quadAtlas) { - return spriteFinder(quadAtlas.getTextureId()); + return spriteFinder(quadAtlas.getId()); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricTextureAtlas.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricTextureAtlas.java index f7065bd620..68371847d5 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricTextureAtlas.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricTextureAtlas.java @@ -31,7 +31,7 @@ public interface FabricTextureAtlas { * *

This method should not be used during a resource reload as this atlas will only be populated with new * sprites towards the end of the resource reload. In this case, use - * {@link FabricSpriteGetter#spriteFinder(Identifier)} or {@link FabricPreparations#spriteFinder()} + * {@link FabricMaterialBaker#spriteFinder(Identifier)} or {@link FabricPreparations#spriteFinder()} * instead. * * @return the sprite finder for this atlas diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/SpriteFinder.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/SpriteFinder.java index 4230228046..555bfdaf26 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/SpriteFinder.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/client/renderer/v1/sprite/SpriteFinder.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.ApiStatus; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.SpriteGetter; import net.minecraft.core.BlockPos; @@ -41,7 +42,7 @@ * finding the sprite for use in {@link QuadView#toBakedQuad(TextureAtlasSprite)}. * *

A sprite finder can be retrieved from various vanilla objects. Always use - * {@link FabricSpriteGetter#spriteFinder(Identifier)} or {@link FabricPreparations#spriteFinder()} + * {@link FabricMaterialBaker#spriteFinder(Identifier)} or {@link FabricPreparations#spriteFinder()} * whenever an applicable instance is available. For example, model baking is supplied with a * {@link SpriteGetter}, so it should be used to retrieve the sprite finder. In most other cases, it is * safe to use {@link FabricTextureAtlas#spriteFinder()}. @@ -63,7 +64,7 @@ public interface SpriteFinder { * Alternative to {@link #find(QuadView)} when vertex centroid is already * known or unsuitable. Expects normalized (0-1) coordinates on the atlas texture, * which should already be the case for u,v values in vanilla baked quads and in - * {@link QuadView} after calling {@link MutableQuadView#spriteBake(TextureAtlasSprite, int)}. + * {@link QuadView} after calling {@link MutableQuadView#materialBake(Material.Baked, int)}. * *

Coordinates must be in the sprite interior for reliable results. Generally will * be easier to use {@link #find(QuadView)} unless you know the vertex diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/BlockModelWrapperExtension.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/BlockModelWrapperExtension.java index 5a357cbecb..ce172c24a0 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/BlockModelWrapperExtension.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/BlockModelWrapperExtension.java @@ -16,10 +16,9 @@ package net.fabricmc.fabric.impl.client.renderer; -import net.minecraft.client.resources.model.SpriteGetter; - import net.fabricmc.fabric.api.client.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.client.renderer.v1.sprite.SpriteFinderGetter; public interface BlockModelWrapperExtension { - void fabric_setMesh(Mesh mesh, SpriteGetter spriteGetter); + void fabric_setMesh(Mesh mesh, SpriteFinderGetter spriteFinderGetter); } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/ExtendedBlockModelSubmit.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/ExtendedBlockModelSubmit.java index 919e00100e..97b4651ece 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/ExtendedBlockModelSubmit.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/client/renderer/ExtendedBlockModelSubmit.java @@ -27,5 +27,5 @@ import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; -public record ExtendedBlockModelSubmit(PoseStack.Pose pose, Function renderTypeFunction, BlockStateModel model, float r, float g, float b, int lightCoords, int overlayCoords, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { +public record ExtendedBlockModelSubmit(PoseStack.Pose pose, Function renderTypeFunction, BlockStateModel model, int tintColor, int lightCoords, int overlayCoords, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/MultiPartModelMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/MultiPartModelMixin.java index 02a2868a22..96c1a3ae4c 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/MultiPartModelMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/MultiPartModelMixin.java @@ -26,8 +26,8 @@ import org.spongepowered.asm.mixin.Shadow; import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.block.model.multipart.MultiPartModel; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; @@ -101,8 +101,8 @@ record Key(List subkeys) { } @Override - public TextureAtlasSprite particleIcon(BlockAndTintGetter level, BlockPos pos, BlockState state) { - return ((MultiPartModelSharedBakedStateAccessor) (Object) shared).getSelectors().getFirst().model().particleIcon( + public Material.Baked particleMaterial(BlockAndTintGetter level, BlockPos pos, BlockState state) { + return ((MultiPartModelSharedBakedStateAccessor) (Object) shared).getSelectors().getFirst().model().particleMaterial( level, pos, state); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/SimpleModelWrapperMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/SimpleModelWrapperMixin.java index 63729feec8..c2c01f777c 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/SimpleModelWrapperMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/SimpleModelWrapperMixin.java @@ -21,6 +21,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; import com.llamalad7.mixinextras.sugar.ref.LocalRef; import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Final; @@ -54,9 +55,9 @@ abstract class SimpleModelWrapperMixin implements BlockModelPart { private boolean useAmbientOcclusion; @Inject(method = "bake(Lnet/minecraft/client/resources/model/ModelBaker;Lnet/minecraft/resources/Identifier;Lnet/minecraft/client/resources/model/ModelState;)Lnet/minecraft/client/renderer/block/model/BlockModelPart;", at = @At(value = "INVOKE", target = "net/minecraft/client/resources/model/QuadCollection.getAll()Ljava/util/List;")) - private static void validateMeshAtlas(final ModelBaker modelBakery, final Identifier location, final ModelState state, CallbackInfoReturnable cir, @Local(name = "geometry") QuadCollection geometry, @Local(name = "forbiddenSprites") LocalRef> forbiddenSpritesRef) { - if (geometry instanceof MeshQuadCollection meshGeometry) { - meshGeometry.getMesh().forEach(quad -> { + private static void analyzeMesh(final ModelBaker modelBakery, final Identifier location, final ModelState state, CallbackInfoReturnable cir, @Local(name = "geometry") QuadCollection geometry, @Local(name = "hasTranslucency") LocalBooleanRef hasTranslucencyRef, @Local(name = "forbiddenSprites") LocalRef> forbiddenSpritesRef) { + if (geometry instanceof MeshQuadCollection meshQuadCollection) { + meshQuadCollection.getMesh().forEach(quad -> { if (quad.atlas() != QuadAtlas.BLOCK) { Multimap forbiddenSprites = forbiddenSpritesRef.get(); @@ -65,9 +66,11 @@ private static void validateMeshAtlas(final ModelBaker modelBakery, final Identi forbiddenSpritesRef.set(forbiddenSprites); } - TextureAtlasSprite sprite = modelBakery.sprites().spriteFinder(quad.atlas()).find(quad); + TextureAtlasSprite sprite = modelBakery.materials().spriteFinder(quad.atlas()).find(quad); forbiddenSprites.put(sprite.atlasLocation(), sprite.contents().name()); } + + hasTranslucencyRef.set(hasTranslucencyRef.get() | quad.chunkLayer().translucent()); }); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/WeightedVariantsMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/WeightedVariantsMixin.java index 670fc05136..df4a0e3c96 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/WeightedVariantsMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/model/WeightedVariantsMixin.java @@ -24,7 +24,7 @@ import org.spongepowered.asm.mixin.Shadow; 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.WeightedVariants; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -55,8 +55,8 @@ public Object createGeometryKey(BlockAndTintGetter level, BlockPos pos, BlockSta } @Override - public TextureAtlasSprite particleIcon(BlockAndTintGetter level, BlockPos pos, BlockState state) { - return list.unwrap().getFirst().value().particleIcon( + public Material.Baked particleMaterial(BlockAndTintGetter level, BlockPos pos, BlockState state) { + return list.unwrap().getFirst().value().particleMaterial( level, pos, state); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/BlockMarkerMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/BlockMarkerMixin.java index 219cfc0f52..c3569cd43a 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/BlockMarkerMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/BlockMarkerMixin.java @@ -23,14 +23,14 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.BlockMarker; import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; @Mixin(BlockMarker.class) abstract class BlockMarkerMixin { - @Redirect(method = "(Lnet/minecraft/client/multiplayer/ClientLevel;DDDLnet/minecraft/world/level/block/state/BlockState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getParticleIcon(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;")) - private static TextureAtlasSprite getParticleIconProxy(BlockModelShaper models, BlockState state, ClientLevel level, double x, double y, double z, BlockState state1) { - return models.getParticleIcon(state, level, BlockPos.containing(x, y, z)); + @Redirect(method = "(Lnet/minecraft/client/multiplayer/ClientLevel;DDDLnet/minecraft/world/level/block/state/BlockState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getParticleMaterial(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/Material$Baked;")) + private static Material.Baked getParticleMaterialProxy(BlockModelShaper models, BlockState state, ClientLevel level, double x, double y, double z, BlockState state1) { + return models.getParticleMaterial(state, level, BlockPos.containing(x, y, z)); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/ScreenEffectRendererMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/ScreenEffectRendererMixin.java index 52e343b79c..d4ac6171ed 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/ScreenEffectRendererMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/ScreenEffectRendererMixin.java @@ -27,7 +27,7 @@ import net.minecraft.client.renderer.ScreenEffectRenderer; import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.state.BlockState; @@ -38,15 +38,15 @@ abstract class ScreenEffectRendererMixin { @Nullable private static BlockPos pos; - @Redirect(method = "renderScreenEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getParticleIcon(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;")) - private static TextureAtlasSprite getParticleIconProxy(BlockModelShaper models, BlockState state, @Local(name = "player") Player player) { + @Redirect(method = "renderScreenEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getParticleMaterial(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/Material$Baked;")) + private static Material.Baked getParticleMaterialProxy(BlockModelShaper models, BlockState state, @Local(name = "player") Player player) { if (pos != null) { - TextureAtlasSprite sprite = models.getParticleIcon(state, player.level(), pos); + Material.Baked material = models.getParticleMaterial(state, player.level(), pos); pos = null; - return sprite; + return material; } - return models.getParticleIcon(state); + return models.getParticleMaterial(state); } @Inject(method = "getViewBlockingState", at = @At("RETURN")) diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/TerrainParticleMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/TerrainParticleMixin.java index b12225e2c8..589d55b9b4 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/TerrainParticleMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/particle/TerrainParticleMixin.java @@ -23,14 +23,14 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.TerrainParticle; import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; @Mixin(TerrainParticle.class) abstract class TerrainParticleMixin { - @Redirect(method = "(Lnet/minecraft/client/multiplayer/ClientLevel;DDDDDDLnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getParticleIcon(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;")) - private static TextureAtlasSprite getParticleIconProxy(BlockModelShaper models, BlockState state, ClientLevel level, double x, double y, double z, double velocityX, double velocityY, double velocityZ, BlockState state1, BlockPos blockPos) { - return models.getParticleIcon(state, level, blockPos); + @Redirect(method = "(Lnet/minecraft/client/multiplayer/ClientLevel;DDDDDDLnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getParticleMaterial(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/Material$Baked;")) + private static Material.Baked getParticleIconProxy(BlockModelShaper models, BlockState state, ClientLevel level, double x, double y, double z, double velocityX, double velocityY, double velocityZ, BlockState state1, BlockPos blockPos) { + return models.getParticleMaterial(state, level, blockPos); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/BlockFeatureRendererMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/BlockFeatureRendererMixin.java index e3dc8db7aa..c1902cc415 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/BlockFeatureRendererMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/BlockFeatureRendererMixin.java @@ -19,13 +19,11 @@ import java.util.function.Predicate; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.OutlineBufferSource; @@ -39,6 +37,7 @@ import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.BlockPos; import net.minecraft.world.level.EmptyBlockAndTintGetter; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.fabricmc.fabric.api.client.renderer.v1.render.BlockMultiBufferSource; @@ -109,25 +108,40 @@ private void renderBlockSubmits(final SubmitNodeCollection nodeCollection, final } } - // Support ExtendedBlockModelSubmit. - @Inject(method = "renderBlockModelSubmits", at = @At("RETURN")) - private void onReturnRenderBlockModelSubmits(SubmitNodeCollection nodeCollection, MultiBufferSource.BufferSource bufferSource, OutlineBufferSource outlineBufferSource, boolean translucent, CallbackInfo ci) { + // Support FRAPI models in BlockModelSubmit and support ExtendedBlockModelSubmit. + @Overwrite + private void renderBlockModelSubmits(final SubmitNodeCollection nodeCollection, final MultiBufferSource.BufferSource bufferSource, final OutlineBufferSource outlineBufferSource, final boolean translucent) { + for (SubmitNodeStorage.BlockModelSubmit submit : nodeCollection.getBlockModelSubmits()) { + if (submit.renderType().hasBlending() == translucent) { + VertexConsumer buffer = bufferSource.getBuffer(submit.renderType()); + FabricModelBlockRenderer.renderModel( + submit.pose(), _ -> buffer, submit.model(), submit.tintColor(), submit.lightCoords(), submit.overlayCoords(), EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, + Blocks.AIR.defaultBlockState()); + + if (submit.outlineColor() != 0) { + outlineBufferSource.setColor(submit.outlineColor()); + VertexConsumer outlineBuffer = outlineBufferSource.getBuffer(submit.renderType()); + FabricModelBlockRenderer.renderModel( + submit.pose(), _ -> outlineBuffer, submit.model(), submit.tintColor(), submit.lightCoords(), submit.overlayCoords(), EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, + Blocks.AIR.defaultBlockState()); + } + } + } + DelegatingBlockMultiBufferSourceImpl blockMultiBufferSource = new DelegatingBlockMultiBufferSourceImpl(translucent); for (ExtendedBlockModelSubmit submit : ((SubmitNodeCollectionExtension) nodeCollection).fabric_getExtendedBlockModelSubmits()) { blockMultiBufferSource.renderTypeFunction = submit.renderTypeFunction(); blockMultiBufferSource.multiBufferSource = bufferSource; FabricModelBlockRenderer.renderModel( - submit.pose(), blockMultiBufferSource, blockMultiBufferSource, submit.model(), submit.r(), submit.g(), - submit.b(), submit.lightCoords(), submit.overlayCoords(), submit.level(), submit.pos(), + submit.pose(), blockMultiBufferSource, blockMultiBufferSource, submit.model(), submit.tintColor(), submit.lightCoords(), submit.overlayCoords(), submit.level(), submit.pos(), submit.state()); if (submit.outlineColor() != 0) { outlineBufferSource.setColor(submit.outlineColor()); blockMultiBufferSource.multiBufferSource = outlineBufferSource; FabricModelBlockRenderer.renderModel( - submit.pose(), blockMultiBufferSource, blockMultiBufferSource, submit.model(), submit.r(), submit.g(), - submit.b(), submit.lightCoords(), submit.overlayCoords(), submit.level(), submit.pos(), + submit.pose(), blockMultiBufferSource, blockMultiBufferSource, submit.model(), submit.tintColor(), submit.lightCoords(), submit.overlayCoords(), submit.level(), submit.pos(), submit.state()); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/ItemFrameRendererMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/ItemFrameRendererMixin.java index fa4fe2609d..63cf9ebb34 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/ItemFrameRendererMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/ItemFrameRendererMixin.java @@ -33,10 +33,10 @@ @Mixin(ItemFrameRenderer.class) abstract class ItemFrameRendererMixin { // Provide the BlockState as context. - @Redirect(method = "submit(Lnet/minecraft/client/renderer/entity/state/ItemFrameRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitBlockModel(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/block/model/BlockStateModel;FFFIII)V")) - private void renderProxy(SubmitNodeCollector submitNodeCollector, PoseStack poseStack, RenderType renderType, BlockStateModel model, float r, float g, float b, int light, int overlay, int outlineColor, @Local(name = "fakeBlockState") BlockState fakeBlockState) { + @Redirect(method = "submit(Lnet/minecraft/client/renderer/entity/state/ItemFrameRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitBlockModel(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/block/model/BlockStateModel;IIII)V")) + private void renderProxy(SubmitNodeCollector submitNodeCollector, PoseStack poseStack, RenderType renderType, BlockStateModel model, int tint, int light, int overlay, int outlineColor, @Local(name = "fakeBlockState") BlockState fakeBlockState) { // The vertex consumer is for a special layer that renders solid, but vanilla has no equivalent // cutout/translucent layers that we can use here without risking compatibility. - submitNodeCollector.submitBlockModel(poseStack, blockLayer -> renderType, model, r, g, b, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, fakeBlockState); + submitNodeCollector.submitBlockModel(poseStack, _ -> renderType, model, tint, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, fakeBlockState); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/MushroomCowMushroomLayerMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/MushroomCowMushroomLayerMixin.java index 6e410d6b2f..31498ea0cc 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/MushroomCowMushroomLayerMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/MushroomCowMushroomLayerMixin.java @@ -33,8 +33,8 @@ @Mixin(MushroomCowMushroomLayer.class) abstract class MushroomCowMushroomLayerMixin { // Fix tinted quads being rendered completely black and provide the BlockState as context. - @Redirect(method = "submitMushroomBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitBlockModel(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/block/model/BlockStateModel;FFFIII)V")) - private void renderProxy(SubmitNodeCollector submitNodeCollector, PoseStack poseStack, RenderType renderType, BlockStateModel model, float r, float g, float b, int light, int overlay, int outlineColor, @Local(argsOnly = true) BlockState blockState) { - submitNodeCollector.submitBlockModel(poseStack, _ -> renderType, model, 1, 1, 1, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, blockState); + @Redirect(method = "submitMushroomBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitBlockModel(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/block/model/BlockStateModel;IIII)V")) + private void renderProxy(SubmitNodeCollector submitNodeCollector, PoseStack poseStack, RenderType renderType, BlockStateModel model, int tint, int light, int overlay, int outlineColor, @Local(argsOnly = true) BlockState blockState) { + submitNodeCollector.submitBlockModel(poseStack, _ -> renderType, model, -1, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, blockState); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SnowGolemHeadLayerMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SnowGolemHeadLayerMixin.java index 9a49f6d70d..941a81f10a 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SnowGolemHeadLayerMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SnowGolemHeadLayerMixin.java @@ -22,6 +22,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.client.renderer.entity.layers.SnowGolemHeadLayer; @@ -31,19 +32,17 @@ import net.minecraft.world.level.EmptyBlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; -import net.fabricmc.fabric.api.client.renderer.v1.render.ChunkSectionLayerHelper; - @Mixin(SnowGolemHeadLayer.class) abstract class SnowGolemHeadLayerMixin { - @Redirect(method = "submit(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/renderer/entity/state/SnowGolemRenderState;FF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitBlockModel(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/block/model/BlockStateModel;FFFIII)V")) - private void renderProxy(SubmitNodeCollector submitNodeCollector, PoseStack poseStack, RenderType renderType, BlockStateModel model, float r, float g, float b, int light, int overlay, int outlineColor, @Local(argsOnly = true) SnowGolemRenderState renderState, @Local(name = "pumpkinBlockState") BlockState pumpkinBlockState) { + @Redirect(method = "submit(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/renderer/entity/state/SnowGolemRenderState;FF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitBlockModel(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/block/model/BlockStateModel;IIII)V")) + private void renderProxy(SubmitNodeCollector submitNodeCollector, PoseStack poseStack, RenderType renderType, BlockStateModel model, int tint, int light, int overlay, int outlineColor, @Local(argsOnly = true) SnowGolemRenderState renderState, @Local(name = "pumpkinBlockState") BlockState pumpkinBlockState) { // If true, the chunk layer is an outline chunk layer, and we want all geometry to use this chunk layer. if (renderState.appearsGlowing() && renderState.isInvisible) { // Fix tinted quads being rendered completely black and provide the BlockState as context. - submitNodeCollector.submitBlockModel(poseStack, _ -> renderType, model, 1, 1, 1, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, pumpkinBlockState); + submitNodeCollector.submitBlockModel(poseStack, _ -> renderType, model, -1, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, pumpkinBlockState); } else { // Support multi-chunk layer models, fix tinted quads being rendered completely black, and provide the BlockState as context. - submitNodeCollector.submitBlockModel(poseStack, ChunkSectionLayerHelper::getEntityBlockLayer, model, 1, 1, 1, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, pumpkinBlockState); + submitNodeCollector.submitBlockModel(poseStack, ItemBlockRenderTypes::getRenderType, model, -1, light, overlay, outlineColor, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, pumpkinBlockState); } } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeCollectionMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeCollectionMixin.java index fdfe0e55a1..d34d176e15 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeCollectionMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeCollectionMixin.java @@ -68,12 +68,12 @@ public void submitBlock(PoseStack poseStack, BlockState state, int light, int ov } @Override - public void submitBlockModel(PoseStack poseStack, Function renderTypeFunction, BlockStateModel model, float r, float g, float b, int light, int overlay, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { + public void submitBlockModel(PoseStack poseStack, Function renderTypeFunction, BlockStateModel model, int tint, int light, int overlay, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { wasUsed = true; extendedBlockModelSubmits.add(new ExtendedBlockModelSubmit( poseStack.last().copy(), - renderTypeFunction, model, r, g, b, light, overlay, outlineColor, - level, pos, state)); + renderTypeFunction, model, tint, + light, overlay, outlineColor, level, pos, state)); } @Override diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeStorageMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeStorageMixin.java index 2adc78c7d1..ae08159100 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeStorageMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/block/render/SubmitNodeStorageMixin.java @@ -39,10 +39,10 @@ public void submitBlock(PoseStack poseStack, BlockState state, int light, int ov } @Override - public void submitBlockModel(PoseStack poseStack, Function renderTypeFunction, BlockStateModel model, float r, float g, float b, int light, int overlay, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { + public void submitBlockModel(PoseStack poseStack, Function renderTypeFunction, BlockStateModel model, int tint, int light, int overlay, int outlineColor, BlockAndTintGetter level, BlockPos pos, BlockState state) { order(0).submitBlockModel( poseStack, - renderTypeFunction, model, r, g, b, light, overlay, outlineColor, + renderTypeFunction, model, tint, light, overlay, outlineColor, level, pos, state); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperMixin.java index 1197fe1469..604c23f879 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperMixin.java @@ -28,20 +28,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.ItemBlockRenderTypes; -import net.minecraft.client.renderer.Sheets; -import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.item.BlockModelWrapper; import net.minecraft.client.renderer.item.ItemModel; import net.minecraft.client.renderer.item.ItemModelResolver; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.resources.model.SpriteGetter; import net.minecraft.world.entity.ItemOwner; -import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.fabricmc.fabric.api.client.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.client.renderer.v1.sprite.SpriteFinderGetter; import net.fabricmc.fabric.impl.client.renderer.BlockModelWrapperExtension; @Mixin(BlockModelWrapper.class) @@ -58,38 +54,12 @@ abstract class BlockModelWrapperMixin implements ItemModel, BlockModelWrapperExt @Inject(method = "update", at = @At("RETURN")) private void onReturnUpdate(final ItemStackRenderState output, final ItemStack item, final ItemModelResolver resolver, final ItemDisplayContext displayContext, final @Nullable ClientLevel level, final @Nullable ItemOwner owner, final int seed, CallbackInfo ci, @Local(name = "layer") ItemStackRenderState.LayerRenderState layer) { if (mesh != null) { - // This logic matches that of ITEM_RENDER_TYPE_GETTER and BLOCK_RENDER_TYPE_GETTER - ChunkSectionLayer defaultSectionLayer; - - if (item.getItem() instanceof BlockItem blockItem) { - defaultSectionLayer = ItemBlockRenderTypes.getChunkRenderType(blockItem.getBlock().defaultBlockState()); - } else { - defaultSectionLayer = ChunkSectionLayer.TRANSLUCENT; - } - - layer.setRenderTypeGetter((quadAtlas, sectionLayer) -> { - return switch (quadAtlas) { - case BLOCK -> { - if (sectionLayer == null) { - sectionLayer = defaultSectionLayer; - } - - if (sectionLayer != ChunkSectionLayer.TRANSLUCENT) { - yield Sheets.cutoutBlockSheet(); - } - - yield Sheets.translucentBlockItemSheet(); - } - case ITEM -> Sheets.translucentItemSheet(); - }; - }); - mesh.outputTo(layer.emitter()); } } @Override - public void fabric_setMesh(Mesh mesh, SpriteGetter spriteGetter) { + public void fabric_setMesh(Mesh mesh, SpriteFinderGetter spriteFinderGetter) { this.mesh = mesh; if (!animated) { @@ -101,7 +71,7 @@ public void fabric_setMesh(Mesh mesh, SpriteGetter spriteGetter) { ItemStackRenderState.FoilType glint = quad.foilType(); if ((glint != null && glint != ItemStackRenderState.FoilType.NONE) - || spriteGetter.spriteFinder(quad.atlas().getTextureId()).find(quad).contents().isAnimated()) { + || spriteFinderGetter.spriteFinder(quad.atlas()).find(quad).contents().isAnimated()) { animated = true; } }); diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperUnbakedMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperUnbakedMixin.java index 357a11f728..ff3ed305e6 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperUnbakedMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/item/BlockModelWrapperUnbakedMixin.java @@ -46,7 +46,7 @@ private BlockModelWrapper injectMesh(BlockModelWrapper model, ItemModel.BakingCo Mesh mesh = meshRef.get(); if (mesh != null) { - ((BlockModelWrapperExtension) model).fabric_setMesh(mesh, context.blockModelBaker().sprites()); + ((BlockModelWrapperExtension) model).fabric_setMesh(mesh, context.blockModelBaker().materials()); } return model; diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/SpriteGetterMixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/MaterialBakerMixin.java similarity index 76% rename from fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/SpriteGetterMixin.java rename to fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/MaterialBakerMixin.java index 7e08767250..b0b9b09c68 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/SpriteGetterMixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/MaterialBakerMixin.java @@ -18,10 +18,10 @@ import org.spongepowered.asm.mixin.Mixin; -import net.minecraft.client.resources.model.SpriteGetter; +import net.minecraft.client.resources.model.MaterialBaker; -import net.fabricmc.fabric.api.client.renderer.v1.sprite.FabricSpriteGetter; +import net.fabricmc.fabric.api.client.renderer.v1.sprite.FabricMaterialBaker; -@Mixin(SpriteGetter.class) -interface SpriteGetterMixin extends FabricSpriteGetter { +@Mixin(MaterialBaker.class) +interface MaterialBakerMixin extends FabricMaterialBaker { } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/ModelManager1Mixin.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/ModelManager1Mixin.java index c5af9a1d2d..342b2a2821 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/ModelManager1Mixin.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/renderer/sprite/ModelManager1Mixin.java @@ -22,20 +22,20 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.texture.SpriteLoader; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.SpriteGetter; +import net.minecraft.data.AtlasIds; import net.minecraft.resources.Identifier; +import net.fabricmc.fabric.api.client.renderer.v1.sprite.FabricMaterialBaker; import net.fabricmc.fabric.api.client.renderer.v1.sprite.SpriteFinder; import net.fabricmc.fabric.impl.client.renderer.MissingSpriteFinderImpl; @Mixin(targets = "net.minecraft.client.resources.model.ModelManager$1") -abstract class ModelManager1Mixin implements SpriteGetter { +abstract class ModelManager1Mixin implements FabricMaterialBaker { @Shadow @Final - private TextureAtlasSprite blockMissing; + private Material.Baked blockMissing; @Shadow @Final SpriteLoader.Preparations val$blockAtlas; @@ -48,10 +48,10 @@ abstract class ModelManager1Mixin implements SpriteGetter { private volatile MissingSpriteFinderImpl missingSpriteFinder; @Override - public SpriteFinder spriteFinder(Identifier atlasTextureId) { - if (atlasTextureId.equals(TextureAtlas.LOCATION_BLOCKS)) { + public SpriteFinder spriteFinder(Identifier atlasId) { + if (atlasId.equals(AtlasIds.BLOCKS)) { return val$blockAtlas.spriteFinder(); - } else if (atlasTextureId.equals(TextureAtlas.LOCATION_ITEMS)) { + } else if (atlasId.equals(AtlasIds.ITEMS)) { return val$itemAtlas.spriteFinder(); } @@ -62,7 +62,7 @@ public SpriteFinder spriteFinder(Identifier atlasTextureId) { result = missingSpriteFinder; if (result == null) { - missingSpriteFinder = result = new MissingSpriteFinderImpl(blockMissing); + missingSpriteFinder = result = new MissingSpriteFinderImpl(blockMissing.sprite()); } } } diff --git a/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.classtweaker b/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.classtweaker index a7c8d9e8d4..3a3dbb5521 100644 --- a/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.classtweaker +++ b/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.classtweaker @@ -8,6 +8,6 @@ transitive-inject-interface net/minecraft/client/renderer/block/ModelBlockRender transitive-inject-interface net/minecraft/client/renderer/block/BlockRenderDispatcher net/fabricmc/fabric/api/client/renderer/v1/render/FabricBlockRenderDispatcher transitive-inject-interface net/minecraft/client/renderer/item/ItemStackRenderState$LayerRenderState net/fabricmc/fabric/api/client/renderer/v1/render/FabricLayerRenderState transitive-inject-interface net/minecraft/client/renderer/OrderedSubmitNodeCollector net/fabricmc/fabric/api/client/renderer/v1/render/FabricOrderedSubmitNodeCollector -transitive-inject-interface net/minecraft/client/resources/model/SpriteGetter net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricSpriteGetter transitive-inject-interface net/minecraft/client/renderer/texture/TextureAtlas net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricTextureAtlas transitive-inject-interface net/minecraft/client/renderer/texture/SpriteLoader$Preparations net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricPreparations +transitive-inject-interface net/minecraft/client/resources/model/MaterialBaker net/fabricmc/fabric/api/client/renderer/v1/sprite/FabricMaterialBaker diff --git a/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json b/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json index 58c1865f8e..3ddeaae2b7 100644 --- a/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json +++ b/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json @@ -5,31 +5,31 @@ "client": [ "block.model.BlockModelPartMixin", "block.model.BlockStateModelMixin", - "block.model.SimpleModelWrapperMixin", - "block.model.MultiPartModelSharedBakedStateAccessor", "block.model.MultiPartModelMixin", + "block.model.MultiPartModelSharedBakedStateAccessor", + "block.model.SimpleModelWrapperMixin", "block.model.SingleVariantMixin", "block.model.WeightedVariantsMixin", - "block.particle.TerrainParticleMixin", "block.particle.BlockMarkerMixin", "block.particle.BlockModelShaperMixin", "block.particle.ScreenEffectRendererMixin", - "block.render.SubmitNodeCollectionMixin", - "block.render.ModelBlockRendererMixin", - "block.render.BlockRenderDispatcherMixin", + "block.particle.TerrainParticleMixin", "block.render.BlockFeatureRendererMixin", + "block.render.BlockRenderDispatcherMixin", "block.render.ItemFrameRendererMixin", + "block.render.ModelBlockRendererMixin", "block.render.MushroomCowMushroomLayerMixin", - "block.render.SubmitNodeStorageMixin", "block.render.OrderedSubmitNodeCollectorMixin", "block.render.SnowGolemHeadLayerMixin", + "block.render.SubmitNodeCollectionMixin", + "block.render.SubmitNodeStorageMixin", "item.BlockModelWrapperMixin", "item.BlockModelWrapperUnbakedMixin", "item.ItemStackRenderStateLayerRenderStateMixin", "sprite.ModelManager1Mixin", - "sprite.SpriteGetterMixin", + "sprite.SpriteLoaderPreparationsMixin", "sprite.TextureAtlasMixin", - "sprite.SpriteLoaderPreparationsMixin" + "sprite.MaterialBakerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/BiomeDependentBlockStateModel.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/BiomeDependentBlockStateModel.java index 56e49de746..41bfc8ed20 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/BiomeDependentBlockStateModel.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/BiomeDependentBlockStateModel.java @@ -25,7 +25,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; @@ -77,16 +77,21 @@ public void collectParts(RandomSource random, List parts) { } @Override - public TextureAtlasSprite particleIcon() { - return regularModel.particleIcon(); + public Material.Baked particleMaterial() { + return regularModel.particleMaterial(); } @Override - public TextureAtlasSprite particleIcon(BlockAndTintGetter level, BlockPos pos, BlockState state) { + public boolean hasTranslucency() { + return this.regularModel.hasTranslucency() || this.biomeModel.hasTranslucency(); + } + + @Override + public Material.Baked particleMaterial(BlockAndTintGetter level, BlockPos pos, BlockState state) { if (((FabricBlockGetter) level).hasBiomes() && ((FabricBlockGetter) level).getBiomeFabric(pos).is(biomeTag)) { - return biomeModel.particleIcon(level, pos, state); + return biomeModel.particleMaterial(level, pos, state); } else { - return regularModel.particleIcon(level, pos, state); + return regularModel.particleMaterial(level, pos, state); } } diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameBlockStateModel.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameBlockStateModel.java index dfb0514b64..d7efa74eea 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameBlockStateModel.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameBlockStateModel.java @@ -26,8 +26,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BlockModelPart; import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -129,20 +129,25 @@ public void collectParts(RandomSource random, List parts) { } @Override - public TextureAtlasSprite particleIcon() { - return frameModel.particleIcon(); + public Material.Baked particleMaterial() { + return frameModel.particleMaterial(); } @Override - public TextureAtlasSprite particleIcon(BlockAndTintGetter level, BlockPos pos, BlockState state) { + public boolean hasTranslucency() { + return true; + } + + @Override + public Material.Baked particleMaterial(BlockAndTintGetter level, BlockPos pos, BlockState state) { // We should not access the block entity from here. We should instead use the immutable render data provided by the block entity. if (!(((FabricBlockGetter) level).getBlockEntityRenderData(pos) instanceof Block mimickedBlock)) { - return frameModel.particleIcon(level, pos, state); // No inner block to render, or data of wrong type + return frameModel.particleMaterial(level, pos, state); // No inner block to render, or data of wrong type } BlockState innerState = mimickedBlock.defaultBlockState(); BlockStateModel innerModel = Minecraft.getInstance().getBlockRenderer().getBlockModel(innerState); - return innerModel.particleIcon(level, pos, state); + return innerModel.particleMaterial(level, pos, state); } public record Unbaked(BlockStateModel.Unbaked frameModel) implements CustomUnbakedBlockStateModel { diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameGeometry.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameGeometry.java index 372d71c537..c5f04b2726 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameGeometry.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/FrameGeometry.java @@ -16,8 +16,10 @@ package net.fabricmc.fabric.test.renderer.client; +import java.util.Objects; + +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.block.model.TextureSlots; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.client.resources.model.ModelDebugName; import net.minecraft.client.resources.model.ModelState; @@ -37,50 +39,51 @@ public record FrameGeometry(boolean emissive) implements UnbakedGeometry { public QuadCollection bake(TextureSlots textures, ModelBaker baker, ModelState settings, ModelDebugName model) { MutableMesh builder = Renderer.get().mutableMesh(); QuadEmitter emitter = builder.emitter(); - emitter.pushTransform(ModelStateHelper.asQuadTransform(settings, baker.sprites())); + emitter.pushTransform(ModelStateHelper.asQuadTransform(settings, baker.materials())); - TextureAtlasSprite sprite = baker.sprites().get(textures.getMaterial("frame"), model); + Material.Baked material = baker.materials() + .get(Objects.requireNonNull(textures.getMaterial("frame")), model); for (Direction direction : Direction.values()) { // Draw outer frame emitter.square(direction, 0.0F, 0.9F, 0.9F, 1.0F, 0.0F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); emitter.square(direction, 0.0F, 0.0F, 0.1F, 0.9F, 0.0F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); emitter.square(direction, 0.9F, 0.1F, 1.0F, 1.0F, 0.0F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); emitter.square(direction, 0.1F, 0.0F, 1.0F, 0.1F, 0.0F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); // Draw inner frame - inset by 0.9 so the frame looks like an actual mesh emitter.square(direction, 0.0F, 0.9F, 0.9F, 1.0F, 0.9F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); emitter.square(direction, 0.0F, 0.0F, 0.1F, 0.9F, 0.9F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); emitter.square(direction, 0.9F, 0.1F, 1.0F, 1.0F, 0.9F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); emitter.square(direction, 0.1F, 0.0F, 1.0F, 0.1F, 0.9F) - .spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) .emissive(emissive) .emit(); } diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnGeometry.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnGeometry.java index 5af456720d..aaa163f272 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnGeometry.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnGeometry.java @@ -16,9 +16,11 @@ package net.fabricmc.fabric.test.renderer.client; +import java.util.Objects; + +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.block.model.TextureSlots; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.client.resources.model.ModelDebugName; import net.minecraft.client.resources.model.ModelState; @@ -44,180 +46,181 @@ public record OctagonalColumnGeometry(ShadeMode shadeMode) implements UnbakedGeo public QuadCollection bake(TextureSlots textures, ModelBaker baker, ModelState settings, ModelDebugName model) { MutableMesh builder = Renderer.get().mutableMesh(); QuadEmitter emitter = builder.emitter(); - emitter.pushTransform(ModelStateHelper.asQuadTransform(settings, baker.sprites())); + emitter.pushTransform(ModelStateHelper.asQuadTransform(settings, baker.materials())); - TextureAtlasSprite sprite = baker.sprites().get(textures.getMaterial("column"), model); + Material.Baked material = baker.materials() + .get(Objects.requireNonNull(textures.getMaterial("column")), model); // up - emitter.pos(0, A, 1, 0); - emitter.pos(1, 0.5f, 1, 0.5f); - emitter.pos(2, 1, 1, A); - emitter.pos(3, B, 1, 0); - emitter.cullFace(Direction.UP); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); - - emitter.pos(0, 0, 1, A); - emitter.pos(1, 0, 1, B); - emitter.pos(2, 0.5f, 1, 0.5f); - emitter.pos(3, A, 1, 0); - emitter.cullFace(Direction.UP); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); - - emitter.pos(0, 0, 1, B); - emitter.pos(1, A, 1, 1); - emitter.pos(2, B, 1, 1); - emitter.pos(3, 0.5f, 1, 0.5f); - emitter.cullFace(Direction.UP); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); - - emitter.pos(0, 0.5f, 1, 0.5f); - emitter.pos(1, B, 1, 1); - emitter.pos(2, 1, 1, B); - emitter.pos(3, 1, 1, A); - emitter.cullFace(Direction.UP); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); + emitter.pos(0, A, 1, 0) + .pos(1, 0.5f, 1, 0.5f) + .pos(2, 1, 1, A) + .pos(3, B, 1, 0) + .cullFace(Direction.UP) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); + + emitter.pos(0, 0, 1, A) + .pos(1, 0, 1, B) + .pos(2, 0.5f, 1, 0.5f) + .pos(3, A, 1, 0) + .cullFace(Direction.UP) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); + + emitter.pos(0, 0, 1, B) + .pos(1, A, 1, 1) + .pos(2, B, 1, 1) + .pos(3, 0.5f, 1, 0.5f) + .cullFace(Direction.UP) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); + + emitter.pos(0, 0.5f, 1, 0.5f) + .pos(1, B, 1, 1) + .pos(2, 1, 1, B) + .pos(3, 1, 1, A) + .cullFace(Direction.UP) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); // down - emitter.pos(0, A, 0, 1); - emitter.pos(1, 0.5f, 0, 0.5f); - emitter.pos(2, 1, 0, B); - emitter.pos(3, B, 0, 1); - emitter.cullFace(Direction.DOWN); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); - - emitter.pos(0, 0, 0, B); - emitter.pos(1, 0, 0, A); - emitter.pos(2, 0.5f, 0, 0.5f); - emitter.pos(3, A, 0, 1); - emitter.cullFace(Direction.DOWN); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); - - emitter.pos(0, 0, 0, A); - emitter.pos(1, A, 0, 0); - emitter.pos(2, B, 0, 0); - emitter.pos(3, 0.5f, 0, 0.5f); - emitter.cullFace(Direction.DOWN); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); - - emitter.pos(0, 0.5f, 0, 0.5f); - emitter.pos(1, B, 0, 0); - emitter.pos(2, 1, 0, A); - emitter.pos(3, 1, 0, B); - emitter.cullFace(Direction.DOWN); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.emit(); + emitter.pos(0, A, 0, 1) + .pos(1, 0.5f, 0, 0.5f) + .pos(2, 1, 0, B) + .pos(3, B, 0, 1) + .cullFace(Direction.DOWN) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); + + emitter.pos(0, 0, 0, B) + .pos(1, 0, 0, A) + .pos(2, 0.5f, 0, 0.5f) + .pos(3, A, 0, 1) + .cullFace(Direction.DOWN) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); + + emitter.pos(0, 0, 0, A) + .pos(1, A, 0, 0) + .pos(2, B, 0, 0) + .pos(3, 0.5f, 0, 0.5f) + .cullFace(Direction.DOWN) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); + + emitter.pos(0, 0.5f, 0, 0.5f) + .pos(1, B, 0, 0) + .pos(2, 1, 0, A) + .pos(3, 1, 0, B) + .cullFace(Direction.DOWN) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .emit(); // north - emitter.pos(0, B, 1, 0); - emitter.pos(1, B, 0, 0); - emitter.pos(2, A, 0, 0); - emitter.pos(3, A, 1, 0); - emitter.cullFace(Direction.NORTH); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, B, 1, 0) + .pos(1, B, 0, 0) + .pos(2, A, 0, 0) + .pos(3, A, 1, 0) + .cullFace(Direction.NORTH) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); // northwest - emitter.pos(0, A, 1, 0); - emitter.pos(1, A, 0, 0); - emitter.pos(2, 0, 0, A); - emitter.pos(3, 0, 1, A); - cornerSprite(emitter, sprite); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, A, 1, 0) + .pos(1, A, 0, 0) + .pos(2, 0, 0, A) + .pos(3, 0, 1, A); + cornerSprite(emitter, material); + emitter.shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); // west - emitter.pos(0, 0, 1, A); - emitter.pos(1, 0, 0, A); - emitter.pos(2, 0, 0, B); - emitter.pos(3, 0, 1, B); - emitter.cullFace(Direction.WEST); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, 0, 1, A) + .pos(1, 0, 0, A) + .pos(2, 0, 0, B) + .pos(3, 0, 1, B) + .cullFace(Direction.WEST) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); // southwest - emitter.pos(0, 0, 1, B); - emitter.pos(1, 0, 0, B); - emitter.pos(2, A, 0, 1); - emitter.pos(3, A, 1, 1); - cornerSprite(emitter, sprite); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, 0, 1, B) + .pos(1, 0, 0, B) + .pos(2, A, 0, 1) + .pos(3, A, 1, 1); + cornerSprite(emitter, material); + emitter.shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); // south - emitter.pos(0, A, 1, 1); - emitter.pos(1, A, 0, 1); - emitter.pos(2, B, 0, 1); - emitter.pos(3, B, 1, 1); - emitter.cullFace(Direction.SOUTH); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, A, 1, 1) + .pos(1, A, 0, 1) + .pos(2, B, 0, 1) + .pos(3, B, 1, 1) + .cullFace(Direction.SOUTH) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); // southeast - emitter.pos(0, B, 1, 1); - emitter.pos(1, B, 0, 1); - emitter.pos(2, 1, 0, B); - emitter.pos(3, 1, 1, B); - cornerSprite(emitter, sprite); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, B, 1, 1) + .pos(1, B, 0, 1) + .pos(2, 1, 0, B) + .pos(3, 1, 1, B); + cornerSprite(emitter, material); + emitter.shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); // east - emitter.pos(0, 1, 1, B); - emitter.pos(1, 1, 0, B); - emitter.pos(2, 1, 0, A); - emitter.pos(3, 1, 1, A); - emitter.cullFace(Direction.EAST); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, 1, 1, B) + .pos(1, 1, 0, B) + .pos(2, 1, 0, A) + .pos(3, 1, 1, A) + .cullFace(Direction.EAST) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); // northeast - emitter.pos(0, 1, 1, A); - emitter.pos(1, 1, 0, A); - emitter.pos(2, B, 0, 0); - emitter.pos(3, B, 1, 0); - cornerSprite(emitter, sprite); - emitter.shadeMode(shadeMode); - emitter.foilType(ItemStackRenderState.FoilType.STANDARD); - emitter.emit(); + emitter.pos(0, 1, 1, A) + .pos(1, 1, 0, A) + .pos(2, B, 0, 0) + .pos(3, B, 1, 0); + cornerSprite(emitter, material); + emitter.shadeMode(shadeMode) + .foilType(ItemStackRenderState.FoilType.STANDARD) + .emit(); return new MeshQuadCollection(builder.immutableCopy()); } - private static void cornerSprite(QuadEmitter emitter, TextureAtlasSprite sprite) { + private static void cornerSprite(QuadEmitter emitter, Material.Baked material) { // Assign uvs for a corner face in such a way that the texture is not stretched, using coordinates in [0, 1]. - emitter.uv(0, A, 0); - emitter.uv(1, A, 1); - emitter.uv(2, B, 1); - emitter.uv(3, B, 0); + emitter.uv(0, A, 0) + .uv(1, A, 1) + .uv(2, B, 1) + .uv(3, B, 0); // Map [0, 1] coordinates to sprite atlas coordinates. spriteBake assumes [0, 16] unless we pass the BAKE_NORMALIZED flag. - emitter.spriteBake(sprite, MutableQuadView.BAKE_NORMALIZED); + emitter.materialBake(material, MutableQuadView.BAKE_NORMALIZED); } } diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OverlayedGeometry.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OverlayedGeometry.java index 1e3f2b8a26..5a3bb35730 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OverlayedGeometry.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OverlayedGeometry.java @@ -16,7 +16,10 @@ package net.fabricmc.fabric.test.renderer.client; +import java.util.Objects; + import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.block.model.TextureSlots; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.ModelBaker; @@ -44,8 +47,10 @@ public QuadCollection bake(TextureSlots textures, ModelBaker modelBaker, ModelSt ResolvedModel parentModel = modelBaker.getModel(parentId); QuadCollection parentQuads = parentModel.bakeTopGeometry(parentModel.getTopTextureSlots(), modelBaker, modelState); - TextureAtlasSprite overlaySprite = modelBaker.sprites().get(textures.getMaterial("overlay"), name); - QuadAtlas overlayAtlas = QuadAtlas.of(overlaySprite.atlasLocation()); + Material.Baked overlayMaterial = modelBaker.materials() + .get(Objects.requireNonNull(textures.getMaterial("overlay")), name); + TextureAtlasSprite overlaySprite = overlayMaterial.sprite(); + QuadAtlas overlayAtlas = QuadAtlas.ofLocation(overlaySprite.atlasLocation()); if (overlayAtlas == null) { return parentQuads; @@ -55,9 +60,8 @@ public QuadCollection bake(TextureSlots textures, ModelBaker modelBaker, ModelSt meshQuadCollection.getMesh().forEach(quad -> { emitter.copyFrom(quad).emit(); emitter.copyFrom(quad); - emitter.atlas(overlayAtlas); - TextureAtlasSprite sprite = modelBaker.sprites().spriteFinder(emitter.atlas()).find(emitter); + TextureAtlasSprite sprite = modelBaker.materials().spriteFinder(emitter.atlas()).find(emitter); for (int i = 0; i < 4; i++) { emitter.uv( @@ -67,6 +71,7 @@ public QuadCollection bake(TextureSlots textures, ModelBaker modelBaker, ModelSt ); } + ModelHelper.setSpriteInfo(emitter, overlayMaterial); emitter.emit(); }); } else { @@ -76,9 +81,8 @@ public QuadCollection bake(TextureSlots textures, ModelBaker modelBaker, ModelSt for (BakedQuad bakedQuad : parentQuads.getQuads(cullFace)) { emitter.fromBakedQuad(bakedQuad).cullFace(cullFace).emit(); emitter.fromBakedQuad(bakedQuad).cullFace(cullFace); - emitter.atlas(overlayAtlas); - TextureAtlasSprite sprite = bakedQuad.sprite(); + TextureAtlasSprite sprite = bakedQuad.spriteInfo().sprite(); for (int j = 0; j < 4; j++) { emitter.uv( @@ -88,6 +92,7 @@ public QuadCollection bake(TextureSlots textures, ModelBaker modelBaker, ModelSt ); } + ModelHelper.setSpriteInfo(emitter, overlayMaterial); emitter.emit(); } } diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarBlockStateModel.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarBlockStateModel.java index 3314a0382b..98564d70a9 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarBlockStateModel.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarBlockStateModel.java @@ -25,9 +25,7 @@ import net.minecraft.client.renderer.block.model.BlockModelPart; import net.minecraft.client.renderer.block.model.BlockStateModel; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.Material; +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.client.resources.model.ModelDebugName; import net.minecraft.core.BlockPos; @@ -52,19 +50,31 @@ private enum ConnectedTexture { } // alone, bottom, middle, top - private final TextureAtlasSprite[] sprites; + private final Material.Baked[] materials; + private final boolean hasTranslucency; - public PillarBlockStateModel(TextureAtlasSprite[] sprites) { - this.sprites = sprites; + public PillarBlockStateModel(Material.Baked[] materials) { + this.materials = materials; + + boolean hasTranslucency = false; + + for (Material.Baked material : materials) { + hasTranslucency |= material.forceTranslucent() || material.sprite() + .contents() + .computeTransparency(0.0f, 0.0f, 1.0f, 1.0f) + .hasTranslucent(); + } + + this.hasTranslucency = hasTranslucency; } @Override public void emitQuads(QuadEmitter emitter, BlockAndTintGetter level, BlockPos pos, BlockState state, RandomSource random, Predicate<@Nullable Direction> cullTest) { for (Direction side : Direction.values()) { ConnectedTexture texture = getConnectedTexture(level, pos, state, side); - emitter.square(side, 0, 0, 1, 1, 0); - emitter.spriteBake(sprites[texture.ordinal()], MutableQuadView.BAKE_LOCK_UV); - emitter.emit(); + emitter.square(side, 0, 0, 1, 1, 0) + .materialBake(materials[texture.ordinal()], MutableQuadView.BAKE_LOCK_UV) + .emit(); } } @@ -111,11 +121,7 @@ private static boolean canConnect(BlockAndTintGetter level, BlockState originSta BlockState otherAppearance = ((FabricBlockState) otherState).getAppearance( level, otherPos, side, originState, originPos); - if (!otherAppearance.is(Registration.PILLAR_BLOCK)) { - return false; - } - - return true; + return otherAppearance.is(Registration.PILLAR_BLOCK); } @Override @@ -123,13 +129,18 @@ public void collectParts(RandomSource random, List parts) { } @Override - public TextureAtlasSprite particleIcon() { - return sprites[0]; + public Material.Baked particleMaterial() { + return this.materials[0]; + } + + @Override + public boolean hasTranslucency() { + return hasTranslucency; } public record Unbaked() implements CustomUnbakedBlockStateModel, ModelDebugName { - private static final List SPRITES = Stream.of("alone", "bottom", "middle", "top") - .map(suffix -> new Material(TextureAtlas.LOCATION_BLOCKS, RendererTest.id("block/pillar_" + suffix))) + private static final List MATERIALS = Stream.of("alone", "bottom", "middle", "top") + .map(suffix -> new Material(RendererTest.id("block/pillar_" + suffix))) .toList(); public static final Unbaked INSTANCE = new Unbaked(); public static final MapCodec CODEC = MapCodec.unit(INSTANCE); @@ -145,13 +156,15 @@ public void resolveDependencies(Resolver resolver) { @Override public BlockStateModel bake(ModelBaker baker) { - TextureAtlasSprite[] sprites = new TextureAtlasSprite[SPRITES.size()]; + Material.Baked[] materials = new Material.Baked[MATERIALS.size()]; - for (int i = 0; i < sprites.length; ++i) { - sprites[i] = baker.sprites().get(SPRITES.get(i), this); + for (int i = 0; i < materials.length; ++i) { + Material.Baked material = baker.materials() + .get(MATERIALS.get(i), this); + materials[i] = material; } - return new PillarBlockStateModel(sprites); + return new PillarBlockStateModel(materials); } @Override diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarGeometry.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarGeometry.java index eb4d12ec3d..f818ef2869 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarGeometry.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/PillarGeometry.java @@ -16,8 +16,10 @@ package net.fabricmc.fabric.test.renderer.client; +import java.util.Objects; + +import net.minecraft.client.renderer.block.model.Material; import net.minecraft.client.renderer.block.model.TextureSlots; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.client.resources.model.ModelDebugName; import net.minecraft.client.resources.model.ModelState; @@ -37,14 +39,15 @@ public record PillarGeometry() implements UnbakedGeometry { public QuadCollection bake(TextureSlots textures, ModelBaker baker, ModelState settings, ModelDebugName model) { MutableMesh builder = Renderer.get().mutableMesh(); QuadEmitter emitter = builder.emitter(); - emitter.pushTransform(ModelStateHelper.asQuadTransform(settings, baker.sprites())); + emitter.pushTransform(ModelStateHelper.asQuadTransform(settings, baker.materials())); - TextureAtlasSprite sprite = baker.sprites().get(textures.getMaterial("pillar"), model); + Material.Baked material = baker.materials() + .get(Objects.requireNonNull(textures.getMaterial("pillar")), model); for (Direction side : Direction.values()) { - emitter.square(side, 0, 0, 1, 1, 0); - emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV); - emitter.emit(); + emitter.square(side, 0, 0, 1, 1, 0) + .materialBake(material, MutableQuadView.BAKE_LOCK_UV) + .emit(); } return new MeshQuadCollection(builder.immutableCopy()); diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RendererClientTest.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RendererClientTest.java index 5f2406a693..5b984d5722 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RendererClientTest.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RendererClientTest.java @@ -16,14 +16,10 @@ package net.fabricmc.fabric.test.renderer.client; -import net.minecraft.client.renderer.chunk.ChunkSectionLayer; - import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.model.loading.v1.CustomUnbakedBlockStateModel; import net.fabricmc.fabric.api.client.model.loading.v1.UnbakedModelDeserializer; import net.fabricmc.fabric.api.client.renderer.v1.Renderer; -import net.fabricmc.fabric.api.client.rendering.v1.ChunkSectionLayerMap; -import net.fabricmc.fabric.test.renderer.Registration; import net.fabricmc.fabric.test.renderer.RendererTest; public final class RendererClientTest implements ClientModInitializer { @@ -36,10 +32,6 @@ public void onInitializeClient() { CustomUnbakedBlockStateModel.register(RendererTest.id("frame"), FrameBlockStateModel.Unbaked.CODEC); CustomUnbakedBlockStateModel.register(RendererTest.id("pillar"), PillarBlockStateModel.Unbaked.CODEC); - // We don't specify a material for the frame mesh, - // so it will use the default material, i.e. the one from ChunkSectionLayers. - ChunkSectionLayerMap.putBlock(Registration.FRAME_BLOCK, ChunkSectionLayer.CUTOUT); - try { // if it crashes, that means the ordering is #*@!ed up. Renderer.get(); // Ensure Renderer can be initialized as early as mod init diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/Indigo.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/Indigo.java index 98d7ff8f91..edf3f27927 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/Indigo.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/Indigo.java @@ -28,6 +28,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.minecraft.client.renderer.MultiBufferSource; + import net.fabricmc.fabric.api.util.TriState; import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoConfig; import net.fabricmc.loader.api.FabricLoader; @@ -46,6 +48,9 @@ public class Indigo { /** If set the default config file will be generated on startup, restoring pre 26.1 behavior. */ private static final boolean GENERATE_CONFIG_FILE = System.getProperty("fabric.indigo.generateConfigFile") != null; + // A hack for Mixins, check usages + public static final ScopedValue LEVEL_RENDERER_BUFFER_SOURCE = ScopedValue.newInstance(); + private static boolean asBoolean(@Nullable String property, boolean defValue) { return asTriState(property).orElse(defValue); } @@ -90,12 +95,12 @@ private static TriState asTriState(@Nullable String property) { } } - AMBIENT_OCCLUSION_MODE = asEnum((String) properties.computeIfAbsent("ambient-occlusion-mode", (_) -> "hybrid"), AoConfig.HYBRID); - DEBUG_COMPARE_LIGHTING = asBoolean((String) properties.computeIfAbsent("debug-compare-lighting", (_) -> "auto"), false); - FIX_SMOOTH_LIGHTING_OFFSET = asBoolean((String) properties.computeIfAbsent("fix-smooth-lighting-offset", (_) -> "auto"), true); - boolean fixMeanLightCalculation = asBoolean((String) properties.computeIfAbsent("fix-mean-light-calculation", (_) -> "auto"), true); - FIX_EXTERIOR_VERTEX_LIGHTING = asBoolean((String) properties.computeIfAbsent("fix-exterior-vertex-lighting", (_) -> "auto"), true); - FIX_LUMINOUS_AO_SHADE = asBoolean((String) properties.computeIfAbsent("fix-luminous-block-ambient-occlusion", (_) -> "auto"), false); + AMBIENT_OCCLUSION_MODE = asEnum((String) properties.computeIfAbsent("ambient-occlusion-mode", _ -> "hybrid"), AoConfig.HYBRID); + DEBUG_COMPARE_LIGHTING = asBoolean((String) properties.computeIfAbsent("debug-compare-lighting", _ -> "auto"), false); + FIX_SMOOTH_LIGHTING_OFFSET = asBoolean((String) properties.computeIfAbsent("fix-smooth-lighting-offset", _ -> "auto"), true); + boolean fixMeanLightCalculation = asBoolean((String) properties.computeIfAbsent("fix-mean-light-calculation", _ -> "auto"), true); + FIX_EXTERIOR_VERTEX_LIGHTING = asBoolean((String) properties.computeIfAbsent("fix-exterior-vertex-lighting", _ -> "auto"), true); + FIX_LUMINOUS_AO_SHADE = asBoolean((String) properties.computeIfAbsent("fix-luminous-block-ambient-occlusion", _ -> "auto"), false); if (fixMeanLightCalculation && !FIX_SMOOTH_LIGHTING_OFFSET) { fixMeanLightCalculation = false; diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java index f26b7e0f5a..22ae2c98cc 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java @@ -19,6 +19,7 @@ import java.util.function.Predicate; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import org.jspecify.annotations.Nullable; import net.minecraft.client.renderer.MultiBufferSource; @@ -27,6 +28,7 @@ import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.RenderShape; @@ -38,7 +40,6 @@ import net.fabricmc.fabric.api.client.renderer.v1.render.BlockMultiBufferSource; import net.fabricmc.fabric.api.client.renderer.v1.render.ChunkSectionLayerHelper; 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.indigo.renderer.accessor.AccessLayerRenderState; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableMeshImpl; import net.fabricmc.fabric.impl.client.indigo.renderer.render.SimpleBlockRenderContext; @@ -74,9 +75,26 @@ public void tesselateBlock(ModelBlockRenderer blockRenderer, BlockAndTintGetter } @Override - public void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, @Nullable Predicate layerFilter, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { + public void renderModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, @Nullable Predicate layerFilter, BlockStateModel model, int tintColor, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { SimpleBlockRenderContext.POOL.get().bufferModel( - pose, bufferSource, layerFilter, model, red, green, blue, light, overlay, level, pos, state); + pose, bufferSource, layerFilter, model, tintColor, light, overlay, level, pos, state); + } + + @Override + public void renderBreakingTexture( + BlockRenderDispatcher renderDispatcher, + BlockState state, + BlockPos pos, + BlockAndTintGetter level, + PoseStack poseStack, + VertexConsumer vertexConsumer + ) { + if (state.getRenderShape() == RenderShape.MODEL) { + BlockStateModel model = renderDispatcher.getBlockModel(state); + TerrainLikeRenderContext.POOL.get() + .bufferModel(level, model, state, pos, poseStack, _ -> vertexConsumer, + null, true, state.getSeed(pos), OverlayTexture.NO_OVERLAY); + } } @Override @@ -86,12 +104,9 @@ public void renderSingleBlock(BlockRenderDispatcher renderDispatcher, BlockState if (renderShape != RenderShape.INVISIBLE) { BlockStateModel model = renderDispatcher.getBlockModel(state); int tint = ((BlockRenderDispatcherAccessor) renderDispatcher).getBlockColors().getColor(state, null, null, 0); - float red = (tint >> 16 & 255) / 255.0F; - float green = (tint >> 8 & 255) / 255.0F; - float blue = (tint & 255) / 255.0F; FabricModelBlockRenderer.renderModel( poseStack.last(), ChunkSectionLayerHelper.entityDelegate( - bufferSource), layerFilter, model, red, green, blue, light, overlay, + bufferSource), layerFilter, model, tint, light, overlay, level, pos, state); } } @@ -100,12 +115,4 @@ public void renderSingleBlock(BlockRenderDispatcher renderDispatcher, BlockState public QuadEmitter getLayerRenderStateEmitter(ItemStackRenderState.LayerRenderState layer) { return ((AccessLayerRenderState) layer).fabric_getMutableMesh().emitter(); } - - @Override - public void setLayerRenderTypeGetter( - ItemStackRenderState.LayerRenderState layer, - ItemRenderTypeGetter renderTypeGetter - ) { - ((AccessLayerRenderState) layer).fabric_setRenderTypeGetter(renderTypeGetter); - } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessLayerRenderState.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessLayerRenderState.java index 82bc5498cc..b86a68b515 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessLayerRenderState.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessLayerRenderState.java @@ -16,11 +16,8 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.accessor; -import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableMeshImpl; public interface AccessLayerRenderState { MutableMeshImpl fabric_getMutableMesh(); - - void fabric_setRenderTypeGetter(ItemRenderTypeGetter renderTypeGetter); } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessOrderedSubmitNodeCollector.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessOrderedSubmitNodeCollector.java index 8080030a73..a8a6016345 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessOrderedSubmitNodeCollector.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/accessor/AccessOrderedSubmitNodeCollector.java @@ -19,15 +19,12 @@ import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; -import org.jspecify.annotations.Nullable; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.world.item.ItemDisplayContext; import net.fabricmc.fabric.api.client.renderer.v1.mesh.MeshView; -import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter; public interface AccessOrderedSubmitNodeCollector { void fabric_submitItem( @@ -38,9 +35,7 @@ void fabric_submitItem( int outlineColors, int[] tintLayers, List quads, - RenderType renderType, ItemStackRenderState.FoilType foilType, - MeshView mesh, - @Nullable ItemRenderTypeGetter renderTypeGetter + MeshView mesh ); } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java index 617ff13630..fab4118ac3 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java @@ -17,13 +17,12 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.mesh; import com.google.common.base.Preconditions; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; import org.apache.commons.lang3.ArrayUtils; import org.jspecify.annotations.Nullable; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.core.Direction; import net.minecraft.util.Mth; @@ -55,23 +54,36 @@ private EncodingFormat() { } static final int VERTEX_V; static final int VERTEX_LIGHTMAP; static final int VERTEX_NORMAL; - public static final int VERTEX_STRIDE; + private static final int VERTEX_POSITION_BYTES = Float.BYTES; + private static final int VERTEX_COLOR_BYTES = Integer.BYTES; + private static final int VERTEX_UV_BYTES = Float.BYTES; + private static final int VERTEX_LIGHTMAP_BYTES = Integer.BYTES; + private static final int VERTEX_NORMAL_BYTES = Integer.BYTES; + private static final int VERTEX_COLOR_SIZE = VERTEX_COLOR_BYTES / 4; + private static final int VERTEX_UV_SIZE = VERTEX_UV_BYTES / 4; + private static final int VERTEX_LIGHTMAP_SIZE = VERTEX_LIGHTMAP_BYTES / 4; + private static final int VERTEX_NORMAL_SIZE = VERTEX_NORMAL_BYTES / 4; + private static final int VERTEX_POSITION_SIZE = VERTEX_POSITION_BYTES / 4; + public static final int VERTEX_STRIDE = + 3 * VERTEX_POSITION_SIZE + + VERTEX_COLOR_SIZE + + 2 * VERTEX_UV_SIZE + + VERTEX_LIGHTMAP_SIZE + + VERTEX_NORMAL_SIZE; public static final int QUAD_STRIDE; public static final int QUAD_STRIDE_BYTES; public static final int TOTAL_STRIDE; static { - final VertexFormat format = DefaultVertexFormat.BLOCK; VERTEX_X = HEADER_STRIDE + 0; - VERTEX_Y = HEADER_STRIDE + 1; - VERTEX_Z = HEADER_STRIDE + 2; - VERTEX_COLOR = HEADER_STRIDE + 3; - VERTEX_U = HEADER_STRIDE + 4; - VERTEX_V = VERTEX_U + 1; - VERTEX_LIGHTMAP = HEADER_STRIDE + 6; - VERTEX_NORMAL = HEADER_STRIDE + 7; - VERTEX_STRIDE = format.getVertexSize() / 4; + VERTEX_Y = VERTEX_X + VERTEX_POSITION_SIZE; + VERTEX_Z = VERTEX_Y + VERTEX_POSITION_SIZE; + VERTEX_COLOR = VERTEX_Z + VERTEX_COLOR_SIZE; + VERTEX_U = VERTEX_COLOR + VERTEX_UV_SIZE; + VERTEX_V = VERTEX_U + VERTEX_UV_SIZE; + VERTEX_LIGHTMAP = VERTEX_V + VERTEX_LIGHTMAP_SIZE; + VERTEX_NORMAL = VERTEX_LIGHTMAP + VERTEX_NORMAL_SIZE; QUAD_STRIDE = VERTEX_STRIDE * 4; QUAD_STRIDE_BYTES = QUAD_STRIDE * 4; TOTAL_STRIDE = HEADER_STRIDE + QUAD_STRIDE; @@ -80,8 +92,10 @@ private EncodingFormat() { } private static final int DIRECTION_COUNT = Direction.values().length; private static final int NULLABLE_DIRECTION_COUNT = DIRECTION_COUNT + 1; - private static final @Nullable ChunkSectionLayer[] NULLABLE_CHUNK_SECTION_LAYERS = ArrayUtils.add(ChunkSectionLayer.values(), null); - private static final int NULLABLE_CHUNK_SECTION_LAYER_COUNT = NULLABLE_CHUNK_SECTION_LAYERS.length; + private static final ChunkSectionLayer[] CHUNK_SECTION_LAYERS = ChunkSectionLayer.values(); + private static final int CHUNK_SECTION_LAYER_COUNT = CHUNK_SECTION_LAYERS.length; + private static final RenderType[] ITEM_RENDER_TYPES = ItemRenderType.RENDER_TYPES; + private static final int ITEM_RENDER_TYPE_COUNT = ITEM_RENDER_TYPES.length; private static final TriState[] TRI_STATES = TriState.values(); private static final int TRI_STATE_COUNT = TRI_STATES.length; private static final ItemStackRenderState.@Nullable FoilType[] NULLABLE_FOIL_TYPES = ArrayUtils.add(ItemStackRenderState.FoilType.values(), null); @@ -91,44 +105,46 @@ private EncodingFormat() { } private static final QuadAtlas[] QUAD_ATLASES = QuadAtlas.values(); private static final int QUAD_ATLAS_COUNT = QUAD_ATLASES.length; - private static final int NULL_CHUNK_LAYER_INDEX = NULLABLE_CHUNK_SECTION_LAYER_COUNT - 1; private static final int NULL_FOIL_TYPE_INDEX = NULLABLE_FOIL_TYPE_COUNT - 1; private static final int CULL_BIT_LENGTH = Mth.ceillog2(NULLABLE_DIRECTION_COUNT); private static final int LIGHT_BIT_LENGTH = Mth.ceillog2(DIRECTION_COUNT); private static final int NORMALS_BIT_LENGTH = 4; private static final int GEOMETRY_BIT_LENGTH = GeometryHelper.FLAG_BIT_COUNT; - private static final int CHUNK_LAYER_BIT_LENGTH = Mth.ceillog2( - NULLABLE_CHUNK_SECTION_LAYER_COUNT); + private static final int QUAD_ATLAS_BIT_LENGTH = Mth.ceillog2(QUAD_ATLAS_COUNT); + private static final int CHUNK_LAYER_BIT_LENGTH = Mth.ceillog2(CHUNK_SECTION_LAYER_COUNT); + private static final int ITEM_RENDER_TYPE_BIT_LENGTH = Mth.ceillog2(ITEM_RENDER_TYPE_COUNT); private static final int EMISSIVE_BIT_LENGTH = 1; private static final int DIFFUSE_BIT_LENGTH = 1; private static final int AO_BIT_LENGTH = Mth.ceillog2(TRI_STATE_COUNT); private static final int FOIL_TYPE_BIT_LENGTH = Mth.ceillog2( NULLABLE_FOIL_TYPE_COUNT); private static final int SHADE_MODE_BIT_LENGTH = Mth.ceillog2(SHADE_MODE_COUNT); - private static final int QUAD_ATLAS_BIT_LENGTH = Mth.ceillog2(QUAD_ATLAS_COUNT); private static final int CULL_BIT_OFFSET = 0; private static final int LIGHT_BIT_OFFSET = CULL_BIT_OFFSET + CULL_BIT_LENGTH; private static final int NORMALS_BIT_OFFSET = LIGHT_BIT_OFFSET + LIGHT_BIT_LENGTH; private static final int GEOMETRY_BIT_OFFSET = NORMALS_BIT_OFFSET + NORMALS_BIT_LENGTH; - private static final int CHUNK_LAYER_BIT_OFFSET = GEOMETRY_BIT_OFFSET + GEOMETRY_BIT_LENGTH; - private static final int EMISSIVE_BIT_OFFSET = CHUNK_LAYER_BIT_OFFSET + CHUNK_LAYER_BIT_LENGTH; + private static final int QUAD_ATLAS_BIT_OFFSET = GEOMETRY_BIT_OFFSET + GEOMETRY_BIT_LENGTH; + private static final int CHUNK_LAYER_BIT_OFFSET = QUAD_ATLAS_BIT_OFFSET + QUAD_ATLAS_BIT_LENGTH; + private static final int ITEM_RENDER_TYPE_BIT_OFFSET = CHUNK_LAYER_BIT_OFFSET + CHUNK_LAYER_BIT_LENGTH; + private static final int EMISSIVE_BIT_OFFSET = ITEM_RENDER_TYPE_BIT_OFFSET + ITEM_RENDER_TYPE_BIT_LENGTH; private static final int DIFFUSE_BIT_OFFSET = EMISSIVE_BIT_OFFSET + EMISSIVE_BIT_LENGTH; private static final int AO_BIT_OFFSET = DIFFUSE_BIT_OFFSET + DIFFUSE_BIT_LENGTH; private static final int FOIL_TYPE_BIT_OFFSET = AO_BIT_OFFSET + AO_BIT_LENGTH; private static final int SHADE_MODE_BIT_OFFSET = FOIL_TYPE_BIT_OFFSET + FOIL_TYPE_BIT_LENGTH; - private static final int QUAD_ATLAS_BIT_OFFSET = SHADE_MODE_BIT_OFFSET + SHADE_MODE_BIT_LENGTH; - private static final int TOTAL_BIT_LENGTH = QUAD_ATLAS_BIT_OFFSET + QUAD_ATLAS_BIT_LENGTH; + private static final int TOTAL_BIT_LENGTH = SHADE_MODE_BIT_OFFSET + SHADE_MODE_BIT_LENGTH; private static final int CULL_MASK = bitMask(CULL_BIT_LENGTH, CULL_BIT_OFFSET); private static final int LIGHT_MASK = bitMask(LIGHT_BIT_LENGTH, LIGHT_BIT_OFFSET); private static final int NORMALS_MASK = bitMask(NORMALS_BIT_LENGTH, NORMALS_BIT_OFFSET); private static final int GEOMETRY_MASK = bitMask(GEOMETRY_BIT_LENGTH, GEOMETRY_BIT_OFFSET); + private static final int QUAD_ATLAS_MASK = bitMask(QUAD_ATLAS_BIT_LENGTH, QUAD_ATLAS_BIT_OFFSET); private static final int CHUNK_LAYER_MASK = bitMask( CHUNK_LAYER_BIT_LENGTH, CHUNK_LAYER_BIT_OFFSET ); + private static final int ITEM_RENDER_TYPE_MASK = bitMask(ITEM_RENDER_TYPE_BIT_LENGTH, ITEM_RENDER_TYPE_BIT_OFFSET); private static final int EMISSIVE_MASK = bitMask(EMISSIVE_BIT_LENGTH, EMISSIVE_BIT_OFFSET); private static final int DIFFUSE_MASK = bitMask(DIFFUSE_BIT_LENGTH, DIFFUSE_BIT_OFFSET); private static final int AO_MASK = bitMask(AO_BIT_LENGTH, AO_BIT_OFFSET); @@ -136,7 +152,6 @@ private EncodingFormat() { } FOIL_TYPE_BIT_OFFSET ); private static final int SHADE_MODE_MASK = bitMask(SHADE_MODE_BIT_LENGTH, SHADE_MODE_BIT_OFFSET); - private static final int QUAD_ATLAS_MASK = bitMask(QUAD_ATLAS_BIT_LENGTH, QUAD_ATLAS_BIT_OFFSET); static { Preconditions.checkArgument(TOTAL_BIT_LENGTH <= 32, "Indigo header encoding bit count (%s) exceeds integer bit length)", TOTAL_STRIDE); @@ -180,14 +195,28 @@ static int geometryFlags(int bits, int geometryFlags) { return (bits & ~GEOMETRY_MASK) | ((geometryFlags << GEOMETRY_BIT_OFFSET) & GEOMETRY_MASK); } - @Nullable + static QuadAtlas quadAtlas(int bits) { + return QUAD_ATLASES[(bits & QUAD_ATLAS_MASK) >>> QUAD_ATLAS_BIT_OFFSET]; + } + + static int quadAtlas(int bits, QuadAtlas quadAtlas) { + return (bits & ~QUAD_ATLAS_MASK) | (quadAtlas.ordinal() << QUAD_ATLAS_BIT_OFFSET); + } + static ChunkSectionLayer chunkLayer(int bits) { - return NULLABLE_CHUNK_SECTION_LAYERS[(bits & CHUNK_LAYER_MASK) >>> CHUNK_LAYER_BIT_OFFSET]; + return CHUNK_SECTION_LAYERS[(bits & CHUNK_LAYER_MASK) >>> CHUNK_LAYER_BIT_OFFSET]; } - static int chunkLayer(int bits, @Nullable ChunkSectionLayer layer) { - int index = layer == null ? NULL_CHUNK_LAYER_INDEX : layer.ordinal(); - return (bits & ~CHUNK_LAYER_MASK) | (index << CHUNK_LAYER_BIT_OFFSET); + static int chunkLayer(int bits, ChunkSectionLayer layer) { + return (bits & ~CHUNK_LAYER_MASK) | (layer.ordinal() << CHUNK_LAYER_BIT_OFFSET); + } + + static RenderType itemRenderType(int bits) { + return ITEM_RENDER_TYPES[(bits & ITEM_RENDER_TYPE_MASK) >>> ITEM_RENDER_TYPE_BIT_OFFSET]; + } + + static int itemRenderType(int bits, ItemRenderType renderType) { + return (bits & ~ITEM_RENDER_TYPE_MASK) | (renderType.ordinal() << ITEM_RENDER_TYPE_BIT_OFFSET); } static boolean emissive(int bits) { @@ -230,12 +259,4 @@ static ShadeMode shadeMode(int bits) { static int shadeMode(int bits, ShadeMode mode) { return (bits & ~SHADE_MODE_MASK) | (mode.ordinal() << SHADE_MODE_BIT_OFFSET); } - - static QuadAtlas quadAtlas(int bits) { - return QUAD_ATLASES[(bits & QUAD_ATLAS_MASK) >>> QUAD_ATLAS_BIT_OFFSET]; - } - - static int quadAtlas(int bits, QuadAtlas quadAtlas) { - return (bits & ~QUAD_ATLAS_MASK) | (quadAtlas.ordinal() << QUAD_ATLAS_BIT_OFFSET); - } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/ItemRenderType.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/ItemRenderType.java new file mode 100644 index 0000000000..d7cfb56c89 --- /dev/null +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/ItemRenderType.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.client.indigo.renderer.mesh; + +import java.util.Arrays; +import java.util.Map; + +import net.minecraft.client.renderer.Sheets; +import net.minecraft.client.renderer.rendertype.RenderType; + +import net.fabricmc.fabric.api.client.renderer.v1.mesh.MutableQuadView; + +/** + * Allowed values for {@link MutableQuadView#itemRenderType(RenderType)}. + */ +enum ItemRenderType { + CUTOUT(Sheets.cutoutItemSheet()), + TRANSLUCENT(Sheets.translucentItemSheet()), + CUTOUT_BLOCK(Sheets.cutoutBlockItemSheet()), + TRANSLUCENT_BLOCK(Sheets.translucentBlockItemSheet()); + + static final RenderType[] RENDER_TYPES = Arrays.stream(ItemRenderType.values()).map(t -> t.renderType).toArray(RenderType[]::new); + static final Map RENDER_TYPE_2_ENUM; + + static { + RENDER_TYPE_2_ENUM = Map.of( + CUTOUT.renderType, CUTOUT, + TRANSLUCENT.renderType, TRANSLUCENT, + CUTOUT_BLOCK.renderType, CUTOUT_BLOCK, + TRANSLUCENT_BLOCK.renderType, TRANSLUCENT_BLOCK + ); + } + + // The atlas of the default render type should match the default QuadAtlas, which is currently BLOCK. + static final ItemRenderType DEFAULT = ItemRenderType.CUTOUT_BLOCK; + + final RenderType renderType; + + ItemRenderType(RenderType renderType) { + this.renderType = renderType; + } +} diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java index 4d6ab45c78..8c2dcceeb6 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java @@ -35,6 +35,7 @@ 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.core.Direction; import net.minecraft.util.LightCoordsUtil; @@ -57,7 +58,7 @@ * numbers. It also allows for a consistent interface for those transformations. */ public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEmitter { - private static final QuadTransform NO_TRANSFORM = q -> true; + private static final QuadTransform NO_TRANSFORM = _ -> true; private static final int[] DEFAULT_QUAD_DATA = new int[EncodingFormat.TOTAL_STRIDE]; @@ -74,7 +75,8 @@ protected void emitDirectly() { // Apply non-zero defaults quad.color(-1, -1, -1, -1); quad.cullFace(null); - quad.chunkLayer(null); + quad.chunkLayer(ChunkSectionLayer.CUTOUT); + quad.itemRenderType(ItemRenderType.DEFAULT.renderType); quad.diffuseShade(true); quad.ambientOcclusion(TriState.DEFAULT); quad.foilType(null); @@ -175,10 +177,19 @@ public final MutableQuadViewImpl cullFace(@Nullable Direction face) { } @Override - public MutableQuadViewImpl chunkLayer(@Nullable ChunkSectionLayer layer) { - data[baseIndex + HEADER_BITS] = EncodingFormat.chunkLayer(data[baseIndex + HEADER_BITS], - layer - ); + public MutableQuadViewImpl chunkLayer(ChunkSectionLayer layer) { + data[baseIndex + HEADER_BITS] = EncodingFormat.chunkLayer(data[baseIndex + HEADER_BITS], layer); + return this; + } + + @Override + public MutableQuadViewImpl itemRenderType(RenderType renderType) { + ItemRenderType enumValue = ItemRenderType.RENDER_TYPE_2_ENUM.get(renderType); + + if (enumValue != null) { + data[baseIndex + HEADER_BITS] = EncodingFormat.itemRenderType(data[baseIndex + HEADER_BITS], enumValue); + } + return this; } @@ -275,13 +286,15 @@ public final MutableQuadViewImpl fromBakedQuad(BakedQuad quad) { nominalFace(quad.direction()); emissive(lightEmission == 15); diffuseShade(quad.shade()); - QuadAtlas atlas = QuadAtlas.of(quad.sprite().atlasLocation()); + QuadAtlas atlas = QuadAtlas.ofLocation(quad.spriteInfo().sprite().atlasLocation()); if (atlas == null) { atlas = QuadAtlas.BLOCK; } atlas(atlas); + chunkLayer(quad.spriteInfo().layer()); + itemRenderType(quad.spriteInfo().itemRenderType()); tintIndex(quad.tintIndex()); return this; } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java index 8f45f817b0..03e221d803 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java @@ -37,6 +37,7 @@ import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.core.Direction; import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadAtlas; @@ -240,11 +241,20 @@ public final Direction cullFace() { } @Override - @Nullable + public QuadAtlas atlas() { + return EncodingFormat.quadAtlas(data[baseIndex + HEADER_BITS]); + } + + @Override public ChunkSectionLayer chunkLayer() { return EncodingFormat.chunkLayer(data[baseIndex + HEADER_BITS]); } + @Override + public RenderType itemRenderType() { + return EncodingFormat.itemRenderType(data[baseIndex + HEADER_BITS]); + } + @Override public boolean emissive() { return EncodingFormat.emissive(data[baseIndex + HEADER_BITS]); @@ -270,11 +280,6 @@ public ShadeMode shadeMode() { return EncodingFormat.shadeMode(data[baseIndex + HEADER_BITS]); } - @Override - public QuadAtlas atlas() { - return EncodingFormat.quadAtlas(data[baseIndex + HEADER_BITS]); - } - @Override public final int tintIndex() { return data[baseIndex + HEADER_TINT_INDEX]; diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java index ed1eb2d73e..503e9fbd41 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java @@ -44,7 +44,7 @@ public class BlockRenderInfo { private boolean useAo; private boolean defaultAo; - private ChunkSectionLayer defaultLayer; + private boolean forceOpaque; private boolean enableCulling; private int cullCompletionFlags; @@ -62,7 +62,7 @@ public void prepareForBlock(BlockPos blockPos, BlockState blockState) { useAo = Minecraft.useAmbientOcclusion(); defaultAo = useAo && blockState.getLightEmission() == 0; - defaultLayer = ItemBlockRenderTypes.getChunkRenderType(blockState); + forceOpaque = ItemBlockRenderTypes.forceOpaque(blockState); cullCompletionFlags = 0; cullResultFlags = 0; @@ -83,8 +83,8 @@ public boolean effectiveAo(TriState aoMode) { return useAo && aoMode.orElse(defaultAo); } - public ChunkSectionLayer effectiveChunkLayer(@Nullable ChunkSectionLayer quadLayer) { - return quadLayer == null ? defaultLayer : quadLayer; + public ChunkSectionLayer effectiveChunkLayer(ChunkSectionLayer quadLayer) { + return forceOpaque ? ChunkSectionLayer.SOLID : quadLayer; } public boolean shouldDrawSide(@Nullable Direction side) { diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java index 21c51fefc5..ba4a11a56e 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java @@ -21,14 +21,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.MatrixUtil; -import org.jspecify.annotations.Nullable; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.chunk.ChunkSectionLayer; -import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.item.ItemStackRenderState; import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.util.ARGB; @@ -36,10 +32,8 @@ import net.minecraft.world.item.ItemDisplayContext; import net.fabricmc.fabric.api.client.renderer.v1.mesh.MeshView; -import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadAtlas; import net.fabricmc.fabric.api.client.renderer.v1.mesh.QuadEmitter; import net.fabricmc.fabric.api.client.renderer.v1.render.FabricLayerRenderState; -import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl; import net.fabricmc.fabric.mixin.client.indigo.renderer.ItemRendererAccessor; @@ -55,16 +49,13 @@ public class ItemRenderContext extends AbstractRenderContext { private int light; private int[] tints; - private RenderType defaultRenderType; - @Nullable - private ItemRenderTypeGetter renderTypeGetter; private ItemStackRenderState.FoilType defaultFoilType; private boolean ignoreQuadFoilType; private boolean translucent; - private PoseStack.Pose specialFoilPose; + private PoseStack.Pose foilDecalPose; // TODO: reuse this between submits - private final VertexConsumer[] vertexConsumerCache = new VertexConsumer[3 * FOIL_TYPE_COUNT]; + private final VertexConsumer[] vertexConsumerCache = new VertexConsumer[4 * FOIL_TYPE_COUNT]; public void renderItem( ItemDisplayContext displayContext, @@ -75,8 +66,6 @@ public void renderItem( int[] tints, List vanillaQuads, MeshView mesh, - RenderType renderType, - @Nullable ItemRenderTypeGetter renderTypeGetter, ItemStackRenderState.FoilType foilType, boolean ignoreQuadFoilType, boolean translucent @@ -88,8 +77,6 @@ public void renderItem( this.overlay = overlay; this.tints = tints; - defaultRenderType = renderType; - this.renderTypeGetter = renderTypeGetter; defaultFoilType = foilType; this.ignoreQuadFoilType = ignoreQuadFoilType; this.translucent = translucent; @@ -100,19 +87,15 @@ public void renderItem( this.bufferSource = null; this.tints = null; - defaultRenderType = null; - this.renderTypeGetter = null; - - specialFoilPose = null; + foilDecalPose = null; Arrays.fill(vertexConsumerCache, null); } private void bufferQuads(List vanillaQuads, MeshView mesh) { QuadEmitter emitter = getEmitter(); - final int vanillaQuadCount = vanillaQuads.size(); - - for (int i = 0; i < vanillaQuadCount; i++) { + //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < vanillaQuads.size(); i++) { final BakedQuad q = vanillaQuads.get(i); emitter.fromBakedQuad(q); emitter.emit(); @@ -123,16 +106,30 @@ private void bufferQuads(List vanillaQuads, MeshView mesh) { @Override protected void bufferQuad(MutableQuadViewImpl quad) { - final RenderType renderType = getRenderType(quad.atlas(), quad.chunkLayer()); + final RenderType renderType = quad.itemRenderType(); if (renderType.hasBlending() != translucent) { return; } - final VertexConsumer vertexConsumer = getVertexConsumer(renderType, quad.foilType()); - tintQuad(quad); shadeQuad(quad, quad.emissive()); + + final ItemStackRenderState.FoilType quadFoilType = quad.foilType(); + ItemStackRenderState.FoilType foilType; + + if (ignoreQuadFoilType || quadFoilType == null) { + foilType = defaultFoilType; + } else { + foilType = quadFoilType; + } + + if (foilType != ItemStackRenderState.FoilType.NONE) { + final VertexConsumer foilBuffer = getVertexConsumer(renderType, quad.foilType()); + bufferQuad(quad, foilBuffer); + } + + final VertexConsumer vertexConsumer = getVertexConsumer(renderType, ItemStackRenderState.FoilType.NONE); bufferQuad(quad, vertexConsumer); } @@ -162,39 +159,17 @@ private void shadeQuad(MutableQuadViewImpl quad, boolean emissive) { } } - private RenderType getRenderType(QuadAtlas quadAtlas, @Nullable ChunkSectionLayer quadLayer) { - RenderType renderType; - - if (renderTypeGetter != null) { - renderType = renderTypeGetter.renderType(quadAtlas, quadLayer); - - if (renderType == null) { - renderType = defaultRenderType; - } - } else { - renderType = defaultRenderType; - } - - return renderType; - } - - private VertexConsumer getVertexConsumer(RenderType renderType, ItemStackRenderState.@Nullable FoilType quadFoilType) { - ItemStackRenderState.FoilType foilType; - - if (ignoreQuadFoilType || quadFoilType == null) { - foilType = defaultFoilType; - } else { - foilType = quadFoilType; - } - + private VertexConsumer getVertexConsumer(RenderType renderType, ItemStackRenderState.FoilType foilType) { int cacheIndex; - if (renderType == Sheets.translucentItemSheet()) { + if (renderType == Sheets.cutoutItemSheet()) { cacheIndex = 0; - } else if (renderType == Sheets.cutoutBlockSheet()) { + } else if (renderType == Sheets.translucentItemSheet()) { cacheIndex = FOIL_TYPE_COUNT; - } else if (renderType == Sheets.translucentBlockItemSheet()) { + } else if (renderType == Sheets.cutoutBlockItemSheet()) { cacheIndex = 2 * FOIL_TYPE_COUNT; + } else if (renderType == Sheets.translucentBlockItemSheet()) { + cacheIndex = 3 * FOIL_TYPE_COUNT; } else { return createVertexConsumer(renderType, foilType); } @@ -211,26 +186,14 @@ private VertexConsumer getVertexConsumer(RenderType renderType, ItemStackRenderS } private VertexConsumer createVertexConsumer(RenderType renderType, ItemStackRenderState.FoilType foilType) { - if (foilType == ItemStackRenderState.FoilType.SPECIAL) { - if (specialFoilPose == null) { - specialFoilPose = pose.copy(); - - if (displayContext == ItemDisplayContext.GUI) { - MatrixUtil.mulComponentWise(specialFoilPose.pose(), 0.5F); - } else if (displayContext.firstPerson()) { - MatrixUtil.mulComponentWise(specialFoilPose.pose(), 0.75F); - } + if (foilType != ItemStackRenderState.FoilType.NONE) { + if (foilType == ItemStackRenderState.FoilType.SPECIAL && foilDecalPose == null) { + foilDecalPose = ItemRendererAccessor.fabric_computeFoilDecalPose(displayContext, pose); } - return ItemRendererAccessor.fabric_getSpecialFoilBuffer( - bufferSource, - renderType, - specialFoilPose - ); + return ItemRendererAccessor.fabric_getFoilBuffer(bufferSource, renderType, foilDecalPose); } - return ItemRenderer.getFoilBuffer( - bufferSource, - renderType, true, foilType != ItemStackRenderState.FoilType.NONE); + return bufferSource.getBuffer(renderType); } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/MeshItemSubmit.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/MeshItemSubmit.java index a356d22e1d..703782eab8 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/MeshItemSubmit.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/MeshItemSubmit.java @@ -19,15 +19,12 @@ import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; -import org.jspecify.annotations.Nullable; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.world.item.ItemDisplayContext; import net.fabricmc.fabric.api.client.renderer.v1.mesh.MeshView; -import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter; public record MeshItemSubmit( PoseStack.Pose pose, @@ -37,9 +34,7 @@ public record MeshItemSubmit( int outlineColor, int[] tintLayers, List quads, - RenderType renderType, ItemStackRenderState.FoilType foilType, - MeshView mesh, - @Nullable ItemRenderTypeGetter renderTypeGetter + MeshView mesh ) { } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/SimpleBlockRenderContext.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/SimpleBlockRenderContext.java index 4df19dc27d..0e47481242 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/SimpleBlockRenderContext.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/SimpleBlockRenderContext.java @@ -28,7 +28,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.util.ARGB; import net.minecraft.util.LightCoordsUtil; -import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; @@ -45,10 +44,8 @@ public class SimpleBlockRenderContext extends AbstractRenderContext { private BlockMultiBufferSource bufferSource; @Nullable private Predicate layerFilter; - private ChunkSectionLayer defaultChunkLayer; - private float red; - private float green; - private float blue; + private boolean forceOpaque; + private int tintColor; private int light; @Nullable @@ -58,8 +55,7 @@ public class SimpleBlockRenderContext extends AbstractRenderContext { @Override protected void bufferQuad(MutableQuadViewImpl quad) { - final ChunkSectionLayer quadLayer = quad.chunkLayer(); - final ChunkSectionLayer layer = quadLayer == null ? defaultChunkLayer : quadLayer; + final ChunkSectionLayer layer = forceOpaque ? ChunkSectionLayer.SOLID : quad.chunkLayer(); if (layerFilter != null && !layerFilter.test(layer)) { return; @@ -81,12 +77,10 @@ protected void bufferQuad(MutableQuadViewImpl quad) { private void tintQuad(MutableQuadViewImpl quad) { if (quad.tintIndex() != -1) { - final float red = this.red; - final float green = this.green; - final float blue = this.blue; + int tint = 0xFF000000 | this.tintColor; for (int i = 0; i < 4; i++) { - quad.color(i, ARGB.scaleRGB(quad.color(i), red, green, blue)); + quad.color(i, ARGB.multiply(quad.color(i), tint)); } } } @@ -105,16 +99,14 @@ private void shadeQuad(MutableQuadViewImpl quad, boolean emissive) { } } - public void bufferModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, @Nullable Predicate layerFilter, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { + public void bufferModel(PoseStack.Pose pose, BlockMultiBufferSource bufferSource, @Nullable Predicate layerFilter, BlockStateModel model, int tintColor, int light, int overlay, BlockAndTintGetter level, BlockPos pos, BlockState state) { this.pose = pose; this.overlay = overlay; this.bufferSource = bufferSource; this.layerFilter = layerFilter; - this.defaultChunkLayer = ItemBlockRenderTypes.getChunkRenderType(state); - this.red = Mth.clamp(red, 0, 1); - this.green = Mth.clamp(green, 0, 1); - this.blue = Mth.clamp(blue, 0, 1); + forceOpaque = ItemBlockRenderTypes.forceOpaque(state); + this.tintColor = tintColor; this.light = light; random.setSeed(42L); diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BlockRenderDispatcherMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BlockRenderDispatcherMixin.java index 45dc68bac1..b118bd04ad 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BlockRenderDispatcherMixin.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BlockRenderDispatcherMixin.java @@ -18,44 +18,35 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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; -import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.EmptyBlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; import net.fabricmc.fabric.api.client.renderer.v1.render.ChunkSectionLayerHelper; import net.fabricmc.fabric.api.client.renderer.v1.render.FabricModelBlockRenderer; @Mixin(BlockRenderDispatcher.class) abstract class BlockRenderDispatcherMixin { - @Shadow - @Final - private ModelBlockRenderer modelRenderer; - - @Inject(method = "renderBreakingTexture(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/BlockAndTintGetter;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;)V", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getBlockModel(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/BlockStateModel;"), cancellable = true) - private void afterGetModel(BlockState blockState, BlockPos blockPos, BlockAndTintGetter level, PoseStack poseStack, VertexConsumer vertexConsumer, CallbackInfo ci, @Local(name = "model") BlockStateModel model) { - modelRenderer.tesselateBlock(level, model, blockState, blockPos, - poseStack, layer -> vertexConsumer, true, blockState.getSeed(blockPos), OverlayTexture.NO_OVERLAY); - ci.cancel(); - } - - @Redirect(method = "renderSingleBlock(Lnet/minecraft/world/level/block/state/BlockState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/ModelBlockRenderer;renderModel(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/client/renderer/block/model/BlockStateModel;FFFII)V")) - private void renderProxy(PoseStack.Pose pose, VertexConsumer vertexConsumer, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockState state, PoseStack poseStack, MultiBufferSource bufferSource, int light1, int overlay1) { - FabricModelBlockRenderer.renderModel(pose, ChunkSectionLayerHelper.entityDelegate( - bufferSource), model, red, green, blue, light, overlay, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, state); + @Redirect(method = "renderSingleBlock(Lnet/minecraft/world/level/block/state/BlockState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/ModelBlockRenderer;renderModel(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lnet/minecraft/client/renderer/block/BakedQuadOutput;Lnet/minecraft/client/renderer/block/model/BlockStateModel;III)V")) + private void renderProxy( + PoseStack.Pose pose, + BakedQuadOutput output, + BlockStateModel model, + int tint, + int light, + int overlay, + @Local(name = "bufferSource") MultiBufferSource bufferSource + ) { + FabricModelBlockRenderer.renderModel(pose, + ChunkSectionLayerHelper.entityDelegate(bufferSource), model, + tint, light, overlay, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, Blocks.AIR.defaultBlockState()); } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemFeatureRendererMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemFeatureRendererMixin.java index d4203d5f81..97f6ed3c71 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemFeatureRendererMixin.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemFeatureRendererMixin.java @@ -59,8 +59,6 @@ private void onReturnRenderSolid(SubmitNodeCollection nodeCollection, MultiBuffe submit.tintLayers(), submit.quads(), submit.mesh(), - submit.renderType(), - submit.renderTypeGetter(), submit.foilType(), false, false @@ -77,8 +75,6 @@ private void onReturnRenderSolid(SubmitNodeCollection nodeCollection, MultiBuffe submit.tintLayers(), submit.quads(), submit.mesh(), - submit.renderType(), - submit.renderTypeGetter(), ItemStackRenderState.FoilType.NONE, true, false @@ -104,8 +100,6 @@ private void onReturnRenderTranslucent(SubmitNodeCollection nodeCollection, Mult submit.tintLayers(), submit.quads(), submit.mesh(), - submit.renderType(), - submit.renderTypeGetter(), submit.foilType(), false, true @@ -122,8 +116,6 @@ private void onReturnRenderTranslucent(SubmitNodeCollection nodeCollection, Mult submit.tintLayers(), submit.quads(), submit.mesh(), - submit.renderType(), - submit.renderTypeGetter(), ItemStackRenderState.FoilType.NONE, true, true diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererAccessor.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererAccessor.java index 5437cf6666..49663203cc 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererAccessor.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererAccessor.java @@ -18,17 +18,24 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.rendertype.RenderType; +import net.minecraft.world.item.ItemDisplayContext; @Mixin(ItemRenderer.class) public interface ItemRendererAccessor { - @Invoker("getSpecialFoilBuffer") - static VertexConsumer fabric_getSpecialFoilBuffer(MultiBufferSource bufferSource, RenderType renderType, PoseStack.Pose pose) { + @Invoker("getFoilBuffer") + static VertexConsumer fabric_getFoilBuffer(MultiBufferSource bufferSource, RenderType renderType, PoseStack.@Nullable Pose foilDecalPose) { + throw new AssertionError(); + } + + @Invoker("computeFoilDecalPose") + static PoseStack.Pose fabric_computeFoilDecalPose(ItemDisplayContext type, PoseStack.Pose pose) { throw new AssertionError(); } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemStackRenderStateLayerRenderStateMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemStackRenderStateLayerRenderStateMixin.java index 92d79a9845..692343e716 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemStackRenderStateLayerRenderStateMixin.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemStackRenderStateLayerRenderStateMixin.java @@ -19,7 +19,6 @@ import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; -import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -30,11 +29,9 @@ import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.world.item.ItemDisplayContext; import net.fabricmc.fabric.api.client.renderer.v1.render.FabricLayerRenderState; -import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter; import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessLayerRenderState; import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessOrderedSubmitNodeCollector; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableMeshImpl; @@ -44,24 +41,29 @@ abstract class ItemStackRenderStateLayerRenderStateMixin implements FabricLayerR @Unique private final MutableMeshImpl mutableMesh = new MutableMeshImpl(); - @Unique - @Nullable - private ItemRenderTypeGetter renderTypeGetter = null; - @Inject(method = "clear()V", at = @At("RETURN")) private void onReturnClear(CallbackInfo ci) { mutableMesh.clear(); - renderTypeGetter = null; } - @Redirect(method = "submit", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitItem(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/item/ItemDisplayContext;III[ILjava/util/List;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/item/ItemStackRenderState$FoilType;)V")) - private void submitItemProxy(SubmitNodeCollector submitNodeCollector, PoseStack poseStack, ItemDisplayContext displayContext, int light, int overlay, int outlineColor, int[] tints, List quads, RenderType layer, ItemStackRenderState.FoilType foilType) { + @Redirect(method = "submit", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitItem(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/item/ItemDisplayContext;III[ILjava/util/List;Lnet/minecraft/client/renderer/item/ItemStackRenderState$FoilType;)V")) + private void submitItemProxy( + SubmitNodeCollector submitNodeCollector, + PoseStack poseStack, + ItemDisplayContext displayContext, + int light, + int overlay, + int outlineColor, + int[] tints, + List quads, + ItemStackRenderState.FoilType foilType + ) { if (mutableMesh.size() > 0 && submitNodeCollector instanceof AccessOrderedSubmitNodeCollector access) { - // We don't have to copy the mesh here because vanilla doesn't copy the tint array or quad list either. - access.fabric_submitItem(poseStack, displayContext, light, overlay, outlineColor, tints, quads, layer, - foilType, mutableMesh, renderTypeGetter); + // We don't have to copy the mesh here because vanilla doesn't copy the tintColor array or quad list either. + access.fabric_submitItem(poseStack, displayContext, light, overlay, outlineColor, tints, quads, + foilType, mutableMesh); } else { - submitNodeCollector.submitItem(poseStack, displayContext, light, overlay, outlineColor, tints, quads, layer, + submitNodeCollector.submitItem(poseStack, displayContext, light, overlay, outlineColor, tints, quads, foilType ); } @@ -71,9 +73,4 @@ private void submitItemProxy(SubmitNodeCollector submitNodeCollector, PoseStack public MutableMeshImpl fabric_getMutableMesh() { return mutableMesh; } - - @Override - public void fabric_setRenderTypeGetter(ItemRenderTypeGetter renderTypeGetter) { - this.renderTypeGetter = renderTypeGetter; - } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/LevelRendererMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/LevelRendererMixin.java new file mode 100644 index 0000000000..2f61c23552 --- /dev/null +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/LevelRendererMixin.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.client.indigo.renderer; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.block.BakedQuadOutput; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +@Mixin(LevelRenderer.class) +public abstract class LevelRendererMixin { + @Redirect( + method = "renderBlockDestroyAnimation", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/block/BlockRenderDispatcher;renderBreakingTexture(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/BlockAndTintGetter;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/block/BakedQuadOutput;)V" + ) + ) + private void redirectRenderBlockBreakingTexture( + BlockRenderDispatcher instance, + BlockState state, + BlockPos pos, + BlockAndTintGetter level, + PoseStack poseStack, + BakedQuadOutput output, + @Local(name = "buffer") VertexConsumer buffer + ) { + instance.renderBreakingTexture(state, pos, level, poseStack, buffer); + } +} diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ModelBlockRendererMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ModelBlockRendererMixin.java deleted file mode 100644 index fe643016d9..0000000000 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ModelBlockRendererMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.client.indigo.renderer; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import net.minecraft.client.renderer.block.ModelBlockRenderer; -import net.minecraft.client.renderer.block.model.BlockStateModel; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.EmptyBlockAndTintGetter; -import net.minecraft.world.level.block.Blocks; - -import net.fabricmc.fabric.api.client.renderer.v1.render.FabricModelBlockRenderer; - -@Mixin(ModelBlockRenderer.class) -abstract class ModelBlockRendererMixin { - @Overwrite - public static void renderModel(PoseStack.Pose pose, VertexConsumer vertexConsumer, BlockStateModel model, float red, float green, float blue, int light, int overlay) { - FabricModelBlockRenderer.renderModel(pose, layer -> vertexConsumer, model, red, green, blue, light, overlay, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, Blocks.AIR.defaultBlockState()); - } -} diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeCollectionMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeCollectionMixin.java index 6895cecd5e..58221fbf1c 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeCollectionMixin.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeCollectionMixin.java @@ -20,7 +20,6 @@ import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; -import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -32,11 +31,9 @@ import net.minecraft.client.renderer.SubmitNodeCollection; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.world.item.ItemDisplayContext; import net.fabricmc.fabric.api.client.renderer.v1.mesh.MeshView; -import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter; import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessOrderedSubmitNodeCollector; import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessSubmitNodeCollection; import net.fabricmc.fabric.impl.client.indigo.renderer.render.MeshItemSubmit; @@ -63,10 +60,8 @@ public void fabric_submitItem( int outlineColors, int[] tintLayers, List quads, - RenderType renderType, ItemStackRenderState.FoilType foilType, - MeshView mesh, - @Nullable ItemRenderTypeGetter renderTypeGetter + MeshView mesh ) { wasUsed = true; meshItemSubmits.add(new MeshItemSubmit( @@ -77,10 +72,8 @@ public void fabric_submitItem( outlineColors, tintLayers, quads, - renderType, foilType, - mesh, - renderTypeGetter + mesh )); } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeStorageMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeStorageMixin.java index a75d9101fc..2d08b3f0c8 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeStorageMixin.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SubmitNodeStorageMixin.java @@ -26,11 +26,9 @@ import net.minecraft.client.renderer.SubmitNodeStorage; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.world.item.ItemDisplayContext; import net.fabricmc.fabric.api.client.renderer.v1.mesh.MeshView; -import net.fabricmc.fabric.api.client.renderer.v1.render.ItemRenderTypeGetter; import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessOrderedSubmitNodeCollector; @Mixin(SubmitNodeStorage.class) @@ -44,20 +42,16 @@ public void fabric_submitItem( int outlineColors, int[] tintLayers, List quads, - RenderType renderType, ItemStackRenderState.FoilType foilType, - MeshView mesh, - ItemRenderTypeGetter renderTypeGetter + MeshView mesh ) { OrderedSubmitNodeCollector nodeCollector = order(0); if (nodeCollector instanceof AccessOrderedSubmitNodeCollector access) { access.fabric_submitItem(poseStack, displayContext, light, overlay, outlineColors, tintLayers, quads, - renderType, - foilType, mesh, renderTypeGetter); + foilType, mesh); } else { nodeCollector.submitItem(poseStack, displayContext, light, overlay, outlineColors, tintLayers, quads, - renderType, foilType ); } diff --git a/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json b/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json index 9c8485c1b8..081e9f5668 100644 --- a/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json +++ b/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json @@ -4,22 +4,25 @@ "compatibilityLevel": "JAVA_25", "plugin": "net.fabricmc.fabric.impl.client.indigo.IndigoMixinConfigPlugin", "client": [ - "SubmitNodeCollectionMixin", - "ModelBlockRendererMixin", "BlockRenderDispatcherAccessor", "BlockRenderDispatcherMixin", - "RenderSectionRegionMixin", "ItemFeatureRendererMixin", "ItemRendererAccessor", "ItemStackRenderStateLayerRenderStateMixin", "ItemStackRenderStateMixin", + "RenderSectionRegionMixin", + "SectionCompilerMixin", + "SubmitNodeCollectionMixin", "SubmitNodeStorageMixin", - "SectionCompilerMixin" + "LevelRendererMixin" ], "injectors": { "defaultRequire": 1 }, "overwrites": { "requireAnnotations": true + }, + "mixinextras": { + "minVersion": "0.5.0" } } diff --git a/settings.gradle b/settings.gradle index 5b58ec989c..8e249715bc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -49,14 +49,14 @@ include 'fabric-lifecycle-events-v1' include 'fabric-loot-api-v3' include 'fabric-menu-api-v1' include 'fabric-message-api-v1' -//include 'fabric-model-loading-api-v1' +include 'fabric-model-loading-api-v1' include 'fabric-networking-api-v1' include 'fabric-object-builder-api-v1' include 'fabric-particles-v1' include 'fabric-recipe-api-v1' include 'fabric-registry-sync-v0' -//include 'fabric-renderer-api-v1' -//include 'fabric-renderer-indigo' +include 'fabric-renderer-api-v1' +include 'fabric-renderer-indigo' include 'fabric-rendering-fluids-v1' include 'fabric-rendering-v1' include 'fabric-resource-conditions-api-v1'