diff --git a/build.gradle b/build.gradle index 8d6c8a68d..6983eddd9 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id 'idea' id 'maven-publish' id 'fabric-loom' version '0.2.5-SNAPSHOT' apply false - id 'net.minecrell.licenser' version '0.4.1' + id 'net.minecrell.licenser' version '0.4.1' id "org.ajoberstar.grgit" version "3.1.1" id 'com.matthewprenger.cursegradle' version "1.1.2" } @@ -183,7 +183,7 @@ publishing { depNode.appendNode("scope", "compile") } } - } + } } repositories { diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java index 2295ee3a5..002d7721f 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ItemRenderContext.java @@ -17,21 +17,30 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render; import java.util.List; +import java.util.Objects; import java.util.Random; import java.util.function.Consumer; import java.util.function.Supplier; +import net.minecraft.class_4722; import net.minecraft.block.BlockState; import net.minecraft.client.color.item.ItemColors; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderLayers; import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.render.model.json.ModelTransformation; +import net.minecraft.client.render.model.json.ModelTransformation.Type; import net.minecraft.client.util.math.Matrix4f; -import net.minecraft.client.util.math.Vector3f; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.util.math.Vector3f; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Direction; +import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; @@ -62,45 +71,69 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo private final ItemColors colorMap; private final Random random = new Random(); private final Consumer<BakedModel> fallbackConsumer; - VertexConsumer bufferBuilder; - MatrixStack matrixStack; - Matrix4f matrix; + private final Vector3f normalVec = new Vector3f(); + + private MatrixStack matrixStack; + private Matrix4f matrix; + private VertexConsumerProvider vertexConsumerProvider; + private VertexConsumer modelVertexConsumer; + private BlendMode quadBlendMode; + private VertexConsumer quadVertexConsumer; + private Type transformType; private int lightmap; private int overlay; private ItemStack itemStack; private VanillaQuadHandler vanillaHandler; - protected final Vector3f normalVec = new Vector3f(); private final Supplier<Random> randomSupplier = () -> { - Random result = random; + final Random result = random; result.setSeed(ITEM_RANDOM_SEED); return random; }; - private final int[] quadData = new int[EncodingFormat.TOTAL_STRIDE];; + private final int[] quadData = new int[EncodingFormat.TOTAL_STRIDE]; public ItemRenderContext(ItemColors colorMap) { this.colorMap = colorMap; - this.fallbackConsumer = this::fallbackConsumer; + fallbackConsumer = this::fallbackConsumer; } - public void renderModel(FabricBakedModel model, ItemStack stack, int lightmap, int overlay, MatrixStack matrixStack, VertexConsumer buffer, VanillaQuadHandler vanillaHandler) { + public void renderModel(ItemStack itemStack, Type transformType, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int lightmap, int overlay, FabricBakedModel model, VanillaQuadHandler vanillaHandler) { this.lightmap = lightmap; this.overlay = overlay; - this.itemStack = stack; - this.bufferBuilder = buffer; + this.itemStack = itemStack; + this.vertexConsumerProvider = vertexConsumerProvider; this.matrixStack = matrixStack; - this.matrix = matrixStack.peek().getModel(); - this.normalMatrix = matrixStack.peek().getNormal(); - this.overlay = overlay; - + this.transformType = transformType; this.vanillaHandler = vanillaHandler; - model.emitItemQuads(stack, randomSupplier, this); + quadBlendMode = BlendMode.DEFAULT; + modelVertexConsumer = selectVertexConsumer(RenderLayers.getItemLayer(itemStack)); + + matrixStack.push(); + ((BakedModel) model).getTransformation().getTransformation(transformType).method_23075(invert, matrixStack); + matrixStack.translate(-0.5D, -0.5D, -0.5D); + matrix = matrixStack.peek().getModel(); + normalMatrix = matrixStack.peek().getNormal(); + + model.emitItemQuads(itemStack, randomSupplier, this); + + matrixStack.pop(); - this.bufferBuilder = null; this.matrixStack = null; this.itemStack = null; this.vanillaHandler = null; + modelVertexConsumer = null; + } + + /** + * Use non-culling translucent material in GUI to match vanilla behavior. If the item + * is enchanted then also select a dual-output vertex consumer. For models with layered + * coplanar polygons this means we will render the glint more than once. Indigo doesn't + * support sprite layers, so this can't be helped in this implementation. + */ + private VertexConsumer selectVertexConsumer(RenderLayer layerIn) { + final RenderLayer layer = transformType == ModelTransformation.Type.GUI && Objects.equals(layerIn, class_4722.method_24075()) ? class_4722.method_24076() : layerIn; + return ItemRenderer.getArmorVertexConsumer(vertexConsumerProvider, layer, true, itemStack.hasEnchantmentGlint()); } private class Maker extends MutableQuadViewImpl implements QuadEmitter { @@ -122,7 +155,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo private final Maker editorQuad = new Maker(); private final Consumer<Mesh> meshConsumer = (mesh) -> { - MeshImpl m = (MeshImpl) mesh; + final MeshImpl m = (MeshImpl) mesh; final int[] data = m.data(); final int limit = data.length; int index = 0; @@ -147,7 +180,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo return; } - RenderMaterialImpl.Value mat = quad.material(); + final RenderMaterialImpl.Value mat = quad.material(); final int quadColor = mat.disableColorIndex(0) ? -1 : indexColor(); final int lightmap = mat.emissive(0) ? AbstractQuadRenderer.FULL_BRIGHTNESS : this.lightmap; @@ -158,7 +191,34 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), lightmap)); } - AbstractQuadRenderer.bufferQuad(bufferBuilder, quad, matrix, overlay, normalMatrix, normalVec); + AbstractQuadRenderer.bufferQuad(quadVertexConsumer(mat.blendMode(0)), quad, matrix, overlay, normalMatrix, normalVec); + } + + /** + * Caches custom blend mode / vertex consumers and mimics the logic + * in {@code RenderLayers.getEntityBlockLayer}. Layers other than + * translucent are mapped to cutout. + */ + private VertexConsumer quadVertexConsumer(BlendMode blendMode) { + if (blendMode == BlendMode.DEFAULT) { + return modelVertexConsumer; + } + + if (blendMode != BlendMode.TRANSLUCENT) { + blendMode = BlendMode.CUTOUT; + } + + if (blendMode == quadBlendMode) { + return quadVertexConsumer; + } else if (blendMode == BlendMode.TRANSLUCENT) { + quadVertexConsumer = selectVertexConsumer(class_4722.method_24075()); + quadBlendMode = BlendMode.TRANSLUCENT; + } else { + quadVertexConsumer = selectVertexConsumer(class_4722.method_24074()); + quadBlendMode = BlendMode.CUTOUT; + } + + return quadVertexConsumer; } @Override @@ -172,23 +232,23 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { random.setSeed(ITEM_RANDOM_SEED); final Direction cullFace = ModelHelper.faceFromIndex(i); - renderFallbackWithTransform(bufferBuilder, model.getQuads((BlockState) null, cullFace, random), lightmap, itemStack, cullFace); + renderFallbackWithTransform(model.getQuads((BlockState) null, cullFace, random), cullFace); } } else { for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { - vanillaHandler.accept(model, itemStack, lightmap, overlay, matrixStack, bufferBuilder); + vanillaHandler.accept(model, itemStack, lightmap, overlay, matrixStack, modelVertexConsumer); } } - }; + } - private void renderFallbackWithTransform(VertexConsumer bufferBuilder, List<BakedQuad> quads, int color, ItemStack stack, Direction cullFace) { + private void renderFallbackWithTransform(List<BakedQuad> quads, Direction cullFace) { if (quads.isEmpty()) { return; } - Maker editorQuad = this.editorQuad; + final Maker editorQuad = this.editorQuad; - for (BakedQuad q : quads) { + for (final BakedQuad q : quads) { editorQuad.clear(); editorQuad.fromVanilla(q.getVertexData(), 0, false); editorQuad.cullFace(cullFace); diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinItemRenderer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinItemRenderer.java index 3b3a5639b..b384e647d 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinItemRenderer.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinItemRenderer.java @@ -24,8 +24,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.color.item.ItemColors; import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; @@ -36,7 +38,7 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.ItemRenderContext. @Mixin(ItemRenderer.class) public abstract class MixinItemRenderer { @Shadow - protected abstract void method_23182(BakedModel model, ItemStack stack, int color, int overlay, MatrixStack matrixStack, VertexConsumer buffer); + protected abstract void method_23182(BakedModel model, ItemStack stack, int light, int overlay, MatrixStack matrixStack, VertexConsumer buffer); @Shadow protected ItemColors colorMap; @@ -45,12 +47,12 @@ public abstract class MixinItemRenderer { private final ThreadLocal<ItemRenderContext> CONTEXTS = ThreadLocal.withInitial(() -> new ItemRenderContext(colorMap)); - @Inject(at = @At("HEAD"), method = "method_23182", cancellable = true) - private void hook_method_23182(BakedModel model, ItemStack stack, int lightmap, int overlay, MatrixStack matrixStack, VertexConsumer buffer, CallbackInfo ci) { + @Inject(at = @At("HEAD"), method = "method_23179", cancellable = true) + public void hook_method_23179(ItemStack stack, ModelTransformation.Type transformType, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, CallbackInfo ci) { final FabricBakedModel fabricModel = (FabricBakedModel) model; - if (!fabricModel.isVanillaAdapter()) { - CONTEXTS.get().renderModel(fabricModel, stack, lightmap, overlay, matrixStack, buffer, vanillaHandler); + if (!(stack.isEmpty() || fabricModel.isVanillaAdapter())) { + CONTEXTS.get().renderModel(stack, transformType, invert, matrixStack, vertexConsumerProvider, light, overlay, fabricModel, vanillaHandler); ci.cancel(); } }