diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java index 573fd91db9..40b497d729 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java @@ -29,6 +29,7 @@ import net.minecraft.world.BlockRenderView; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; /** * Interface for baked models that output meshes with enhanced rendering features. @@ -92,9 +93,8 @@ default boolean isVanillaAdapter() { * Will not be thread-safe. Do not cache or retain a reference. * @param context Accepts model output. */ - @SuppressWarnings("deprecation") default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { - context.bakedModelConsumer().accept((BakedModel) this, state); + VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, context.getEmitter()); } /** @@ -124,9 +124,7 @@ default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPo * logic here, instead of returning every possible shape from {@link BakedModel#getOverrides} * as vanilla baked models. */ - @SuppressWarnings("deprecation") default void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { - // Pass null state to enforce item quads in block render contexts - context.bakedModelConsumer().accept((BakedModel) this, null); + VanillaModelEncoder.emitItemQuads((BakedModel) this, null, randomSupplier, context); } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderContext.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderContext.java index 41f8eab486..ab5c96b1dc 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderContext.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderContext.java @@ -23,13 +23,16 @@ import net.minecraft.block.BlockState; import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; /** @@ -54,6 +57,15 @@ public interface RenderContext { */ QuadEmitter getEmitter(); + /** + * Returns whether this context currently has at least one transform. + * + * @apiNote The default implementation will be removed in the next breaking release. + */ + default boolean hasTransform() { + return true; + } + /** * Causes all models/quads/meshes sent to this consumer to be transformed by the provided * {@link QuadTransform} that edits each quad before buffering. Quads in the mesh will @@ -67,6 +79,8 @@ public interface RenderContext { * *

Meshes are never mutated by the transformer - only buffered quads. This ensures thread-safe * use of meshes/models across multiple chunk builders. + * + *

Using the {@linkplain #getEmitter() quad emitter of this context} from the inside of a quad transform is not supported. */ void pushTransform(QuadTransform transform); @@ -76,6 +90,36 @@ public interface RenderContext { */ void popTransform(); + /** + * Returns {@code true} if the given face will be culled away. + * + *

This function can be used to skip complex transformations of quads that will be culled anyway. + * The cull face of a quad is determined by {@link QuadView#cullFace()}. + * Note that if {@linkplain #hasTransform() there is a transform}, no computation should be skipped, + * because the cull face might be changed by the transform, + * or the transform might wish to receive culled faces too. + * + *

This function can only be used on a block render context (i.e. in {@link FabricBakedModel#emitBlockQuads}). + * Calling it on another context (e.g. in {@link FabricBakedModel#emitItemQuads}) will throw an exception. + * + * @apiNote The default implementation will be removed in the next breaking release. + */ + default boolean isFaceCulled(@Nullable Direction face) { + return false; + } + + /** + * Returns the current transformation mode. + * + *

This function can only be used on an item render context (i.e. in {@link FabricBakedModel#emitItemQuads}). + * Calling it on another context (e.g. in {@link FabricBakedModel#emitBlockQuads}) will throw an exception. + * + * @apiNote The default implementation will be removed in the next breaking release. + */ + default ModelTransformationMode itemTransformationMode() { + return ModelTransformationMode.NONE; + } + @FunctionalInterface interface QuadTransform { /** @@ -89,14 +133,16 @@ interface QuadTransform { * @deprecated Use {@link Mesh#outputTo(QuadEmitter)} instead. */ @Deprecated - Consumer meshConsumer(); + default Consumer meshConsumer() { + return mesh -> mesh.outputTo(getEmitter()); + } /** * @deprecated Use {@link FabricBakedModel#emitBlockQuads(BlockRenderView, BlockState, BlockPos, Supplier, RenderContext) emitBlockQuads} * or {@link FabricBakedModel#emitItemQuads(ItemStack, Supplier, RenderContext) emitItemQuads} on the baked model * that you want to consume instead. */ - @Deprecated + @Deprecated(forRemoval = true) BakedModelConsumer bakedModelConsumer(); /** @@ -104,12 +150,12 @@ interface QuadTransform { * or {@link FabricBakedModel#emitItemQuads(ItemStack, Supplier, RenderContext) emitItemQuads} on the baked model * that you want to consume instead. */ - @Deprecated + @Deprecated(forRemoval = true) default Consumer fallbackConsumer() { return bakedModelConsumer(); } - @Deprecated + @Deprecated(forRemoval = true) interface BakedModelConsumer extends Consumer { /** * Render a baked model by processing its {@linkplain BakedModel#getQuads} using the rendered block state. diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/VanillaModelEncoder.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/VanillaModelEncoder.java new file mode 100644 index 0000000000..af2a817cac --- /dev/null +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/VanillaModelEncoder.java @@ -0,0 +1,85 @@ +/* + * 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.renderer; + +import java.util.List; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.random.Random; + +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.fabricmc.fabric.api.renderer.v1.RendererAccess; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.util.TriState; + +/** + * Routines for adaptation of vanilla {@link BakedModel}s to FRAPI pipelines. + * Even though Indigo calls them directly, they are not for use by third party renderers, and might change at any time. + */ +public class VanillaModelEncoder { + private static final Renderer RENDERER = RendererAccess.INSTANCE.getRenderer(); + private static final RenderMaterial MATERIAL_STANDARD = RENDERER.materialFinder().find(); + private static final RenderMaterial MATERIAL_NO_AO = RENDERER.materialFinder().ambientOcclusion(TriState.FALSE).find(); + + // Separate QuadEmitter parameter so that Indigo can pass its own emitter that handles vanilla quads differently. + public static void emitBlockQuads(BakedModel model, @Nullable BlockState state, Supplier randomSupplier, RenderContext context, QuadEmitter emitter) { + final RenderMaterial defaultMaterial = model.useAmbientOcclusion() ? MATERIAL_STANDARD : MATERIAL_NO_AO; + + for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { + final Direction cullFace = ModelHelper.faceFromIndex(i); + + if (!context.hasTransform() && context.isFaceCulled(cullFace)) { + // Skip entire quad list if possible. + continue; + } + + final List quads = model.getQuads(state, cullFace, randomSupplier.get()); + final int count = quads.size(); + + for (int j = 0; j < count; j++) { + final BakedQuad q = quads.get(j); + emitter.fromVanilla(q, defaultMaterial, cullFace); + emitter.emit(); + } + } + } + + public static void emitItemQuads(BakedModel model, @Nullable BlockState state, Supplier randomSupplier, RenderContext context) { + QuadEmitter emitter = context.getEmitter(); + + for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { + final Direction cullFace = ModelHelper.faceFromIndex(i); + final List quads = model.getQuads(state, cullFace, randomSupplier.get()); + final int count = quads.size(); + + for (int j = 0; j < count; j++) { + final BakedQuad q = quads.get(j); + emitter.fromVanilla(q, MATERIAL_STANDARD, cullFace); + emitter.emit(); + } + } + } +} diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java index 7d63f22c9f..6f564a6b75 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java @@ -30,6 +30,7 @@ import net.minecraft.client.texture.SpriteAtlasTexture; import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Direction; import net.fabricmc.fabric.api.renderer.v1.Renderer; import net.fabricmc.fabric.api.renderer.v1.RendererAccess; @@ -79,6 +80,7 @@ public BakedModel bake(Baker baker, Function textureGe 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(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -87,6 +89,7 @@ public BakedModel bake(Baker baker, Function textureGe 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(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -95,6 +98,7 @@ public BakedModel bake(Baker baker, Function textureGe 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(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -103,6 +107,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, B, 1, 1); emitter.pos(2, 1, 1, B); emitter.pos(3, 1, 1, A); + emitter.cullFace(Direction.UP); emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -113,6 +118,7 @@ public BakedModel bake(Baker baker, Function textureGe 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(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -121,6 +127,7 @@ public BakedModel bake(Baker baker, Function textureGe 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(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -129,6 +136,7 @@ public BakedModel bake(Baker baker, Function textureGe 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(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -137,6 +145,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, B, 0, 0); emitter.pos(2, 1, 0, A); emitter.pos(3, 1, 0, B); + emitter.cullFace(Direction.DOWN); emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -146,6 +155,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, B, 0, 0); emitter.pos(2, A, 0, 0); emitter.pos(3, A, 1, 0); + emitter.cullFace(Direction.NORTH); emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); @@ -156,7 +166,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, A, 0, 0); emitter.pos(2, 0, 0, A); emitter.pos(3, 0, 1, A); - emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); + cornerSprite(emitter, whiteConcreteSprite); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -166,6 +176,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, 0, 0, A); emitter.pos(2, 0, 0, B); emitter.pos(3, 0, 1, B); + emitter.cullFace(Direction.WEST); emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); @@ -176,7 +187,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, 0, 0, B); emitter.pos(2, A, 0, 1); emitter.pos(3, A, 1, 1); - emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); + cornerSprite(emitter, whiteConcreteSprite); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -186,6 +197,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, A, 0, 1); emitter.pos(2, B, 0, 1); emitter.pos(3, B, 1, 1); + emitter.cullFace(Direction.SOUTH); emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); @@ -196,7 +208,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, B, 0, 1); emitter.pos(2, 1, 0, B); emitter.pos(3, 1, 1, B); - emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); + cornerSprite(emitter, whiteConcreteSprite); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); emitter.emit(); @@ -206,6 +218,7 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, 1, 0, B); emitter.pos(2, 1, 0, A); emitter.pos(3, 1, 1, A); + emitter.cullFace(Direction.EAST); emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); @@ -216,11 +229,21 @@ public BakedModel bake(Baker baker, Function textureGe emitter.pos(1, 1, 0, A); emitter.pos(2, B, 0, 0); emitter.pos(3, B, 1, 0); - emitter.spriteBake(whiteConcreteSprite, MutableQuadView.BAKE_LOCK_UV); + cornerSprite(emitter, whiteConcreteSprite); emitter.material(glintMaterial); emitter.color(-1, -1, -1, -1); emitter.emit(); return new SingleMeshBakedModel(builder.build(), whiteConcreteSprite); } + + private static void cornerSprite(QuadEmitter emitter, Sprite sprite) { + // 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); + // 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); + } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java index 610549e164..38659bb2fd 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java @@ -19,8 +19,6 @@ import static net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper.AXIS_ALIGNED_FLAG; import static net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper.LIGHT_FACE_FLAG; -import java.util.List; - import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; @@ -30,21 +28,20 @@ import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; -import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; import net.fabricmc.fabric.api.util.TriState; import net.fabricmc.fabric.impl.client.indigo.Indigo; -import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer; import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator; import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoConfig; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl; +import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; public abstract class AbstractBlockRenderContext extends AbstractRenderContext { protected final BlockRenderInfo blockInfo = new BlockRenderInfo(); @@ -61,6 +58,17 @@ public void emitDirectly() { renderQuad(this, false); } }; + private final MutableQuadViewImpl vanillaModelEditorQuad = new MutableQuadViewImpl() { + { + data = new int[EncodingFormat.TOTAL_STRIDE]; + clear(); + } + + @Override + public void emitDirectly() { + renderQuad(this, true); + } + }; private final BakedModelConsumerImpl vanillaModelConsumer = new BakedModelConsumerImpl(); @@ -80,6 +88,21 @@ public QuadEmitter getEmitter() { return editorQuad; } + public QuadEmitter getVanillaModelEmitter() { + // Do not clear the editorQuad since it is not accessible to API users. + return vanillaModelEditorQuad; + } + + @Override + public boolean isFaceCulled(@Nullable Direction face) { + return !blockInfo.shouldDrawFace(face); + } + + @Override + public ModelTransformationMode itemTransformationMode() { + throw new IllegalStateException("itemTransformationMode() can only be called on an item render context."); + } + @Override public BakedModelConsumer bakedModelConsumer() { return vanillaModelConsumer; @@ -90,7 +113,7 @@ private void renderQuad(MutableQuadViewImpl quad, boolean isVanilla) { return; } - if (!blockInfo.shouldDrawFace(quad.cullFace())) { + if (isFaceCulled(quad.cullFace())) { return; } @@ -275,21 +298,6 @@ private int flatBrightness(MutableQuadViewImpl quad, BlockState blockState, Bloc * them through vanilla logic would require additional hooks. */ private class BakedModelConsumerImpl implements BakedModelConsumer { - private static final RenderMaterial MATERIAL_SHADED = IndigoRenderer.INSTANCE.materialFinder().find(); - private static final RenderMaterial MATERIAL_FLAT = IndigoRenderer.INSTANCE.materialFinder().ambientOcclusion(TriState.FALSE).find(); - - private final MutableQuadViewImpl editorQuad = new MutableQuadViewImpl() { - { - data = new int[EncodingFormat.TOTAL_STRIDE]; - clear(); - } - - @Override - public void emitDirectly() { - renderQuad(this, true); - } - }; - @Override public void accept(BakedModel model) { accept(model, blockInfo.blockState); @@ -297,23 +305,7 @@ public void accept(BakedModel model) { @Override public void accept(BakedModel model, @Nullable BlockState state) { - MutableQuadViewImpl editorQuad = this.editorQuad; - final RenderMaterial defaultMaterial = model.useAmbientOcclusion() ? MATERIAL_SHADED : MATERIAL_FLAT; - - for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { - final Direction cullFace = ModelHelper.faceFromIndex(i); - final List quads = model.getQuads(state, cullFace, blockInfo.randomSupplier.get()); - final int count = quads.size(); - - for (int j = 0; j < count; j++) { - final BakedQuad q = quads.get(j); - editorQuad.fromVanilla(q, defaultMaterial, cullFace); - // Call renderQuad directly instead of emit for efficiency - renderQuad(editorQuad, true); - } - } - - // Do not clear the editorQuad since it is not accessible to API users. + VanillaModelEncoder.emitBlockQuads(model, state, blockInfo.randomSupplier, AbstractBlockRenderContext.this, vanillaModelEditorQuad); } } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractRenderContext.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractRenderContext.java index 967e6e8673..81969f7a4c 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractRenderContext.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractRenderContext.java @@ -61,7 +61,8 @@ protected final boolean transform(MutableQuadView q) { return activeTransform.transform(q); } - protected boolean hasTransform() { + @Override + public boolean hasTransform() { return activeTransform != NO_TRANSFORM; } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/IndigoQuadHandler.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/IndigoQuadHandler.java deleted file mode 100644 index 9ecc8e4a78..0000000000 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/IndigoQuadHandler.java +++ /dev/null @@ -1,36 +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.impl.client.indigo.renderer.render; - -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; - -public class IndigoQuadHandler implements ItemRenderContext.VanillaQuadHandler { - private final ItemRenderer itemRenderer; - - public IndigoQuadHandler(ItemRenderer itemRenderer) { - this.itemRenderer = itemRenderer; - } - - @Override - public void accept(BakedModel model, ItemStack stack, int color, int overlay, MatrixStack matrixStack, VertexConsumer buffer) { - itemRenderer.renderBakedItemModel(model, stack, color, overlay, matrixStack, buffer); - } -} 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 f42d5c7a41..6badb4ce3e 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 @@ -16,7 +16,6 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render; -import java.util.List; import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; @@ -32,7 +31,6 @@ 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.ModelTransformationMode; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.BlockItem; @@ -44,12 +42,11 @@ import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; -import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; import net.fabricmc.fabric.api.util.TriState; -import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl; +import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; /** * The render context used for item rendering. @@ -84,7 +81,6 @@ public void emitDirectly() { private MatrixStack matrixStack; private VertexConsumerProvider vertexConsumerProvider; private int lightmap; - private VanillaQuadHandler vanillaHandler; private boolean isDefaultTranslucent; private boolean isTranslucentDirect; @@ -94,7 +90,6 @@ public void emitDirectly() { private VertexConsumer cutoutVertexConsumer; private VertexConsumer translucentGlintVertexConsumer; private VertexConsumer cutoutGlintVertexConsumer; - private VertexConsumer defaultVertexConsumer; public ItemRenderContext(ItemColors colorMap) { this.colorMap = colorMap; @@ -106,19 +101,28 @@ public QuadEmitter getEmitter() { return editorQuad; } + @Override + public boolean isFaceCulled(@Nullable Direction face) { + throw new IllegalStateException("isFaceCulled can only be called on a block render context."); + } + + @Override + public ModelTransformationMode itemTransformationMode() { + return transformMode; + } + @Override public BakedModelConsumer bakedModelConsumer() { return vanillaModelConsumer; } - public void renderModel(ItemStack itemStack, ModelTransformationMode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int lightmap, int overlay, BakedModel model, VanillaQuadHandler vanillaHandler) { + public void renderModel(ItemStack itemStack, ModelTransformationMode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int lightmap, int overlay, BakedModel model) { this.itemStack = itemStack; this.transformMode = transformMode; this.matrixStack = matrixStack; this.vertexConsumerProvider = vertexConsumerProvider; this.lightmap = lightmap; this.overlay = overlay; - this.vanillaHandler = vanillaHandler; computeOutputInfo(); matrix = matrixStack.peek().getPositionMatrix(); @@ -129,13 +133,11 @@ public void renderModel(ItemStack itemStack, ModelTransformationMode transformMo this.itemStack = null; this.matrixStack = null; this.vertexConsumerProvider = null; - this.vanillaHandler = null; translucentVertexConsumer = null; cutoutVertexConsumer = null; translucentGlintVertexConsumer = null; cutoutGlintVertexConsumer = null; - defaultVertexConsumer = null; } private void computeOutputInfo() { @@ -158,8 +160,6 @@ private void computeOutputInfo() { } isDefaultGlint = itemStack.hasGlint(); - - defaultVertexConsumer = getVertexConsumer(BlendMode.DEFAULT, TriState.DEFAULT); } private void renderQuad(MutableQuadViewImpl quad) { @@ -275,34 +275,7 @@ public void accept(BakedModel model) { @Override public void accept(BakedModel model, @Nullable BlockState state) { - if (hasTransform()) { - MutableQuadViewImpl editorQuad = ItemRenderContext.this.editorQuad; - - // if there's a transform in effect, convert to mesh-based quads so that we can apply it - for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { - final Direction cullFace = ModelHelper.faceFromIndex(i); - random.setSeed(ITEM_RANDOM_SEED); - final List quads = model.getQuads(state, cullFace, random); - final int count = quads.size(); - - for (int j = 0; j < count; j++) { - final BakedQuad q = quads.get(j); - editorQuad.fromVanilla(q, IndigoRenderer.MATERIAL_STANDARD, cullFace); - // Call renderQuad directly instead of emit for efficiency - renderQuad(editorQuad); - } - } - - editorQuad.clear(); - } else { - vanillaHandler.accept(model, itemStack, lightmap, overlay, matrixStack, defaultVertexConsumer); - } + VanillaModelEncoder.emitItemQuads(model, state, randomSupplier, ItemRenderContext.this); } } - - /** used to accept a method reference from the ItemRenderer. */ - @FunctionalInterface - public interface VanillaQuadHandler { - void accept(BakedModel model, ItemStack stack, int color, int overlay, MatrixStack matrixStack, VertexConsumer buffer); - } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BakedModelMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BakedModelMixin.java new file mode 100644 index 0000000000..10218850f8 --- /dev/null +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BakedModelMixin.java @@ -0,0 +1,43 @@ +/* + * 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 java.util.function.Supplier; + +import org.spongepowered.asm.mixin.Mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.BlockRenderView; + +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.impl.client.indigo.renderer.render.AbstractBlockRenderContext; +import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; + +@Mixin(BakedModel.class) +public interface BakedModelMixin extends FabricBakedModel { + /** + * Override the fallback path to shade vanilla quads differently. + */ + @Override + default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, ((AbstractBlockRenderContext) context).getVanillaModelEmitter()); + } +} diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererMixin.java index 3b170efa93..40890cc213 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererMixin.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/ItemRendererMixin.java @@ -32,9 +32,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; -import net.fabricmc.fabric.impl.client.indigo.renderer.render.IndigoQuadHandler; import net.fabricmc.fabric.impl.client.indigo.renderer.render.ItemRenderContext; -import net.fabricmc.fabric.impl.client.indigo.renderer.render.ItemRenderContext.VanillaQuadHandler; @Mixin(ItemRenderer.class) public abstract class ItemRendererMixin { @@ -45,13 +43,10 @@ public abstract class ItemRendererMixin { @Unique private final ThreadLocal fabric_contexts = ThreadLocal.withInitial(() -> new ItemRenderContext(colors)); - @Unique - private final VanillaQuadHandler fabric_vanillaHandler = new IndigoQuadHandler((ItemRenderer) (Object) this); - @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/BakedModel;isBuiltin()Z"), method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", cancellable = true) public void hook_renderItem(ItemStack stack, ModelTransformationMode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, CallbackInfo ci) { if (!model.isVanillaAdapter()) { - fabric_contexts.get().renderModel(stack, transformMode, invert, matrixStack, vertexConsumerProvider, light, overlay, model, fabric_vanillaHandler); + fabric_contexts.get().renderModel(stack, transformMode, invert, matrixStack, vertexConsumerProvider, light, overlay, model); matrixStack.pop(); ci.cancel(); } 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 929ca21453..f15cbeb367 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 @@ -6,6 +6,7 @@ "mixins": [ ], "client": [ + "BakedModelMixin", "BlockModelRendererMixin", "ChunkBuilderBuiltChunkRebuildTaskMixin", "ChunkRendererRegionMixin",