mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-14 19:25:23 -05:00
FRAPI improvements: context getters, full removal of fallback consumers, small enhancements (#3287)
* Add cull check and item transformation mode getter to FRAPI * Terminally deprecate `fallbackConsumer` and `bakedModelConsumer` * Fix uvs in octagonal column test mod * Review comments
This commit is contained in:
parent
ecfd5a888d
commit
39a511ba53
11 changed files with 255 additions and 134 deletions
|
@ -29,6 +29,7 @@ import net.minecraft.util.math.random.Random;
|
|||
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 @@ public interface FabricBakedModel {
|
|||
* 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<Random> randomSupplier, RenderContext context) {
|
||||
context.bakedModelConsumer().accept((BakedModel) this, state);
|
||||
VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, context.getEmitter());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,9 +124,7 @@ public interface FabricBakedModel {
|
|||
* logic here, instead of returning every possible shape from {@link BakedModel#getOverrides}
|
||||
* as vanilla baked models.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
default void emitItemQuads(ItemStack stack, Supplier<Random> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,16 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
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 {
|
|||
*
|
||||
* <p>Meshes are never mutated by the transformer - only buffered quads. This ensures thread-safe
|
||||
* use of meshes/models across multiple chunk builders.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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 @@ public interface RenderContext {
|
|||
* @deprecated Use {@link Mesh#outputTo(QuadEmitter)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
Consumer<Mesh> meshConsumer();
|
||||
default Consumer<Mesh> 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 @@ public interface RenderContext {
|
|||
* or {@link FabricBakedModel#emitItemQuads(ItemStack, Supplier, RenderContext) emitItemQuads} on the baked model
|
||||
* that you want to consume instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
default Consumer<BakedModel> fallbackConsumer() {
|
||||
return bakedModelConsumer();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
interface BakedModelConsumer extends Consumer<BakedModel> {
|
||||
/**
|
||||
* Render a baked model by processing its {@linkplain BakedModel#getQuads} using the rendered block state.
|
||||
|
|
|
@ -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<Random> 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<BakedQuad> 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<Random> 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<BakedQuad> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ import net.minecraft.client.texture.Sprite;
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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 class OctagonalColumnUnbakedModel implements UnbakedModel {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render;
|
|||
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.RenderLayer;
|
|||
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 abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
|||
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 abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
|||
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 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!blockInfo.shouldDrawFace(quad.cullFace())) {
|
||||
if (isFaceCulled(quad.cullFace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -275,21 +298,6 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
|||
* 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 abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
|||
|
||||
@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<BakedQuad> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,8 @@ abstract class AbstractRenderContext implements RenderContext {
|
|||
return activeTransform.transform(q);
|
||||
}
|
||||
|
||||
protected boolean hasTransform() {
|
||||
@Override
|
||||
public boolean hasTransform() {
|
||||
return activeTransform != NO_TRANSFORM;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.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.ModelTransformationMode;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.BlockItem;
|
||||
|
@ -44,12 +42,11 @@ import net.minecraft.util.math.random.Random;
|
|||
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 class ItemRenderContext extends AbstractRenderContext {
|
|||
private MatrixStack matrixStack;
|
||||
private VertexConsumerProvider vertexConsumerProvider;
|
||||
private int lightmap;
|
||||
private VanillaQuadHandler vanillaHandler;
|
||||
|
||||
private boolean isDefaultTranslucent;
|
||||
private boolean isTranslucentDirect;
|
||||
|
@ -94,7 +90,6 @@ public class ItemRenderContext extends AbstractRenderContext {
|
|||
private VertexConsumer cutoutVertexConsumer;
|
||||
private VertexConsumer translucentGlintVertexConsumer;
|
||||
private VertexConsumer cutoutGlintVertexConsumer;
|
||||
private VertexConsumer defaultVertexConsumer;
|
||||
|
||||
public ItemRenderContext(ItemColors colorMap) {
|
||||
this.colorMap = colorMap;
|
||||
|
@ -106,19 +101,28 @@ public class ItemRenderContext extends AbstractRenderContext {
|
|||
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 class ItemRenderContext extends AbstractRenderContext {
|
|||
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 @@ public class ItemRenderContext extends AbstractRenderContext {
|
|||
}
|
||||
|
||||
isDefaultGlint = itemStack.hasGlint();
|
||||
|
||||
defaultVertexConsumer = getVertexConsumer(BlendMode.DEFAULT, TriState.DEFAULT);
|
||||
}
|
||||
|
||||
private void renderQuad(MutableQuadViewImpl quad) {
|
||||
|
@ -275,34 +275,7 @@ public class ItemRenderContext extends AbstractRenderContext {
|
|||
|
||||
@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<BakedQuad> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Random> randomSupplier, RenderContext context) {
|
||||
VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, ((AbstractBlockRenderContext) context).getVanillaModelEmitter());
|
||||
}
|
||||
}
|
|
@ -32,9 +32,7 @@ import net.minecraft.client.render.model.json.ModelTransformationMode;
|
|||
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<ItemRenderContext> 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();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"mixins": [
|
||||
],
|
||||
"client": [
|
||||
"BakedModelMixin",
|
||||
"BlockModelRendererMixin",
|
||||
"ChunkBuilderBuiltChunkRebuildTaskMixin",
|
||||
"ChunkRendererRegionMixin",
|
||||
|
|
Loading…
Reference in a new issue