Simplify item rendering optimization

Now uses a wrapped item model instead of actually modifying
the rendering code, to avoid disabling Sodium's optimization
This commit is contained in:
embeddedt 2023-06-01 21:11:54 -04:00
parent c8bce3e015
commit 39e1ac0896
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
2 changed files with 106 additions and 60 deletions

View File

@ -2,55 +2,33 @@ package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemTransform; import net.minecraft.client.renderer.block.model.ItemTransform;
import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.SimpleBakedModel; import net.minecraft.client.resources.model.SimpleBakedModel;
import net.minecraft.core.Direction;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.embeddedt.modernfix.render.FastItemRenderType; import org.embeddedt.modernfix.render.FastItemRenderType;
import org.embeddedt.modernfix.render.RenderState; import org.embeddedt.modernfix.render.RenderState;
import org.spongepowered.asm.mixin.Final; import org.embeddedt.modernfix.render.SimpleItemModelView;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List; @Mixin(value = ItemRenderer.class, priority = 600)
import java.util.Random;
@Mixin(ItemRenderer.class)
public abstract class ItemRendererMixin { public abstract class ItemRendererMixin {
@Shadow @Final private ItemColors itemColors;
private final Random dummyRandom = new Random();
private static final float[] COLOR_MULTIPLIER = new float[]{1.0F, 1.0F, 1.0F, 1.0F};
private ItemTransforms.TransformType transformType; private ItemTransforms.TransformType transformType;
private final SimpleItemModelView modelView = new SimpleItemModelView();
@Inject(method = "render", at = @At("HEAD")) @Inject(method = "render", at = @At("HEAD"))
private void markRenderingType(ItemStack itemStack, ItemTransforms.TransformType transformType, boolean leftHand, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model, CallbackInfo ci) { private void markRenderingType(ItemStack itemStack, ItemTransforms.TransformType transformType, boolean leftHand, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model, CallbackInfo ci) {
this.transformType = transformType; this.transformType = transformType;
} }
private static final Direction[] ITEM_DIRECTIONS = new Direction[] { Direction.SOUTH };
private static final Direction[] BLOCK_DIRECTIONS = new Direction[] { Direction.UP, Direction.EAST, Direction.NORTH };
private boolean isCorrectDirectionForType(FastItemRenderType type, Direction direction) {
if(type == FastItemRenderType.SIMPLE_ITEM)
return direction == Direction.SOUTH;
else {
return direction == Direction.UP || direction == Direction.EAST || direction == Direction.NORTH;
}
}
/** /**
* If a model * If a model
* - is a vanilla item model (SimpleBakedModel), * - is a vanilla item model (SimpleBakedModel),
@ -59,8 +37,8 @@ public abstract class ItemRendererMixin {
* we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the * we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the
* camera). * camera).
*/ */
@Inject(method = "renderModelLists", at = @At("HEAD"), cancellable = true) @ModifyVariable(method = "renderModelLists", at = @At("HEAD"), index = 1, argsOnly = true)
private void fasterItemRender(BakedModel model, ItemStack stack, int combinedLight, int combinedOverlay, PoseStack matrixStack, VertexConsumer buffer, CallbackInfo ci) { private BakedModel useSimpleWrappedItemModel(BakedModel model, BakedModel arg, ItemStack stack, int combinedLight, int combinedOverlay, PoseStack matrixStack, VertexConsumer buffer) {
if(!RenderState.IS_RENDERING_LEVEL && !stack.isEmpty() && model.getClass() == SimpleBakedModel.class && transformType == ItemTransforms.TransformType.GUI) { if(!RenderState.IS_RENDERING_LEVEL && !stack.isEmpty() && model.getClass() == SimpleBakedModel.class && transformType == ItemTransforms.TransformType.GUI) {
FastItemRenderType type; FastItemRenderType type;
ItemTransform transform = model.getTransforms().gui; ItemTransform transform = model.getTransforms().gui;
@ -69,26 +47,12 @@ public abstract class ItemRendererMixin {
else if(stack.getItem() instanceof BlockItem && isBlockTransforms(transform)) else if(stack.getItem() instanceof BlockItem && isBlockTransforms(transform))
type = FastItemRenderType.SIMPLE_BLOCK; type = FastItemRenderType.SIMPLE_BLOCK;
else else
return; return model;
ci.cancel(); modelView.setItem(model);
PoseStack.Pose pose = matrixStack.last(); modelView.setType(type);
int[] combinedLights = new int[] {combinedLight, combinedLight, combinedLight, combinedLight}; return modelView;
Direction[] directions = type == FastItemRenderType.SIMPLE_ITEM ? ITEM_DIRECTIONS : BLOCK_DIRECTIONS; } else
for(Direction direction : directions) { return model;
List<BakedQuad> culledFaces = model.getQuads(null, direction, dummyRandom);
/* check size to avoid instantiating iterator when the list is empty */
if(culledFaces.size() > 0) {
for(BakedQuad quad : culledFaces) {
render2dItemFace(quad, stack, buffer, pose, combinedLights, combinedOverlay);
}
}
}
List<BakedQuad> unculledFaces = model.getQuads(null, null, dummyRandom);
for(BakedQuad quad : unculledFaces) {
if(isCorrectDirectionForType(type, quad.getDirection()))
render2dItemFace(quad, stack, buffer, pose, combinedLights, combinedOverlay);
}
}
} }
private boolean isBlockTransforms(ItemTransform transform) { private boolean isBlockTransforms(ItemTransform transform) {
@ -96,16 +60,4 @@ public abstract class ItemRendererMixin {
&& transform.rotation.y() == 225f && transform.rotation.y() == 225f
&& transform.rotation.z() == 0f; && transform.rotation.z() == 0f;
} }
private void render2dItemFace(BakedQuad quad, ItemStack stack, VertexConsumer buffer, PoseStack.Pose pose, int[] combinedLights, int combinedOverlay) {
int i = -1;
if (quad.isTinted()) {
i = this.itemColors.getColor(stack, quad.getTintIndex());
}
float f = (float)(i >> 16 & 255) / 255.0F;
float f1 = (float)(i >> 8 & 255) / 255.0F;
float f2 = (float)(i & 255) / 255.0F;
buffer.putBulkData(pose, quad, COLOR_MULTIPLIER, f, f1, f2, combinedLights, combinedOverlay, true);
}
} }

View File

@ -0,0 +1,94 @@
package org.embeddedt.modernfix.render;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemOverrides;
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.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Random;
/**
* 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<BakedQuad> nullQuadList = new ObjectArrayList<>();
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
if(side != null) {
return isCorrectDirectionForType(side) ? wrappedItem.getQuads(state, side, rand) : ImmutableList.of();
} else {
nullQuadList.clear();
List<BakedQuad> realList = wrappedItem.getQuads(state, null, rand);
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 boolean isCustomRenderer() {
return wrappedItem.isCustomRenderer();
}
@Override
public TextureAtlasSprite getParticleIcon() {
return wrappedItem.getParticleIcon();
}
@Override
public ItemTransforms getTransforms() {
return wrappedItem.getTransforms();
}
@Override
public ItemOverrides getOverrides() {
return wrappedItem.getOverrides();
}
}