mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-22 23:58:02 -05:00
Modernize Indigo (#2110)
* Modernize Indigo - Restructure ItemRenderContext to be more efficient and consistent with block rendering - Remove unnecessary code including CompatibilityHelper - Add Unique annotations to fields added by Indigo - Fix typos - Organize imports * Remove unused import * Fix bugs - Fix enchantment glint not rendering on item models - Fix QuadView#copyTo not copying enough data - Make ItemRenderContext vertex consumer calculation mirror vanilla and be more efficient * Clear the target quad's material * Tweaks - Retain material during copyTo instead of clearing it - Standardize mixins * Direct return - Return from ItemRenderContext#quadVertexConsumer instead of assigning value to variable
This commit is contained in:
parent
bd8a4a1845
commit
7faf0d8813
16 changed files with 318 additions and 316 deletions
|
@ -33,9 +33,10 @@ import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingForma
|
|||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl;
|
||||
|
@ -163,7 +164,9 @@ public class QuadViewImpl implements QuadView {
|
|||
|
||||
final MutableQuadViewImpl quad = (MutableQuadViewImpl) target;
|
||||
// copy everything except the material
|
||||
System.arraycopy(data, baseIndex + 1, quad.data, quad.baseIndex + 1, EncodingFormat.TOTAL_STRIDE - 1);
|
||||
RenderMaterial material = quad.material();
|
||||
System.arraycopy(data, baseIndex, quad.data, quad.baseIndex, EncodingFormat.TOTAL_STRIDE);
|
||||
quad.material(material);
|
||||
quad.faceNormal.set(faceNormal.getX(), faceNormal.getY(), faceNormal.getZ());
|
||||
quad.nominalFace = this.nominalFace;
|
||||
quad.isGeometryInvalid = false;
|
||||
|
|
|
@ -34,7 +34,7 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MeshImpl;
|
|||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
||||
|
||||
/**
|
||||
* Consumer for pre-baked meshes. Works by copying the mesh data to a
|
||||
* Consumer for pre-baked meshes. Works by copying the mesh data to an
|
||||
* "editor" quad held in the instance, where all transformations are applied before buffering.
|
||||
*/
|
||||
public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implements Consumer<Mesh> {
|
||||
|
@ -46,7 +46,7 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
|
|||
* Where we handle all pre-buffer coloring, lighting, transformation, etc.
|
||||
* Reused for all mesh quads. Fixed baking array sized to hold largest possible mesh quad.
|
||||
*/
|
||||
private class Maker extends MutableQuadViewImpl implements QuadEmitter {
|
||||
private class Maker extends MutableQuadViewImpl {
|
||||
{
|
||||
data = new int[EncodingFormat.TOTAL_STRIDE];
|
||||
material(IndigoRenderer.MATERIAL_STANDARD);
|
||||
|
@ -84,44 +84,44 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
|
|||
return editorQuad;
|
||||
}
|
||||
|
||||
private void renderQuad(MutableQuadViewImpl q) {
|
||||
if (!transform.transform(editorQuad)) {
|
||||
private void renderQuad(MutableQuadViewImpl quad) {
|
||||
if (!transform.transform(quad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blockInfo.shouldDrawFace(q.cullFace())) {
|
||||
if (!blockInfo.shouldDrawFace(quad.cullFace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final RenderMaterialImpl.Value mat = q.material();
|
||||
final RenderMaterialImpl.Value mat = quad.material();
|
||||
|
||||
if (!mat.disableAo(0) && MinecraftClient.isAmbientOcclusionEnabled()) {
|
||||
// needs to happen before offsets are applied
|
||||
aoCalc.compute(q, false);
|
||||
aoCalc.compute(quad, false);
|
||||
}
|
||||
|
||||
tesselateQuad(q, mat, 0);
|
||||
tessellateQuad(quad, mat, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines color index and render layer, then routes to appropriate
|
||||
* tesselate routine based on material properties.
|
||||
* tessellate routine based on material properties.
|
||||
*/
|
||||
private void tesselateQuad(MutableQuadViewImpl quad, RenderMaterialImpl.Value mat, int textureIndex) {
|
||||
private void tessellateQuad(MutableQuadViewImpl quad, RenderMaterialImpl.Value mat, int textureIndex) {
|
||||
final int colorIndex = mat.disableColorIndex(textureIndex) ? -1 : quad.colorIndex();
|
||||
final RenderLayer renderLayer = blockInfo.effectiveRenderLayer(mat.blendMode(textureIndex));
|
||||
|
||||
if (blockInfo.defaultAo && !mat.disableAo(textureIndex)) {
|
||||
if (mat.emissive(textureIndex)) {
|
||||
tesselateSmoothEmissive(quad, renderLayer, colorIndex);
|
||||
tessellateSmoothEmissive(quad, renderLayer, colorIndex);
|
||||
} else {
|
||||
tesselateSmooth(quad, renderLayer, colorIndex);
|
||||
tessellateSmooth(quad, renderLayer, colorIndex);
|
||||
}
|
||||
} else {
|
||||
if (mat.emissive(textureIndex)) {
|
||||
tesselateFlatEmissive(quad, renderLayer, colorIndex);
|
||||
tessellateFlatEmissive(quad, renderLayer, colorIndex);
|
||||
} else {
|
||||
tesselateFlat(quad, renderLayer, colorIndex);
|
||||
tessellateFlat(quad, renderLayer, colorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,14 +22,15 @@ import java.util.function.Function;
|
|||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.LightmapTextureManager;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.WorldRenderer;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
|
||||
|
@ -42,8 +43,6 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
|||
* Has most of the actual buffer-time lighting and coloring logic.
|
||||
*/
|
||||
public abstract class AbstractQuadRenderer {
|
||||
static final int FULL_BRIGHTNESS = 0xF000F0;
|
||||
|
||||
protected final Function<RenderLayer, VertexConsumer> bufferFunc;
|
||||
protected final BlockRenderInfo blockInfo;
|
||||
protected final AoCalculator aoCalc;
|
||||
|
@ -115,7 +114,7 @@ public abstract class AbstractQuadRenderer {
|
|||
// routines below have a bit of copy-paste code reuse to avoid conditional execution inside a hot loop
|
||||
|
||||
/** for non-emissive mesh quads and all fallback quads with smooth lighting. */
|
||||
protected void tesselateSmooth(MutableQuadViewImpl q, RenderLayer renderLayer, int blockColorIndex) {
|
||||
protected void tessellateSmooth(MutableQuadViewImpl q, RenderLayer renderLayer, int blockColorIndex) {
|
||||
colorizeQuad(q, blockColorIndex);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
@ -127,19 +126,19 @@ public abstract class AbstractQuadRenderer {
|
|||
}
|
||||
|
||||
/** for emissive mesh quads with smooth lighting. */
|
||||
protected void tesselateSmoothEmissive(MutableQuadViewImpl q, RenderLayer renderLayer, int blockColorIndex) {
|
||||
protected void tessellateSmoothEmissive(MutableQuadViewImpl q, RenderLayer renderLayer, int blockColorIndex) {
|
||||
colorizeQuad(q, blockColorIndex);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
q.spriteColor(i, 0, ColorHelper.multiplyRGB(q.spriteColor(i, 0), aoCalc.ao[i]));
|
||||
q.lightmap(i, FULL_BRIGHTNESS);
|
||||
q.lightmap(i, LightmapTextureManager.MAX_LIGHT_COORDINATE);
|
||||
}
|
||||
|
||||
bufferQuad(q, renderLayer);
|
||||
}
|
||||
|
||||
/** for non-emissive mesh quads and all fallback quads with flat lighting. */
|
||||
protected void tesselateFlat(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
|
||||
protected void tessellateFlat(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
|
||||
colorizeQuad(quad, blockColorIndex);
|
||||
shadeFlatQuad(quad);
|
||||
|
||||
|
@ -153,12 +152,12 @@ public abstract class AbstractQuadRenderer {
|
|||
}
|
||||
|
||||
/** for emissive mesh quads with flat lighting. */
|
||||
protected void tesselateFlatEmissive(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
|
||||
protected void tessellateFlatEmissive(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
|
||||
colorizeQuad(quad, blockColorIndex);
|
||||
shadeFlatQuad(quad);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quad.lightmap(i, FULL_BRIGHTNESS);
|
||||
quad.lightmap(i, LightmapTextureManager.MAX_LIGHT_COORDINATE);
|
||||
}
|
||||
|
||||
bufferQuad(quad, renderLayer);
|
||||
|
|
|
@ -18,19 +18,17 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render;
|
|||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
|
||||
abstract class AbstractRenderContext implements RenderContext {
|
||||
private final ObjectArrayList<QuadTransform> transformStack = new ObjectArrayList<>();
|
||||
private static final QuadTransform NO_TRANSFORM = (q) -> true;
|
||||
protected Matrix4f matrix;
|
||||
protected Matrix3f normalMatrix;
|
||||
protected int overlay;
|
||||
|
||||
private QuadTransform activeTransform = NO_TRANSFORM;
|
||||
private final ObjectArrayList<QuadTransform> transformStack = new ObjectArrayList<>();
|
||||
private final QuadTransform stackTransform = (q) -> {
|
||||
int i = transformStack.size() - 1;
|
||||
|
||||
|
@ -43,7 +41,9 @@ abstract class AbstractRenderContext implements RenderContext {
|
|||
return true;
|
||||
};
|
||||
|
||||
private QuadTransform activeTransform = NO_TRANSFORM;
|
||||
protected Matrix4f matrix;
|
||||
protected Matrix3f normalMatrix;
|
||||
protected int overlay;
|
||||
|
||||
protected final boolean transform(MutableQuadView q) {
|
||||
return activeTransform.transform(q);
|
||||
|
|
|
@ -18,37 +18,36 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render;
|
|||
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.LightmapTextureManager;
|
||||
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.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
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;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoLuminanceFix;
|
||||
|
||||
/**
|
||||
* Context for non-terrain block rendering.
|
||||
*/
|
||||
public class BlockRenderContext extends AbstractRenderContext implements RenderContext {
|
||||
public class BlockRenderContext extends AbstractRenderContext {
|
||||
private final BlockRenderInfo blockInfo = new BlockRenderInfo();
|
||||
private final AoCalculator aoCalc = new AoCalculator(blockInfo, this::brightness, this::aoLevel);
|
||||
private final MeshConsumer meshConsumer = new MeshConsumer(blockInfo, this::outputBuffer, aoCalc, this::transform);
|
||||
|
||||
private VertexConsumer bufferBuilder;
|
||||
private boolean didOutput = false;
|
||||
// These are kept as fields to avoid avoid the heap allocation for a supplier.
|
||||
// These are kept as fields to avoid the heap allocation for a supplier.
|
||||
// BlockModelRenderer allows the caller to supply both the random object and seed.
|
||||
private Random random;
|
||||
private long seed;
|
||||
|
@ -57,16 +56,7 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
|
|||
return random;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reuse the fallback consumer from the render context used during chunk rebuild to make it properly
|
||||
* apply the current transforms to vanilla models.
|
||||
*/
|
||||
private final TerrainFallbackConsumer fallbackConsumer = new TerrainFallbackConsumer(blockInfo, this::outputBuffer, aoCalc, this::transform) {
|
||||
@Override
|
||||
protected int overlay() {
|
||||
return overlay;
|
||||
}
|
||||
|
||||
private final AbstractMeshConsumer meshConsumer = new AbstractMeshConsumer(blockInfo, this::outputBuffer, aoCalc, this::transform) {
|
||||
@Override
|
||||
protected Matrix4f matrix() {
|
||||
return matrix;
|
||||
|
@ -76,11 +66,37 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
|
|||
protected Matrix3f normalMatrix() {
|
||||
return normalMatrix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int overlay() {
|
||||
return overlay;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reuse the fallback consumer from the render context used during chunk rebuild to make it properly
|
||||
* apply the current transforms to vanilla models.
|
||||
*/
|
||||
private final TerrainFallbackConsumer fallbackConsumer = new TerrainFallbackConsumer(blockInfo, this::outputBuffer, aoCalc, this::transform) {
|
||||
@Override
|
||||
protected Matrix4f matrix() {
|
||||
return matrix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matrix3f normalMatrix() {
|
||||
return normalMatrix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int overlay() {
|
||||
return overlay;
|
||||
}
|
||||
};
|
||||
|
||||
private int brightness(BlockPos pos) {
|
||||
if (blockInfo.blockView == null) {
|
||||
return 15 << 20 | 15 << 4;
|
||||
return LightmapTextureManager.MAX_LIGHT_COORDINATE;
|
||||
}
|
||||
|
||||
return WorldRenderer.getLightmapCoordinates(blockInfo.blockView, blockInfo.blockView.getBlockState(pos), pos);
|
||||
|
@ -119,27 +135,6 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
|
|||
return didOutput;
|
||||
}
|
||||
|
||||
private class MeshConsumer extends AbstractMeshConsumer {
|
||||
MeshConsumer(BlockRenderInfo blockInfo, Function<RenderLayer, VertexConsumer> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
|
||||
super(blockInfo, bufferFunc, aoCalc, transform);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matrix4f matrix() {
|
||||
return matrix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matrix3f normalMatrix() {
|
||||
return normalMatrix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int overlay() {
|
||||
return overlay;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<Mesh> meshConsumer() {
|
||||
return meshConsumer;
|
||||
|
|
|
@ -25,8 +25,8 @@ import net.minecraft.client.render.BufferBuilder;
|
|||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.WorldRenderer;
|
||||
import net.minecraft.client.render.chunk.BlockBufferBuilderStorage;
|
||||
import net.minecraft.client.render.chunk.ChunkBuilder.ChunkData;
|
||||
import net.minecraft.client.render.chunk.ChunkBuilder.BuiltChunk;
|
||||
import net.minecraft.client.render.chunk.ChunkBuilder.ChunkData;
|
||||
import net.minecraft.client.render.chunk.ChunkRendererRegion;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
|
|
@ -1,44 +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.fabricmc.fabric.impl.client.indigo.Indigo;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat;
|
||||
|
||||
/**
|
||||
* Controls 1x warning for vanilla quad vertex format when running in compatibility mode.
|
||||
*/
|
||||
public abstract class CompatibilityHelper {
|
||||
private CompatibilityHelper() { }
|
||||
|
||||
private static boolean logCompatibilityWarning = true;
|
||||
|
||||
private static boolean isCompatible(int[] vertexData) {
|
||||
final boolean result = vertexData.length == EncodingFormat.QUAD_STRIDE;
|
||||
|
||||
if (!result && logCompatibilityWarning) {
|
||||
logCompatibilityWarning = false;
|
||||
Indigo.LOGGER.warn("[Indigo] Encountered baked quad with non-standard vertex format. Some blocks will not be rendered");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean canRender(int[] vertexData) {
|
||||
return !Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY || isCompatible(vertexData);
|
||||
}
|
||||
}
|
|
@ -22,7 +22,9 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.color.item.ItemColors;
|
||||
import net.minecraft.client.render.LightmapTextureManager;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.RenderLayers;
|
||||
import net.minecraft.client.render.TexturedRenderLayers;
|
||||
|
@ -31,20 +33,19 @@ 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.Mode;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
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;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
|
||||
|
@ -54,10 +55,8 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
|||
|
||||
/**
|
||||
* The render context used for item rendering.
|
||||
* Does not implement emissive lighting for sake
|
||||
* of simplicity in the default renderer.
|
||||
*/
|
||||
public class ItemRenderContext extends AbstractRenderContext implements RenderContext {
|
||||
public class ItemRenderContext extends AbstractRenderContext {
|
||||
/** Value vanilla uses for item rendering. The only sensible choice, of course. */
|
||||
private static final long ITEM_RANDOM_SEED = 42L;
|
||||
|
||||
|
@ -69,127 +68,82 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
|
|||
|
||||
private final ItemColors colorMap;
|
||||
private final Random random = new Random();
|
||||
private final Consumer<BakedModel> fallbackConsumer;
|
||||
private final Vec3f normalVec = new Vec3f();
|
||||
|
||||
private MatrixStack matrixStack;
|
||||
private Matrix4f matrix;
|
||||
private VertexConsumerProvider vertexConsumerProvider;
|
||||
private VertexConsumer modelVertexConsumer;
|
||||
private BlendMode quadBlendMode;
|
||||
private VertexConsumer quadVertexConsumer;
|
||||
private Mode transformMode;
|
||||
private int lightmap;
|
||||
private int overlay;
|
||||
private ItemStack itemStack;
|
||||
private VanillaQuadHandler vanillaHandler;
|
||||
|
||||
private final Supplier<Random> randomSupplier = () -> {
|
||||
final Random result = random;
|
||||
result.setSeed(ITEM_RANDOM_SEED);
|
||||
random.setSeed(ITEM_RANDOM_SEED);
|
||||
return random;
|
||||
};
|
||||
|
||||
private final int[] quadData = new int[EncodingFormat.TOTAL_STRIDE];
|
||||
private final Maker editorQuad = new Maker();
|
||||
private final MeshConsumer meshConsumer = new MeshConsumer();
|
||||
private final FallbackConsumer fallbackConsumer = new FallbackConsumer();
|
||||
|
||||
private ItemStack itemStack;
|
||||
private Mode transformMode;
|
||||
private MatrixStack matrixStack;
|
||||
private VertexConsumerProvider vertexConsumerProvider;
|
||||
private int lightmap;
|
||||
private VanillaQuadHandler vanillaHandler;
|
||||
|
||||
private boolean isDefaultTranslucent;
|
||||
private boolean isTranslucentDirect;
|
||||
private VertexConsumer translucentVertexConsumer;
|
||||
private VertexConsumer cutoutVertexConsumer;
|
||||
private VertexConsumer modelVertexConsumer;
|
||||
|
||||
public ItemRenderContext(ItemColors colorMap) {
|
||||
this.colorMap = colorMap;
|
||||
fallbackConsumer = this::fallbackConsumer;
|
||||
}
|
||||
|
||||
public void renderModel(ItemStack itemStack, Mode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int lightmap, int overlay, FabricBakedModel model, VanillaQuadHandler vanillaHandler) {
|
||||
public void renderModel(ItemStack itemStack, Mode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int lightmap, int overlay, BakedModel model, VanillaQuadHandler vanillaHandler) {
|
||||
this.itemStack = itemStack;
|
||||
this.transformMode = transformMode;
|
||||
this.matrixStack = matrixStack;
|
||||
this.vertexConsumerProvider = vertexConsumerProvider;
|
||||
this.lightmap = lightmap;
|
||||
this.overlay = overlay;
|
||||
this.itemStack = itemStack;
|
||||
this.vertexConsumerProvider = vertexConsumerProvider;
|
||||
this.matrixStack = matrixStack;
|
||||
this.transformMode = transformMode;
|
||||
this.vanillaHandler = vanillaHandler;
|
||||
quadBlendMode = BlendMode.DEFAULT;
|
||||
modelVertexConsumer = selectVertexConsumer(RenderLayers.getItemLayer(itemStack, transformMode != ModelTransformation.Mode.GROUND));
|
||||
computeOutputInfo();
|
||||
|
||||
matrixStack.push();
|
||||
((BakedModel) model).getTransformation().getTransformation(transformMode).apply(invert, matrixStack);
|
||||
model.getTransformation().getTransformation(transformMode).apply(invert, matrixStack);
|
||||
matrixStack.translate(-0.5D, -0.5D, -0.5D);
|
||||
matrix = matrixStack.peek().getPositionMatrix();
|
||||
normalMatrix = matrixStack.peek().getNormalMatrix();
|
||||
|
||||
model.emitItemQuads(itemStack, randomSupplier, this);
|
||||
((FabricBakedModel) model).emitItemQuads(itemStack, randomSupplier, this);
|
||||
|
||||
matrixStack.pop();
|
||||
|
||||
this.matrixStack = null;
|
||||
this.itemStack = null;
|
||||
this.matrixStack = null;
|
||||
this.vanillaHandler = null;
|
||||
translucentVertexConsumer = null;
|
||||
cutoutVertexConsumer = 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 = transformMode == ModelTransformation.Mode.GUI ? TexturedRenderLayers.getEntityTranslucentCull() : layerIn;
|
||||
return ItemRenderer.getArmorGlintConsumer(vertexConsumerProvider, layer, true, itemStack.hasGlint());
|
||||
}
|
||||
private void computeOutputInfo() {
|
||||
isDefaultTranslucent = true;
|
||||
isTranslucentDirect = true;
|
||||
|
||||
private class Maker extends MutableQuadViewImpl implements QuadEmitter {
|
||||
{
|
||||
data = quadData;
|
||||
clear();
|
||||
Item item = itemStack.getItem();
|
||||
|
||||
if (item instanceof BlockItem blockItem) {
|
||||
BlockState state = blockItem.getBlock().getDefaultState();
|
||||
RenderLayer renderLayer = RenderLayers.getBlockLayer(state);
|
||||
|
||||
if (renderLayer != RenderLayer.getTranslucent()) {
|
||||
isDefaultTranslucent = false;
|
||||
}
|
||||
|
||||
if (transformMode != Mode.GUI && !transformMode.isFirstPerson()) {
|
||||
isTranslucentDirect = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maker emit() {
|
||||
computeGeometry();
|
||||
renderQuad();
|
||||
clear();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private final Maker editorQuad = new Maker();
|
||||
|
||||
private final Consumer<Mesh> meshConsumer = (mesh) -> {
|
||||
final MeshImpl m = (MeshImpl) mesh;
|
||||
final int[] data = m.data();
|
||||
final int limit = data.length;
|
||||
int index = 0;
|
||||
|
||||
while (index < limit) {
|
||||
System.arraycopy(data, index, editorQuad.data(), 0, EncodingFormat.TOTAL_STRIDE);
|
||||
editorQuad.load();
|
||||
index += EncodingFormat.TOTAL_STRIDE;
|
||||
renderQuad();
|
||||
}
|
||||
};
|
||||
|
||||
private int indexColor() {
|
||||
final int colorIndex = editorQuad.colorIndex();
|
||||
return colorIndex == -1 ? -1 : (colorMap.getColor(itemStack, colorIndex) | 0xFF000000);
|
||||
}
|
||||
|
||||
private void renderQuad() {
|
||||
final MutableQuadViewImpl quad = editorQuad;
|
||||
|
||||
if (!transform(editorQuad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int c = quad.spriteColor(i, 0);
|
||||
c = ColorHelper.multiplyColor(quadColor, c);
|
||||
quad.spriteColor(i, 0, ColorHelper.swapRedBlueIfNeeded(c));
|
||||
quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), lightmap));
|
||||
}
|
||||
|
||||
AbstractQuadRenderer.bufferQuad(quadVertexConsumer(mat.blendMode(0)), quad, matrix, overlay, normalMatrix, normalVec);
|
||||
modelVertexConsumer = quadVertexConsumer(BlendMode.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,25 +152,157 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
|
|||
* translucent are mapped to cutout.
|
||||
*/
|
||||
private VertexConsumer quadVertexConsumer(BlendMode blendMode) {
|
||||
boolean translucent;
|
||||
|
||||
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(TexturedRenderLayers.getEntityTranslucentCull());
|
||||
quadBlendMode = BlendMode.TRANSLUCENT;
|
||||
translucent = isDefaultTranslucent;
|
||||
} else {
|
||||
quadVertexConsumer = selectVertexConsumer(TexturedRenderLayers.getEntityCutout());
|
||||
quadBlendMode = BlendMode.CUTOUT;
|
||||
translucent = blendMode == BlendMode.TRANSLUCENT;
|
||||
}
|
||||
|
||||
return quadVertexConsumer;
|
||||
if (translucent) {
|
||||
if (translucentVertexConsumer == null) {
|
||||
if (isTranslucentDirect) {
|
||||
translucentVertexConsumer = ItemRenderer.getDirectItemGlintConsumer(vertexConsumerProvider, TexturedRenderLayers.getEntityTranslucentCull(), true, itemStack.hasGlint());
|
||||
} else if (MinecraftClient.isFabulousGraphicsOrBetter()) {
|
||||
translucentVertexConsumer = ItemRenderer.getItemGlintConsumer(vertexConsumerProvider, TexturedRenderLayers.getItemEntityTranslucentCull(), true, itemStack.hasGlint());
|
||||
} else {
|
||||
translucentVertexConsumer = ItemRenderer.getItemGlintConsumer(vertexConsumerProvider, TexturedRenderLayers.getEntityTranslucentCull(), true, itemStack.hasGlint());
|
||||
}
|
||||
}
|
||||
|
||||
return translucentVertexConsumer;
|
||||
} else {
|
||||
if (cutoutVertexConsumer == null) {
|
||||
cutoutVertexConsumer = ItemRenderer.getDirectItemGlintConsumer(vertexConsumerProvider, TexturedRenderLayers.getEntityCutout(), true, itemStack.hasGlint());
|
||||
}
|
||||
|
||||
return cutoutVertexConsumer;
|
||||
}
|
||||
}
|
||||
|
||||
private void bufferQuad(MutableQuadViewImpl quad, BlendMode blendMode) {
|
||||
AbstractQuadRenderer.bufferQuad(quadVertexConsumer(blendMode), quad, matrix, overlay, normalMatrix, normalVec);
|
||||
}
|
||||
|
||||
private void colorizeQuad(MutableQuadViewImpl q, int colorIndex) {
|
||||
if (colorIndex == -1) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
q.spriteColor(i, 0, ColorHelper.swapRedBlueIfNeeded(q.spriteColor(i, 0)));
|
||||
}
|
||||
} else {
|
||||
final int itemColor = 0xFF000000 | colorMap.getColor(itemStack, colorIndex);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
q.spriteColor(i, 0, ColorHelper.swapRedBlueIfNeeded(ColorHelper.multiplyColor(itemColor, q.spriteColor(i, 0))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderQuad(MutableQuadViewImpl quad, BlendMode blendMode, int colorIndex) {
|
||||
colorizeQuad(quad, colorIndex);
|
||||
|
||||
final int lightmap = this.lightmap;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), lightmap));
|
||||
}
|
||||
|
||||
bufferQuad(quad, blendMode);
|
||||
}
|
||||
|
||||
private void renderQuadEmissive(MutableQuadViewImpl quad, BlendMode blendMode, int colorIndex) {
|
||||
colorizeQuad(quad, colorIndex);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quad.lightmap(i, LightmapTextureManager.MAX_LIGHT_COORDINATE);
|
||||
}
|
||||
|
||||
bufferQuad(quad, blendMode);
|
||||
}
|
||||
|
||||
private void renderMeshQuad(MutableQuadViewImpl quad) {
|
||||
if (!transform(quad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final RenderMaterialImpl.Value mat = quad.material();
|
||||
|
||||
final int colorIndex = mat.disableColorIndex(0) ? -1 : quad.colorIndex();
|
||||
final BlendMode blendMode = mat.blendMode(0);
|
||||
|
||||
if (mat.emissive(0)) {
|
||||
renderQuadEmissive(quad, blendMode, colorIndex);
|
||||
} else {
|
||||
renderQuad(quad, blendMode, colorIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private class Maker extends MutableQuadViewImpl implements QuadEmitter {
|
||||
{
|
||||
data = new int[EncodingFormat.TOTAL_STRIDE];
|
||||
clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maker emit() {
|
||||
computeGeometry();
|
||||
renderMeshQuad(this);
|
||||
clear();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private class MeshConsumer implements Consumer<Mesh> {
|
||||
@Override
|
||||
public void accept(Mesh mesh) {
|
||||
final MeshImpl m = (MeshImpl) mesh;
|
||||
final int[] data = m.data();
|
||||
final int limit = data.length;
|
||||
int index = 0;
|
||||
|
||||
while (index < limit) {
|
||||
System.arraycopy(data, index, editorQuad.data(), 0, EncodingFormat.TOTAL_STRIDE);
|
||||
editorQuad.load();
|
||||
index += EncodingFormat.TOTAL_STRIDE;
|
||||
renderMeshQuad(editorQuad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FallbackConsumer implements Consumer<BakedModel> {
|
||||
@Override
|
||||
public void accept(BakedModel model) {
|
||||
if (hasTransform()) {
|
||||
// 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(null, cullFace, random);
|
||||
final int count = quads.size();
|
||||
|
||||
if (count != 0) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
final BakedQuad q = quads.get(j);
|
||||
renderQuadWithTransform(q, cullFace);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vanillaHandler.accept(model, itemStack, lightmap, overlay, matrixStack, modelVertexConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderQuadWithTransform(BakedQuad quad, Direction cullFace) {
|
||||
final Maker editorQuad = ItemRenderContext.this.editorQuad;
|
||||
editorQuad.fromVanilla(quad, IndigoRenderer.MATERIAL_STANDARD, cullFace);
|
||||
|
||||
if (!transform(editorQuad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderQuad(editorQuad, BlendMode.DEFAULT, editorQuad.colorIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -224,32 +310,6 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
|
|||
return meshConsumer;
|
||||
}
|
||||
|
||||
private void fallbackConsumer(BakedModel model) {
|
||||
if (hasTransform()) {
|
||||
// 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++) {
|
||||
random.setSeed(ITEM_RANDOM_SEED);
|
||||
final Direction cullFace = ModelHelper.faceFromIndex(i);
|
||||
renderFallbackWithTransform(model.getQuads((BlockState) null, cullFace, random), cullFace);
|
||||
}
|
||||
} else {
|
||||
vanillaHandler.accept(model, itemStack, lightmap, overlay, matrixStack, modelVertexConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderFallbackWithTransform(List<BakedQuad> quads, Direction cullFace) {
|
||||
if (quads.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Maker editorQuad = this.editorQuad;
|
||||
|
||||
for (final BakedQuad q : quads) {
|
||||
editorQuad.fromVanilla(q, IndigoRenderer.MATERIAL_STANDARD, cullFace);
|
||||
renderQuad();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<BakedModel> fallbackConsumer() {
|
||||
return fallbackConsumer;
|
||||
|
|
|
@ -58,10 +58,8 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
|||
* manipulating the data via NIO.
|
||||
*/
|
||||
public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer implements Consumer<BakedModel> {
|
||||
private static Value MATERIAL_FLAT = (Value) IndigoRenderer.INSTANCE.materialFinder().disableAo(0, true).find();
|
||||
private static Value MATERIAL_SHADED = (Value) IndigoRenderer.INSTANCE.materialFinder().find();
|
||||
|
||||
private final int[] editorBuffer = new int[EncodingFormat.TOTAL_STRIDE];
|
||||
private static final Value MATERIAL_FLAT = (Value) IndigoRenderer.INSTANCE.materialFinder().disableAo(0, true).find();
|
||||
private static final Value MATERIAL_SHADED = (Value) IndigoRenderer.INSTANCE.materialFinder().find();
|
||||
|
||||
TerrainFallbackConsumer(BlockRenderInfo blockInfo, Function<RenderLayer, VertexConsumer> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
|
||||
super(blockInfo, bufferFunc, aoCalc, transform);
|
||||
|
@ -69,7 +67,7 @@ public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer imple
|
|||
|
||||
private final MutableQuadViewImpl editorQuad = new MutableQuadViewImpl() {
|
||||
{
|
||||
data = editorBuffer;
|
||||
data = new int[EncodingFormat.TOTAL_STRIDE];
|
||||
material(MATERIAL_SHADED);
|
||||
}
|
||||
|
||||
|
@ -86,36 +84,21 @@ public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer imple
|
|||
final Value defaultMaterial = blockInfo.defaultAo && model.useAmbientOcclusion() ? MATERIAL_SHADED : MATERIAL_FLAT;
|
||||
final BlockState blockState = blockInfo.blockState;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
final Direction face = ModelHelper.faceFromIndex(i);
|
||||
final List<BakedQuad> quads = model.getQuads(blockState, face, random.get());
|
||||
for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) {
|
||||
final Direction cullFace = ModelHelper.faceFromIndex(i);
|
||||
final List<BakedQuad> quads = model.getQuads(blockState, cullFace, random.get());
|
||||
final int count = quads.size();
|
||||
|
||||
if (count != 0) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
final BakedQuad q = quads.get(j);
|
||||
renderQuad(q, face, defaultMaterial);
|
||||
renderQuad(q, cullFace, defaultMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final List<BakedQuad> quads = model.getQuads(blockState, null, random.get());
|
||||
final int count = quads.size();
|
||||
|
||||
if (count != 0) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
final BakedQuad q = quads.get(j);
|
||||
renderQuad(q, null, defaultMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderQuad(BakedQuad quad, Direction cullFace, Value defaultMaterial) {
|
||||
// TODO: should remove in 1.17 cycle, was for OF compat only
|
||||
if (!CompatibilityHelper.canRender(quad.getVertexData())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final MutableQuadViewImpl editorQuad = this.editorQuad;
|
||||
editorQuad.fromVanilla(quad, defaultMaterial, cullFace);
|
||||
|
||||
|
@ -132,16 +115,16 @@ public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer imple
|
|||
if (!editorQuad.material().disableAo(0)) {
|
||||
// needs to happen before offsets are applied
|
||||
aoCalc.compute(editorQuad, true);
|
||||
tesselateSmooth(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
|
||||
tessellateSmooth(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
|
||||
} else {
|
||||
// Recomputing whether the quad has a light face is only needed if it doesn't also have a cull face,
|
||||
// as in those cases, the cull face will always be used to offset the light sampling position
|
||||
if (cullFace == null) {
|
||||
// Can't rely on lazy computation in tesselateFlat() because needs to happen before offsets are applied
|
||||
// Can't rely on lazy computation in tessellateFlat() because needs to happen before offsets are applied
|
||||
editorQuad.geometryFlags();
|
||||
}
|
||||
|
||||
tesselateFlat(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
|
||||
tessellateFlat(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,17 +20,17 @@ import java.util.function.Consumer;
|
|||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.chunk.BlockBufferBuilderStorage;
|
||||
import net.minecraft.client.render.chunk.ChunkBuilder.ChunkData;
|
||||
import net.minecraft.client.render.chunk.ChunkBuilder.BuiltChunk;
|
||||
import net.minecraft.client.render.chunk.ChunkBuilder.ChunkData;
|
||||
import net.minecraft.client.render.chunk.ChunkRendererRegion;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.crash.CrashException;
|
||||
import net.minecraft.util.crash.CrashReport;
|
||||
import net.minecraft.util.crash.CrashReportSection;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
|
@ -43,8 +43,9 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
|
|||
* Dispatches calls from models during chunk rebuild to the appropriate consumer,
|
||||
* and holds/manages all of the state needed by them.
|
||||
*/
|
||||
public class TerrainRenderContext extends AbstractRenderContext implements RenderContext {
|
||||
public class TerrainRenderContext extends AbstractRenderContext {
|
||||
public static final ThreadLocal<TerrainRenderContext> POOL = ThreadLocal.withInitial(TerrainRenderContext::new);
|
||||
|
||||
private final TerrainBlockRenderInfo blockInfo = new TerrainBlockRenderInfo();
|
||||
private final ChunkRenderInfo chunkInfo = new ChunkRenderInfo();
|
||||
private final AoCalculator aoCalc = new AoCalculator(blockInfo, chunkInfo::cachedBrightness, chunkInfo::cachedAoLevel);
|
||||
|
@ -83,10 +84,9 @@ public class TerrainRenderContext extends AbstractRenderContext implements Rende
|
|||
}
|
||||
};
|
||||
|
||||
public TerrainRenderContext prepare(ChunkRendererRegion blockView, BuiltChunk chunkRenderer, ChunkData chunkData, BlockBufferBuilderStorage builders) {
|
||||
public void prepare(ChunkRendererRegion blockView, BuiltChunk chunkRenderer, ChunkData chunkData, BlockBufferBuilderStorage builders) {
|
||||
blockInfo.setBlockView(blockView);
|
||||
chunkInfo.prepare(blockView, chunkRenderer, chunkData, builders);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
|
@ -95,7 +95,7 @@ public class TerrainRenderContext extends AbstractRenderContext implements Rende
|
|||
}
|
||||
|
||||
/** Called from chunk renderer hook. */
|
||||
public boolean tesselateBlock(BlockState blockState, BlockPos blockPos, final BakedModel model, MatrixStack matrixStack) {
|
||||
public boolean tessellateBlock(BlockState blockState, BlockPos blockPos, final BakedModel model, MatrixStack matrixStack) {
|
||||
this.matrix = matrixStack.peek().getPositionMatrix();
|
||||
this.normalMatrix = matrixStack.peek().getNormalMatrix();
|
||||
|
||||
|
@ -103,11 +103,11 @@ public class TerrainRenderContext extends AbstractRenderContext implements Rende
|
|||
aoCalc.clear();
|
||||
blockInfo.prepareForBlock(blockState, blockPos, model.useAmbientOcclusion());
|
||||
((FabricBakedModel) model).emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this);
|
||||
} catch (Throwable var9) {
|
||||
CrashReport crashReport_1 = CrashReport.create(var9, "Tesselating block in world - Indigo Renderer");
|
||||
CrashReportSection crashReportElement_1 = crashReport_1.addElement("Block being tesselated");
|
||||
CrashReportSection.addBlockInfo(crashReportElement_1, chunkInfo.blockView, blockPos, blockState);
|
||||
throw new CrashException(crashReport_1);
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashReport = CrashReport.create(throwable, "Tessellating block in world - Indigo Renderer");
|
||||
CrashReportSection crashReportSection = crashReport.addElement("Block being tessellated");
|
||||
CrashReportSection.addBlockInfo(crashReportSection, chunkInfo.blockView, blockPos, blockState);
|
||||
throw new CrashException(crashReport);
|
||||
}
|
||||
|
||||
// false because we've already marked the chunk as populated - caller doesn't need to
|
||||
|
|
|
@ -30,8 +30,10 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessAmbientOcc
|
|||
|
||||
@Mixin(targets = "net.minecraft.client.render.block.BlockModelRenderer$AmbientOcclusionCalculator")
|
||||
public abstract class MixinAmbientOcclusionCalculator implements AccessAmbientOcclusionCalculator {
|
||||
@Shadow private float[] brightness;
|
||||
@Shadow private int[] light;
|
||||
@Shadow
|
||||
private float[] brightness;
|
||||
@Shadow
|
||||
private int[] light;
|
||||
|
||||
@Shadow
|
||||
public abstract void apply(BlockRenderView blockRenderView, BlockState blockState, BlockPos pos, Direction face, float[] aoData, BitSet controlBits, boolean shade);
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Random;
|
|||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
@ -42,15 +43,16 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderContext
|
|||
|
||||
@Mixin(BlockModelRenderer.class)
|
||||
public abstract class MixinBlockModelRenderer implements AccessBlockModelRenderer {
|
||||
@Unique
|
||||
private final ThreadLocal<BlockRenderContext> fabric_contexts = ThreadLocal.withInitial(BlockRenderContext::new);
|
||||
|
||||
@Shadow
|
||||
protected abstract void getQuadDimensions(BlockRenderView blockView, BlockState blockState, BlockPos blockPos, int[] vertexData, Direction face, float[] aoData, BitSet controlBits);
|
||||
|
||||
private final ThreadLocal<BlockRenderContext> CONTEXTS = ThreadLocal.withInitial(BlockRenderContext::new);
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/render/model/BakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;ZLjava/util/Random;JI)Z", cancellable = true)
|
||||
private void hookRender(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrix, VertexConsumer buffer, boolean checkSides, Random rand, long seed, int overlay, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (!((FabricBakedModel) model).isVanillaAdapter()) {
|
||||
BlockRenderContext context = CONTEXTS.get();
|
||||
BlockRenderContext context = fabric_contexts.get();
|
||||
// Note that we do not support face-culling here (so checkSides is ignored)
|
||||
ci.setReturnValue(context.render(blockView, model, state, pos, matrix, buffer, rand, seed, overlay));
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.chunk.BlockBufferBuilderStorage;
|
||||
|
@ -64,14 +63,14 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.TerrainRenderConte
|
|||
* (Though they can use these as an example if they wish.)
|
||||
*/
|
||||
@Mixin(targets = "net.minecraft.client.render.chunk.ChunkBuilder$BuiltChunk$RebuildTask")
|
||||
public class MixinChunkRebuildTask {
|
||||
public abstract class MixinChunkRebuildTask {
|
||||
@Shadow
|
||||
protected ChunkRendererRegion region;
|
||||
@Shadow
|
||||
protected BuiltChunk field_20839;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "Lnet/minecraft/client/render/chunk/ChunkBuilder$BuiltChunk$RebuildTask;render(FFFLnet/minecraft/client/render/chunk/ChunkBuilder$ChunkData;Lnet/minecraft/client/render/chunk/BlockBufferBuilderStorage;)Ljava/util/Set;")
|
||||
private void hookChunkBuild(float float_1, float float_2, float float_3, ChunkBuilder.ChunkData renderData, BlockBufferBuilderStorage builder, CallbackInfoReturnable<Set<BlockEntity>> ci) {
|
||||
private void hookChunkBuild(float cameraX, float cameraY, float cameraZ, ChunkBuilder.ChunkData renderData, BlockBufferBuilderStorage builder, CallbackInfoReturnable<Set<BlockEntity>> ci) {
|
||||
ChunkRendererRegion region = this.region;
|
||||
|
||||
if (region != null) {
|
||||
|
@ -85,14 +84,14 @@ public class MixinChunkRebuildTask {
|
|||
* This is the hook that actually implements the rendering API for terrain rendering.
|
||||
*
|
||||
* <p>It's unusual to have a @Redirect in a Fabric library, but in this case
|
||||
* it is our explicit intention that {@link BlockRenderManager#tesselateBlock(BlockState, BlockPos, BlockRenderView, BufferBuilder, Random)}
|
||||
* it is our explicit intention that {@link BlockRenderManager#renderBlock(BlockState, BlockPos, BlockRenderView, MatrixStack, VertexConsumer, boolean, Random)}
|
||||
* does not execute for models that will be rendered by our renderer.
|
||||
*
|
||||
* <p>Any mod that wants to redirect this specific call is likely also a renderer, in which case this
|
||||
* renderer should not be present, or the mod should probably instead be relying on the renderer API
|
||||
* which was specifically created to provide for enhanced terrain rendering.
|
||||
*
|
||||
* <p>Note also that {@link BlockRenderManager#tesselateBlock(BlockState, BlockPos, BlockRenderView, BufferBuilder, Random)}
|
||||
* <p>Note also that {@link BlockRenderManager#renderBlock(BlockState, BlockPos, BlockRenderView, MatrixStack, VertexConsumer, boolean, Random)}
|
||||
* IS called if the block render type is something other than {@link BlockRenderType#MODEL}.
|
||||
* Normally this does nothing but will allow mods to create rendering hooks that are
|
||||
* driven off of render type. (Not recommended or encouraged, but also not prevented.)
|
||||
|
@ -106,7 +105,7 @@ public class MixinChunkRebuildTask {
|
|||
if (Indigo.ALWAYS_TESSELATE_INDIGO || !((FabricBakedModel) model).isVanillaAdapter()) {
|
||||
Vec3d vec3d = blockState.getModelOffset(blockView, blockPos);
|
||||
matrix.translate(vec3d.x, vec3d.y, vec3d.z);
|
||||
return ((AccessChunkRendererRegion) blockView).fabric_getRenderer().tesselateBlock(blockState, blockPos, model, matrix);
|
||||
return ((AccessChunkRendererRegion) blockView).fabric_getRenderer().tessellateBlock(blockState, blockPos, model, matrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import net.minecraft.client.render.chunk.ChunkBuilder.ChunkData;
|
|||
import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessChunkRendererData;
|
||||
|
||||
@Mixin(ChunkData.class)
|
||||
public class MixinChunkRenderData implements AccessChunkRendererData {
|
||||
public abstract class MixinChunkRenderData implements AccessChunkRendererData {
|
||||
@Shadow
|
||||
private Set<RenderLayer> initializedLayers;
|
||||
@Shadow
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package net.fabricmc.fabric.mixin.client.indigo.renderer;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import net.minecraft.client.render.chunk.ChunkRendererRegion;
|
||||
|
||||
|
@ -25,6 +26,7 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.TerrainRenderConte
|
|||
|
||||
@Mixin(ChunkRendererRegion.class)
|
||||
public abstract class MixinChunkRendererRegion implements AccessChunkRendererRegion {
|
||||
@Unique
|
||||
private TerrainRenderContext fabric_renderer;
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ package net.fabricmc.fabric.mixin.client.indigo.renderer;
|
|||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
@ -32,29 +33,29 @@ import net.minecraft.client.util.math.MatrixStack;
|
|||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.render.ItemRenderContext;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.render.ItemRenderContext.VanillaQuadHandler;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessItemRenderer;
|
||||
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 MixinItemRenderer implements AccessItemRenderer {
|
||||
@Shadow
|
||||
protected abstract void renderBakedItemModel(BakedModel model, ItemStack stack, int light, int overlay, MatrixStack matrixStack, VertexConsumer buffer);
|
||||
|
||||
@Shadow
|
||||
protected ItemColors colors;
|
||||
|
||||
private final VanillaQuadHandler vanillaHandler = new IndigoQuadHandler(this);
|
||||
@Unique
|
||||
private final ThreadLocal<ItemRenderContext> fabric_contexts = ThreadLocal.withInitial(() -> new ItemRenderContext(colors));
|
||||
|
||||
private final ThreadLocal<ItemRenderContext> CONTEXTS = ThreadLocal.withInitial(() -> new ItemRenderContext(colors));
|
||||
@Unique
|
||||
private final VanillaQuadHandler fabric_vanillaHandler = new IndigoQuadHandler(this);
|
||||
|
||||
@Shadow
|
||||
protected abstract void renderBakedItemModel(BakedModel model, ItemStack stack, int light, int overlay, MatrixStack matrixStack, VertexConsumer buffer);
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformation$Mode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", cancellable = true)
|
||||
public void hook_method_23179(ItemStack stack, ModelTransformation.Mode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, CallbackInfo ci) {
|
||||
final FabricBakedModel fabricModel = (FabricBakedModel) model;
|
||||
|
||||
if (!(stack.isEmpty() || fabricModel.isVanillaAdapter())) {
|
||||
CONTEXTS.get().renderModel(stack, transformMode, invert, matrixStack, vertexConsumerProvider, light, overlay, fabricModel, vanillaHandler);
|
||||
public void hook_renderItem(ItemStack stack, ModelTransformation.Mode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, CallbackInfo ci) {
|
||||
if (!stack.isEmpty() && !((FabricBakedModel) model).isVanillaAdapter()) {
|
||||
fabric_contexts.get().renderModel(stack, transformMode, invert, matrixStack, vertexConsumerProvider, light, overlay, model, fabric_vanillaHandler);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue