From e0f941cfe5e55ec388b41648b9f1e9a38b3903a5 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 25 Dec 2024 20:01:05 -0500 Subject: [PATCH] Port faster item rendering to 1.21.4 --- .../ItemStackRenderStateAccessor.java | 14 ++++ .../LayerRenderStateMixin.java | 70 ++++++++++++++++ .../modernfix/render/SimpleItemModelView.java | 84 +++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemStackRenderStateAccessor.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/LayerRenderStateMixin.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemStackRenderStateAccessor.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemStackRenderStateAccessor.java new file mode 100644 index 00000000..554c4100 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemStackRenderStateAccessor.java @@ -0,0 +1,14 @@ +package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; + +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.world.item.ItemDisplayContext; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ItemStackRenderState.class) +@ClientOnlyMixin +public interface ItemStackRenderStateAccessor { + @Accessor + ItemDisplayContext getDisplayContext(); +} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/LayerRenderStateMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/LayerRenderStateMixin.java new file mode 100644 index 00000000..fd289ba9 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/LayerRenderStateMixin.java @@ -0,0 +1,70 @@ +package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; + +import net.minecraft.client.renderer.block.model.ItemTransform; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.SimpleBakedModel; +import net.minecraft.world.item.ItemDisplayContext; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.render.FastItemRenderType; +import org.embeddedt.modernfix.render.RenderState; +import org.embeddedt.modernfix.render.SimpleItemModelView; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin(value = ItemStackRenderState.LayerRenderState.class, priority = 600) +@ClientOnlyMixin +public abstract class LayerRenderStateMixin { + @Shadow @Final private ItemStackRenderState field_55345; + + @Shadow abstract ItemTransform transform(); + + @Unique + private final SimpleItemModelView modelView = new SimpleItemModelView(); + + /** + * If a model + * - is a vanilla item model (SimpleBakedModel), + * - has no custom GUI transforms, and + * - is being rendered in 2D on a GUI + * we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the + * camera). + */ + @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/ItemRenderer;renderItem(Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;II[ILnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/client/renderer/RenderType;Lnet/minecraft/client/renderer/item/ItemStackRenderState$FoilType;)V"), index = 6) + private BakedModel useSimpleWrappedItemModel(BakedModel model) { + var transformType = ((ItemStackRenderStateAccessor)this.field_55345).getDisplayContext(); + // Forge composite models split themselves into a smaller simple model, we need to detect that the parent + // was not simple + // TODO 1.21.4 - I don't think that is needed anymore with the changes to item rendering + /* + if(originalModel != null && originalModel.getClass() != SimpleBakedModel.class) { + return model; + } + */ + + if(!RenderState.IS_RENDERING_LEVEL && model.getClass() == SimpleBakedModel.class && transformType == ItemDisplayContext.GUI) { + FastItemRenderType type; + ItemTransform transform = this.transform(); + if(transform == ItemTransform.NO_TRANSFORM) + type = FastItemRenderType.SIMPLE_ITEM; + else if(model.isGui3d() && isBlockTransforms(transform)) + type = FastItemRenderType.SIMPLE_BLOCK; + else + return model; + modelView.setItem(model); + modelView.setType(type); + return modelView; + } else + return model; + } + + private boolean isBlockTransforms(ItemTransform transform) { + return transform.rotation.x() == 30f + && transform.rotation.y() == 225f + && transform.rotation.z() == 0f; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java b/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java new file mode 100644 index 00000000..61a06b19 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java @@ -0,0 +1,84 @@ +package org.embeddedt.modernfix.render; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Wrapper class that presents a fake view of item models (only showing the simple front-facing quads), rather + * than every quad. + */ +public class SimpleItemModelView implements BakedModel { + private BakedModel wrappedItem; + private FastItemRenderType type; + + public void setItem(BakedModel model) { + this.wrappedItem = model; + } + + public void setType(FastItemRenderType type) { + this.type = type; + } + + private boolean isCorrectDirectionForType(Direction direction) { + if(type == FastItemRenderType.SIMPLE_ITEM) + return direction == Direction.SOUTH; + else { + return direction == Direction.UP || direction == Direction.EAST || direction == Direction.NORTH; + } + } + + private final List nullQuadList = new ObjectArrayList<>(); + + @Override + public List getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand) { + boolean isWholeListValid = isCorrectDirectionForType(side); + List realList = wrappedItem.getQuads(state, side, rand); + if (isWholeListValid) { + return realList; + } + nullQuadList.clear(); + //noinspection ForLoopReplaceableByForEach + for(int i = 0; i < realList.size(); i++) { + BakedQuad quad = realList.get(i); + if(isCorrectDirectionForType(quad.getDirection())) { + nullQuadList.add(quad); + } + } + return nullQuadList; + } + + @Override + public boolean useAmbientOcclusion() { + return wrappedItem.useAmbientOcclusion(); + } + + @Override + public boolean isGui3d() { + return wrappedItem.isGui3d(); + } + + @Override + public boolean usesBlockLight() { + return wrappedItem.usesBlockLight(); + } + + @Override + public TextureAtlasSprite getParticleIcon() { + return wrappedItem.getParticleIcon(); + } + + @Override + public ItemTransforms getTransforms() { + return wrappedItem.getTransforms(); + } +} +