Skip to content

Commit e0f941c

Browse files
committed
Port faster item rendering to 1.21.4
1 parent a5af6e5 commit e0f941c

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering;
2+
3+
import net.minecraft.client.renderer.item.ItemStackRenderState;
4+
import net.minecraft.world.item.ItemDisplayContext;
5+
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.gen.Accessor;
8+
9+
@Mixin(ItemStackRenderState.class)
10+
@ClientOnlyMixin
11+
public interface ItemStackRenderStateAccessor {
12+
@Accessor
13+
ItemDisplayContext getDisplayContext();
14+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering;
2+
3+
import net.minecraft.client.renderer.block.model.ItemTransform;
4+
import net.minecraft.client.renderer.item.ItemStackRenderState;
5+
import net.minecraft.client.resources.model.BakedModel;
6+
import net.minecraft.client.resources.model.SimpleBakedModel;
7+
import net.minecraft.world.item.ItemDisplayContext;
8+
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
9+
import org.embeddedt.modernfix.render.FastItemRenderType;
10+
import org.embeddedt.modernfix.render.RenderState;
11+
import org.embeddedt.modernfix.render.SimpleItemModelView;
12+
import org.spongepowered.asm.mixin.Final;
13+
import org.spongepowered.asm.mixin.Mixin;
14+
import org.spongepowered.asm.mixin.Shadow;
15+
import org.spongepowered.asm.mixin.Unique;
16+
import org.spongepowered.asm.mixin.injection.At;
17+
import org.spongepowered.asm.mixin.injection.ModifyArg;
18+
19+
@Mixin(value = ItemStackRenderState.LayerRenderState.class, priority = 600)
20+
@ClientOnlyMixin
21+
public abstract class LayerRenderStateMixin {
22+
@Shadow @Final private ItemStackRenderState field_55345;
23+
24+
@Shadow abstract ItemTransform transform();
25+
26+
@Unique
27+
private final SimpleItemModelView modelView = new SimpleItemModelView();
28+
29+
/**
30+
* If a model
31+
* - is a vanilla item model (SimpleBakedModel),
32+
* - has no custom GUI transforms, and
33+
* - is being rendered in 2D on a GUI
34+
* we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the
35+
* camera).
36+
*/
37+
@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)
38+
private BakedModel useSimpleWrappedItemModel(BakedModel model) {
39+
var transformType = ((ItemStackRenderStateAccessor)this.field_55345).getDisplayContext();
40+
// Forge composite models split themselves into a smaller simple model, we need to detect that the parent
41+
// was not simple
42+
// TODO 1.21.4 - I don't think that is needed anymore with the changes to item rendering
43+
/*
44+
if(originalModel != null && originalModel.getClass() != SimpleBakedModel.class) {
45+
return model;
46+
}
47+
*/
48+
49+
if(!RenderState.IS_RENDERING_LEVEL && model.getClass() == SimpleBakedModel.class && transformType == ItemDisplayContext.GUI) {
50+
FastItemRenderType type;
51+
ItemTransform transform = this.transform();
52+
if(transform == ItemTransform.NO_TRANSFORM)
53+
type = FastItemRenderType.SIMPLE_ITEM;
54+
else if(model.isGui3d() && isBlockTransforms(transform))
55+
type = FastItemRenderType.SIMPLE_BLOCK;
56+
else
57+
return model;
58+
modelView.setItem(model);
59+
modelView.setType(type);
60+
return modelView;
61+
} else
62+
return model;
63+
}
64+
65+
private boolean isBlockTransforms(ItemTransform transform) {
66+
return transform.rotation.x() == 30f
67+
&& transform.rotation.y() == 225f
68+
&& transform.rotation.z() == 0f;
69+
}
70+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package org.embeddedt.modernfix.render;
2+
3+
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
4+
import net.minecraft.client.renderer.block.model.BakedQuad;
5+
import net.minecraft.client.renderer.block.model.ItemTransforms;
6+
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
7+
import net.minecraft.client.resources.model.BakedModel;
8+
import net.minecraft.core.Direction;
9+
import net.minecraft.util.RandomSource;
10+
import net.minecraft.world.level.block.state.BlockState;
11+
import org.jetbrains.annotations.Nullable;
12+
13+
import java.util.List;
14+
15+
/**
16+
* Wrapper class that presents a fake view of item models (only showing the simple front-facing quads), rather
17+
* than every quad.
18+
*/
19+
public class SimpleItemModelView implements BakedModel {
20+
private BakedModel wrappedItem;
21+
private FastItemRenderType type;
22+
23+
public void setItem(BakedModel model) {
24+
this.wrappedItem = model;
25+
}
26+
27+
public void setType(FastItemRenderType type) {
28+
this.type = type;
29+
}
30+
31+
private boolean isCorrectDirectionForType(Direction direction) {
32+
if(type == FastItemRenderType.SIMPLE_ITEM)
33+
return direction == Direction.SOUTH;
34+
else {
35+
return direction == Direction.UP || direction == Direction.EAST || direction == Direction.NORTH;
36+
}
37+
}
38+
39+
private final List<BakedQuad> nullQuadList = new ObjectArrayList<>();
40+
41+
@Override
42+
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand) {
43+
boolean isWholeListValid = isCorrectDirectionForType(side);
44+
List<BakedQuad> realList = wrappedItem.getQuads(state, side, rand);
45+
if (isWholeListValid) {
46+
return realList;
47+
}
48+
nullQuadList.clear();
49+
//noinspection ForLoopReplaceableByForEach
50+
for(int i = 0; i < realList.size(); i++) {
51+
BakedQuad quad = realList.get(i);
52+
if(isCorrectDirectionForType(quad.getDirection())) {
53+
nullQuadList.add(quad);
54+
}
55+
}
56+
return nullQuadList;
57+
}
58+
59+
@Override
60+
public boolean useAmbientOcclusion() {
61+
return wrappedItem.useAmbientOcclusion();
62+
}
63+
64+
@Override
65+
public boolean isGui3d() {
66+
return wrappedItem.isGui3d();
67+
}
68+
69+
@Override
70+
public boolean usesBlockLight() {
71+
return wrappedItem.usesBlockLight();
72+
}
73+
74+
@Override
75+
public TextureAtlasSprite getParticleIcon() {
76+
return wrappedItem.getParticleIcon();
77+
}
78+
79+
@Override
80+
public ItemTransforms getTransforms() {
81+
return wrappedItem.getTransforms();
82+
}
83+
}
84+

0 commit comments

Comments
 (0)