From 099c1e8b8c8d4cace0bc64db17405b0ca719ba81 Mon Sep 17 00:00:00 2001 From: grondag Date: Sun, 7 Jul 2019 23:14:07 +0200 Subject: [PATCH] Various Indigo Improvements (#295) - Fix #199 Vanilla Bug: Glowstone creates AO shade - Fix #289 Rendering on the Cutout and Transparent Layers together interferes with water rendering - Fix #290 Smooth lighting breaks on continuous angled surfaces - Fix #291 QuadEmitter not cleared on MeshBuilder.build() - Fix #292 Render context QuadEmitter crash with flat lighting - Fix #293 Relax vertex order requirements for modded quads - Fix swapped color components for grass and other blocks - Add option to partially support non-standard vertex formats --- fabric-renderer-api-v1/build.gradle | 2 +- fabric-renderer-indigo/build.gradle | 2 +- .../main/java/net/fabricmc/indigo/Indigo.java | 20 ++- .../indigo/IndigoMixinConfigPlugin.java | 44 ++++-- .../accessor/AccessBufferBuilder.java | 4 +- .../indigo/renderer/aocalc/AoCalculator.java | 85 ++++++------ .../indigo/renderer/aocalc/AoConfig.java | 3 +- .../indigo/renderer/aocalc/AoFaceData.java | 19 --- .../renderer/aocalc/AoLuminanceFix.java | 42 ++++++ .../helper/BufferBuilderTransformHelper.java | 120 ----------------- .../indigo/renderer/mesh/MeshBuilderImpl.java | 1 + .../renderer/mixin/MixinBufferBuilder.java | 127 +++++++++--------- .../renderer/render/AbstractMeshConsumer.java | 4 + .../renderer/render/AbstractQuadRenderer.java | 2 +- .../renderer/render/BlockRenderContext.java | 6 +- .../renderer/render/ChunkRenderInfo.java | 25 +++- .../renderer/render/ItemRenderContext.java | 5 +- .../render/TerrainFallbackConsumer.java | 22 ++- .../renderer/render/TerrainRenderContext.java | 4 - 19 files changed, 251 insertions(+), 286 deletions(-) create mode 100644 fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoLuminanceFix.java delete mode 100644 fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/helper/BufferBuilderTransformHelper.java diff --git a/fabric-renderer-api-v1/build.gradle b/fabric-renderer-api-v1/build.gradle index 87695a145..d718c7667 100644 --- a/fabric-renderer-api-v1/build.gradle +++ b/fabric-renderer-api-v1/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "fabric-renderer-api-v1" -version = getSubprojectVersion(project, "0.1.0") +version = getSubprojectVersion(project, "0.1.1") dependencies { compile project(path: ':fabric-api-base', configuration: 'dev') diff --git a/fabric-renderer-indigo/build.gradle b/fabric-renderer-indigo/build.gradle index 196927bb4..988c38735 100644 --- a/fabric-renderer-indigo/build.gradle +++ b/fabric-renderer-indigo/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "fabric-renderer-indigo" -version = getSubprojectVersion(project, "0.1.7") +version = getSubprojectVersion(project, "0.1.8") dependencies { compile project(path: ':fabric-api-base', configuration: 'dev') diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java index 0a982840d..c31b6a228 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java @@ -34,13 +34,15 @@ import java.util.Properties; public class Indigo implements ClientModInitializer { public static final boolean ALWAYS_TESSELATE_INDIGO; + public static final boolean ENSURE_VERTEX_FORMAT_COMPATIBILITY; public static final AoConfig AMBIENT_OCCLUSION_MODE; /** Set true in dev env to confirm results match vanilla when they should */ public static final boolean DEBUG_COMPARE_LIGHTING; public static final boolean FIX_SMOOTH_LIGHTING_OFFSET; public static final boolean FIX_EXTERIOR_VERTEX_LIGHTING; - - private static final Logger LOGGER = LogManager.getLogger(); + public static final boolean FIX_LUMINOUS_AO_SHADE; + + public static final Logger LOGGER = LogManager.getLogger(); private static boolean asBoolean(String property, boolean defValue) { switch (asTriState(property)) { @@ -53,7 +55,8 @@ public class Indigo implements ClientModInitializer { } } - private static T asEnum(String property, T defValue) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static T asEnum(String property, T defValue) { if (property == null || property.isEmpty()) { return defValue; } else { @@ -102,12 +105,16 @@ public class Indigo implements ClientModInitializer { } } - ALWAYS_TESSELATE_INDIGO = asBoolean((String) properties.computeIfAbsent("always-tesselate-blocks", (a) -> "auto"), true); + final boolean forceCompatibility = IndigoMixinConfigPlugin.shouldForceCompatibility(); + ENSURE_VERTEX_FORMAT_COMPATIBILITY = forceCompatibility; + // necessary because OF alters the BakedModel vertex format and will confuse the fallback model consumer + ALWAYS_TESSELATE_INDIGO = !forceCompatibility && asBoolean((String) properties.computeIfAbsent("always-tesselate-blocks", (a) -> "auto"), true); AMBIENT_OCCLUSION_MODE = asEnum((String) properties.computeIfAbsent("ambient-occlusion-mode", (a) -> "hybrid"), AoConfig.HYBRID); DEBUG_COMPARE_LIGHTING = asBoolean((String) properties.computeIfAbsent("debug-compare-lighting", (a) -> "auto"), false); FIX_SMOOTH_LIGHTING_OFFSET = asBoolean((String) properties.computeIfAbsent("fix-smooth-lighting-offset", (a) -> "auto"), true); FIX_EXTERIOR_VERTEX_LIGHTING = asBoolean((String) properties.computeIfAbsent("fix-exterior-vertex-lighting", (a) -> "auto"), true); - + FIX_LUMINOUS_AO_SHADE = asBoolean((String) properties.computeIfAbsent("fix-luminous-block-ambient-occlusion", (a) -> "auto"), false); + try (FileOutputStream stream = new FileOutputStream(configFile)) { properties.store(stream, "Indigo properties file"); } catch (IOException e) { @@ -119,6 +126,9 @@ public class Indigo implements ClientModInitializer { public void onInitializeClient() { if (IndigoMixinConfigPlugin.shouldApplyIndigo()) { LOGGER.info("[Indigo] Registering Indigo renderer!"); + if(IndigoMixinConfigPlugin.shouldForceCompatibility()) { + LOGGER.info("[Indigo] Compatibility mode enabled."); + } RendererAccess.INSTANCE.registerRenderer(IndigoRenderer.INSTANCE); } else { LOGGER.info("[Indigo] Different rendering plugin detected; not applying Indigo."); diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java index e875b296e..de8337017 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java @@ -18,6 +18,8 @@ package net.fabricmc.indigo; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.ModMetadata; + import org.spongepowered.asm.lib.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -26,23 +28,39 @@ import java.util.List; import java.util.Set; public class IndigoMixinConfigPlugin implements IMixinConfigPlugin { - private static final String JSON_ELEMENT = "fabric-renderer-api-v1:contains_renderer"; - private static Boolean indigoApplicable; + /** Set by other renderers to disable loading of Indigo */ + private static final String JSON_KEY_DISABLE_INDIGO = "fabric-renderer-api-v1:contains_renderer"; + /** Disables vanilla block tesselation and ensures vertex format compatibility */ + private static final String JSON_KEY_FORCE_COMPATIBILITY = "fabric-renderer-indigo:force_compatibility"; + + private static boolean needsLoad = true; + + private static boolean indigoApplicable = true; + private static boolean forceCompatibility = false; + private static void loadIfNeeded() { + if(needsLoad) { + for (ModContainer container : FabricLoader.getInstance().getAllMods()) { + final ModMetadata meta = container.getMetadata(); + if (meta.containsCustomElement(JSON_KEY_DISABLE_INDIGO)) { + indigoApplicable = false; + } else if (meta.containsCustomElement(JSON_KEY_FORCE_COMPATIBILITY)) { + forceCompatibility = true; + } + } + needsLoad = false; + } + } static boolean shouldApplyIndigo() { - if (indigoApplicable != null) return indigoApplicable; - - for (ModContainer container : FabricLoader.getInstance().getAllMods()) { - if (container.getMetadata().containsCustomElement(JSON_ELEMENT)) { - indigoApplicable = false; - return false; - } - } - - indigoApplicable = true; - return true; + loadIfNeeded(); + return indigoApplicable; } + static boolean shouldForceCompatibility() { + loadIfNeeded(); + return forceCompatibility; + } + @Override public void onLoad(String mixinPackage) { diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java index 82e8b5643..1554aa1b9 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java @@ -16,6 +16,8 @@ package net.fabricmc.indigo.renderer.accessor; +import net.fabricmc.indigo.renderer.mesh.QuadViewImpl; + public interface AccessBufferBuilder { - void fabric_putVanillaData(int[] data, int start, boolean isItemFormat); + void fabric_putQuad(QuadViewImpl quad); } diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java index cd5dba3d9..19f9169ac 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java @@ -112,31 +112,37 @@ public class AoCalculator { public void compute(MutableQuadViewImpl quad, boolean isVanilla) { final AoConfig config = Indigo.AMBIENT_OCCLUSION_MODE; - boolean shouldMatch = false; + final boolean shouldCompare; switch(config) { case VANILLA: calcVanilla(quad); + // no point in comparing vanilla with itself + shouldCompare = false; break; case EMULATE: calcFastVanilla(quad); - shouldMatch = Indigo.DEBUG_COMPARE_LIGHTING && isVanilla; + shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING && isVanilla; break; + default: case HYBRID: if(isVanilla) { + shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING; calcFastVanilla(quad); - break; + } else { + shouldCompare = false; + calcEnhanced(quad); } - // else fall through to enhanced + break; - default: case ENHANCED: - shouldMatch = calcEnhanced(quad); + shouldCompare = false; + calcEnhanced(quad); } - if (shouldMatch) { + if (shouldCompare) { float[] vanillaAo = new float[4]; int[] vanillaLight = new int[4]; @@ -178,28 +184,21 @@ public class AoCalculator { } } - /** returns true if should match vanilla results */ - private boolean calcEnhanced(MutableQuadViewImpl quad) { + private void calcEnhanced(MutableQuadViewImpl quad) { switch(quad.geometryFlags()) { case AXIS_ALIGNED_FLAG | CUBIC_FLAG | LIGHT_FACE_FLAG: - vanillaFullFace(quad, true); - return Indigo.DEBUG_COMPARE_LIGHTING; - case AXIS_ALIGNED_FLAG | LIGHT_FACE_FLAG: vanillaPartialFace(quad, true); - return Indigo.DEBUG_COMPARE_LIGHTING; + break; case AXIS_ALIGNED_FLAG | CUBIC_FLAG: - blendedFullFace(quad); - return false; - case AXIS_ALIGNED_FLAG: blendedPartialFace(quad); - return false; + break; default: irregularFace(quad); - return false; + break; } } @@ -246,11 +245,6 @@ public class AoCalculator { } } - private void blendedFullFace(QuadViewImpl quad) { - final Direction lightFace = quad.lightFace(); - blendedInsetFace(quad, 0, lightFace).toArray(ao, light, VERTEX_MAP[lightFace.getId()]); - } - private void blendedPartialFace(QuadViewImpl quad) { final Direction lightFace = quad.lightFace(); AoFaceData faceData = blendedInsetFace(quad, 0, lightFace); @@ -283,12 +277,15 @@ public class AoCalculator { final AoFaceData fd = gatherInsetFace(quad, i, face); AoFace.get(face).weightFunc.apply(quad, i, w); final float n = x * x; - ao += n * fd.weigtedAo(w); - sky += n * fd.weigtedSkyLight(w); - block += n * fd.weigtedBlockLight(w); - maxAo = fd.maxAo(maxAo); - maxSky = fd.maxSkyLight(maxSky); - maxBlock = fd.maxBlockLight(maxBlock); + final float a = fd.weigtedAo(w); + final int s = fd.weigtedSkyLight(w); + final int b = fd.weigtedBlockLight(w); + ao += n * a; + sky += n * s; + block += n * b; + maxAo = a; + maxSky = s; + maxBlock = b; } final float y = normal.y(); @@ -297,12 +294,15 @@ public class AoCalculator { final AoFaceData fd = gatherInsetFace(quad, i, face); AoFace.get(face).weightFunc.apply(quad, i, w); final float n = y * y; - ao += n * fd.weigtedAo(w); - sky += n * fd.weigtedSkyLight(w); - block += n * fd.weigtedBlockLight(w); - maxAo = fd.maxAo(maxAo); - maxSky = fd.maxSkyLight(maxSky); - maxBlock = fd.maxBlockLight(maxBlock); + final float a = fd.weigtedAo(w); + final int s = fd.weigtedSkyLight(w); + final int b = fd.weigtedBlockLight(w); + ao += n * a; + sky += n * s; + block += n * b; + maxAo = Math.max(maxAo, a); + maxSky = Math.max(maxSky, s); + maxBlock = Math.max(maxBlock, b); } final float z = normal.z(); @@ -311,12 +311,15 @@ public class AoCalculator { final AoFaceData fd = gatherInsetFace(quad, i, face); AoFace.get(face).weightFunc.apply(quad, i, w); final float n = z * z; - ao += n * fd.weigtedAo(w); - sky += n * fd.weigtedSkyLight(w); - block += n * fd.weigtedBlockLight(w); - maxAo = fd.maxAo(maxAo); - maxSky = fd.maxSkyLight(maxSky); - maxBlock = fd.maxBlockLight(maxBlock); + final float a = fd.weigtedAo(w); + final int s = fd.weigtedSkyLight(w); + final int b = fd.weigtedBlockLight(w); + ao += n * a; + sky += n * s; + block += n * b; + maxAo = Math.max(maxAo, a); + maxSky = Math.max(maxSky, s); + maxBlock = Math.max(maxBlock, b); } aoResult[i] = (ao + maxAo) * 0.5f; diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java index 1b41b5152..cc5155f0b 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java @@ -36,8 +36,7 @@ public enum AoConfig { * aligned quads not on the block face will have interpolated brightness based * on depth instead of the all-or-nothing brightness of vanilla.

* - * Unit (full face) quads must still have the vanilla fixed winding order but smaller - * quads can have vertices in any (counter-clockwise) order.

+ * Non-vanilla quads can have vertices in any (counter-clockwise) order.

*/ ENHANCED, diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java index a39a716c8..d19273b4e 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java @@ -58,22 +58,10 @@ class AoFaceData { return (int) (b0 * w[0] + b1 * w[1] + b2 * w[2] + b3 * w[3]) & 0xFF; } - int maxBlockLight(int oldMax) { - final int i = b0 > b1 ? b0 : b1; - final int j = b2 > b3 ? b2 : b3; - return Math.max(oldMax, i > j ? i : j); - } - int weigtedSkyLight(float[] w) { return (int) (s0 * w[0] + s1 * w[1] + s2 * w[2] + s3 * w[3]) & 0xFF; } - int maxSkyLight(int oldMax) { - final int i = s0 > s1 ? s0 : s1; - final int j = s2 > s3 ? s2 : s3; - return Math.max(oldMax, i > j ? i : j); - } - int weightedCombinedLight(float[] w) { return weigtedSkyLight(w) << 16 | weigtedBlockLight(w); } @@ -82,13 +70,6 @@ class AoFaceData { return a0 * w[0] + a1 * w[1] + a2 * w[2] + a3 * w[3]; } - float maxAo(float oldMax) { - final float x = a0 > a1 ? a0 : a1; - final float y = a2 > a3 ? a2 : a3; - final float z = x > y ? x : y; - return oldMax > z ? oldMax : z; - } - void toArray(float[] aOut, int[] bOut, int[] vertexMap) { aOut[vertexMap[0]] = a0; aOut[vertexMap[1]] = a1; diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoLuminanceFix.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoLuminanceFix.java new file mode 100644 index 000000000..69b4634d6 --- /dev/null +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoLuminanceFix.java @@ -0,0 +1,42 @@ +/* + * 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.indigo.renderer.aocalc; + +import net.fabricmc.indigo.Indigo; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; + +/** + * Implements a fix to prevent luminous blocks from casting AO shade. + * Will give normal result if fix is disabled. + */ +@FunctionalInterface +public interface AoLuminanceFix { + float apply(BlockView view, BlockPos pos); + + AoLuminanceFix INSTANCE = Indigo.FIX_LUMINOUS_AO_SHADE ? AoLuminanceFix::fixed : AoLuminanceFix::vanilla; + + static float vanilla(BlockView view, BlockPos pos) { + return view.getBlockState(pos).getAmbientOcclusionLightLevel(view, pos); + } + + static float fixed(BlockView view, BlockPos pos) { + final BlockState state = view.getBlockState(pos); + return state.getLuminance() == 0 ? state.getAmbientOcclusionLightLevel(view, pos) : 1f; + } +} diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/helper/BufferBuilderTransformHelper.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/helper/BufferBuilderTransformHelper.java deleted file mode 100644 index 8102a77c4..000000000 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/helper/BufferBuilderTransformHelper.java +++ /dev/null @@ -1,120 +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.indigo.renderer.helper; - -import com.google.common.collect.Sets; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import net.minecraft.client.render.VertexFormat; -import net.minecraft.client.render.VertexFormatElement; -import net.minecraft.client.render.VertexFormats; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class BufferBuilderTransformHelper { - /** - * Fast copying mode; used only if the vanilla format is an exact match. - */ - public static final int MODE_COPY_FAST = 0; - - /** - * Padded copying mode; used when the vanilla format is an exact match, - * but includes additional data at the end. Will emit a warning. - */ - public static final int MODE_COPY_PADDED = 1; - - /** - * ShadersMod compatibility mode; as MODE_COPY_PADDED, but populates in - * the correct normal values as provided by the mod. - * - * Assumes a format of [vertex, color, texture, lmap, normal], all in - * their respective vanilla formats, plus any amount of additional data - * afterwards. - */ - public static final int MODE_COPY_PADDED_SHADERSMOD = 2; - - /** - * Unsupported mode; an error will be emitted and no quads will be - * pushed to the buffer builder. - */ - public static final int MODE_UNSUPPORTED = 3; - - private static final Map vertexFormatCache = new ConcurrentHashMap<>(); - private static final Set errorEmittedFormats = Sets.newConcurrentHashSet(); - private static final Logger logger = LogManager.getLogger(); - - public static void emitUnsupportedError(VertexFormat format) { - // This can be slow, as it's only called on unsupported formats - which is already an error condition. - if (errorEmittedFormats.add(format)) { - logger.error("[Indigo] Unsupported vertex format! " + format); - } - } - - private static int computeProcessingMode(VertexFormat f) { - if ( - f.getElementCount() >= 4 && f.getVertexSizeInteger() >= 7 - && f.getElement(0).equals(VertexFormats.POSITION_ELEMENT) - && f.getElement(1).equals(VertexFormats.COLOR_ELEMENT) - && f.getElement(2).equals(VertexFormats.UV_ELEMENT) - ) { - if ( - f.getElement(3).equals(VertexFormats.LMAP_ELEMENT) - || f.getElement(3).equals(VertexFormats.NORMAL_ELEMENT) - ) { - if ( - f.getElementCount() >= 5 - && f.getElement(3).equals(VertexFormats.LMAP_ELEMENT) - && f.getElement(4).equals(VertexFormats.NORMAL_ELEMENT) - ) { - logger.debug("[Indigo] Classified format as ShadersMod-compatible: " + f); - return MODE_COPY_PADDED_SHADERSMOD; - } else if (f.getElementCount() == 4) { - logger.debug("[Indigo] Classified format as vanilla-like: " + f); - return MODE_COPY_FAST; - } else { - logger.debug("[Indigo] Unsupported but likely vanilla-compliant vertex format. " + f); - return MODE_COPY_PADDED; - } - } - } - - return MODE_UNSUPPORTED; - } - - public static int getProcessingMode(VertexFormat format) { - // Fast passthrough for the most common vanilla block/item formats. - if (format == VertexFormats.POSITION_COLOR_UV_LMAP || format == VertexFormats.POSITION_COLOR_UV_NORMAL) { - return MODE_COPY_FAST; - } else { - Integer cached = vertexFormatCache.get(format); - - if (cached == null) { - // VertexFormats are mutable, so we need to make an immutable copy. - format = new VertexFormat(format); - cached = computeProcessingMode(format); - vertexFormatCache.put(format, cached); - } - - return cached; - } - } -} diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java index a3f8c82e4..1ad88977e 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java @@ -50,6 +50,7 @@ public class MeshBuilderImpl implements MeshBuilder { int[] packed = new int[index]; System.arraycopy(data, 0, packed, 0, index); index = 0; + maker.begin(data, index); return new MeshImpl(packed); } diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java index cc25fd06d..da1e9a4af 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java @@ -18,18 +18,15 @@ package net.fabricmc.indigo.renderer.mixin; import java.nio.IntBuffer; -import net.fabricmc.indigo.Indigo; -import net.fabricmc.indigo.renderer.helper.BufferBuilderTransformHelper; -import net.fabricmc.indigo.renderer.mesh.EncodingFormat; -import net.minecraft.client.render.VertexFormat; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import net.fabricmc.indigo.Indigo; import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder; +import net.fabricmc.indigo.renderer.mesh.QuadViewImpl; import net.minecraft.client.render.BufferBuilder; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import net.minecraft.client.render.VertexFormat; +import net.minecraft.client.render.VertexFormatElement; @Mixin(BufferBuilder.class) public abstract class MixinBufferBuilder implements AccessBufferBuilder { @@ -40,73 +37,71 @@ public abstract class MixinBufferBuilder implements AccessBufferBuilder { @Shadow public abstract VertexFormat getVertexFormat(); private static final int VERTEX_STRIDE_INTS = 7; - private static final int VERTEX_STRIDE_BYTES = VERTEX_STRIDE_INTS * 4; private static final int QUAD_STRIDE_INTS = VERTEX_STRIDE_INTS * 4; private static final int QUAD_STRIDE_BYTES = QUAD_STRIDE_INTS * 4; - private int fabric_processingMode; + @Override + public void fabric_putQuad(QuadViewImpl quad) { + if(Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY) { + bufferCompatibly(quad); + } else { + bufferFast(quad); + } + } - @Inject(at = @At("RETURN"), method = "begin") - private void afterBegin(int mode, VertexFormat passedFormat, CallbackInfo info) { - fabric_processingMode = BufferBuilderTransformHelper.getProcessingMode(getVertexFormat()); - } + private void bufferFast(QuadViewImpl quad) { + grow(QUAD_STRIDE_BYTES); + bufInt.position(getCurrentSize()); + bufInt.put(quad.data(), quad.vertexStart(), QUAD_STRIDE_INTS); + vertexCount += 4; + } /** - * Similar to {@link BufferBuilder#putVertexData(int[])} but - * accepts an array index so that arrays containing more than one - * quad don't have to be copied to a transfer array before the call. - * - * It also always assumes the vanilla data format and is capable of - * transforming data from it to a different, non-vanilla data format. + * Uses buffer vertex format to drive buffer population. + * Relies on logic elsewhere to ensure coordinates don't include chunk offset + * (because buffer builder will handle that.)

+ * + * Calling putVertexData() would likely be a little faster but this approach + * gives us a chance to pass vertex normals to shaders, which isn't possible + * with the standard block format. It also doesn't require us to encode a specific + * custom format directly, which would be prone to breakage outside our control. */ - @Override - public void fabric_putVanillaData(int[] data, int start, boolean isItemFormat) { - switch (fabric_processingMode) { - case BufferBuilderTransformHelper.MODE_COPY_FAST: { - this.grow(QUAD_STRIDE_BYTES); - this.bufInt.position(this.getCurrentSize()); - this.bufInt.put(data, start, QUAD_STRIDE_INTS); - } break; - case BufferBuilderTransformHelper.MODE_COPY_PADDED: { - int currSize = this.getCurrentSize(); - int formatSizeBytes = getVertexFormat().getVertexSize(); - int formatSizeInts = formatSizeBytes / 4; - this.grow(formatSizeBytes * 4); + private void bufferCompatibly(QuadViewImpl quad) { + final VertexFormat format = getVertexFormat();; + final int elementCount = format.getElementCount(); + for(int i = 0; i < 4; i++) { + for(int j = 0; j < elementCount; j++) { + VertexFormatElement e = format.getElement(j); + switch(e.getType()) { + case COLOR: + final int c = quad.spriteColor(i, 0); + ((BufferBuilder)(Object)this).color(c & 0xFF, (c >>> 8) & 0xFF, (c >>> 16) & 0xFF, (c >>> 24) & 0xFF); + break; + case NORMAL: + ((BufferBuilder)(Object)this).normal(quad.normalX(i), quad.normalY(i), quad.normalZ(i)); + break; + case POSITION: + ((BufferBuilder)(Object)this).vertex(quad.x(i), quad.y(i), quad.z(i)); + break; + case UV: + if(e.getIndex() == 0) { + ((BufferBuilder)(Object)this).texture(quad.spriteU(i, 0), quad.spriteV(i, 0)); + } else { + final int b = quad.lightmap(i); + ((BufferBuilder)(Object)this).texture((b >> 16) & 0xFFFF, b & 0xFFFF); + } + break; - this.bufInt.position(currSize); - this.bufInt.put(data, start, VERTEX_STRIDE_INTS); - this.bufInt.position(currSize + formatSizeInts); - this.bufInt.put(data, start + 7, VERTEX_STRIDE_INTS); - this.bufInt.position(currSize + formatSizeInts * 2); - this.bufInt.put(data, start + 14, VERTEX_STRIDE_INTS); - this.bufInt.position(currSize + formatSizeInts * 3); - this.bufInt.put(data, start + 21, VERTEX_STRIDE_INTS); - } break; - case BufferBuilderTransformHelper.MODE_COPY_PADDED_SHADERSMOD: { - int currSize = this.getCurrentSize(); - int formatSizeBytes = getVertexFormat().getVertexSize(); - int formatSizeInts = formatSizeBytes / 4; - this.grow(formatSizeBytes * 4); + // these types should never occur and/or require no action + case MATRIX: + case BLEND_WEIGHT: + case PADDING: + default: + break; - this.bufInt.position(currSize); - this.bufInt.put(data, start, VERTEX_STRIDE_INTS); - this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA]); - this.bufInt.position(currSize + formatSizeInts); - this.bufInt.put(data, start + 7, VERTEX_STRIDE_INTS); - this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA + 1]); - this.bufInt.position(currSize + formatSizeInts * 2); - this.bufInt.put(data, start + 14, VERTEX_STRIDE_INTS); - this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA + 2]); - this.bufInt.position(currSize + formatSizeInts * 3); - this.bufInt.put(data, start + 21, VERTEX_STRIDE_INTS); - this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA + 3]); - } break; - case BufferBuilderTransformHelper.MODE_UNSUPPORTED: - // Don't emit any quads. - BufferBuilderTransformHelper.emitUnsupportedError(getVertexFormat()); - return; - } - - this.vertexCount += 4; + } + } + ((BufferBuilder)(Object)this).next(); + } } } diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java index 276f43808..1aadb2e7c 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java @@ -28,6 +28,8 @@ import net.fabricmc.indigo.renderer.RenderMaterialImpl.Value; import net.fabricmc.indigo.renderer.IndigoRenderer; import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder; import net.fabricmc.indigo.renderer.aocalc.AoCalculator; +import net.fabricmc.indigo.renderer.helper.ColorHelper; +import net.fabricmc.indigo.renderer.helper.GeometryHelper; import net.fabricmc.indigo.renderer.mesh.EncodingFormat; import net.fabricmc.indigo.renderer.mesh.MeshImpl; import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl; @@ -57,6 +59,8 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen // only used via RenderContext.getEmitter() @Override public Maker emit() { + lightFace = GeometryHelper.lightFace(this); + ColorHelper.applyDiffuseShading(this, false); renderQuad(this); clear(); return this; diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java index 8c3ef17fa..7fa9e4dc0 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java @@ -69,7 +69,7 @@ public abstract class AbstractQuadRenderer { /** final output step, common to all renders */ private void bufferQuad(MutableQuadViewImpl quad, int renderLayer) { - bufferFunc.get(renderLayer).fabric_putVanillaData(quad.data(), quad.vertexStart(), false); + bufferFunc.get(renderLayer).fabric_putQuad(quad); } // routines below have a bit of copy-paste code reuse to avoid conditional execution inside a hot loop diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java index 5bb0d0275..b12f810ad 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java @@ -27,6 +27,7 @@ import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder; import net.fabricmc.indigo.renderer.aocalc.AoCalculator; +import net.fabricmc.indigo.renderer.aocalc.AoLuminanceFix; import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl; import net.fabricmc.indigo.renderer.mixin.BufferBuilderOffsetAccessor; import net.minecraft.block.BlockState; @@ -67,10 +68,7 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC private float aoLevel(BlockPos pos) { final ExtendedBlockView blockView = blockInfo.blockView; - if(blockView == null) { - return 1f; - } - return blockView.getBlockState(pos).getAmbientOcclusionLightLevel(blockView, pos); + return blockView == null ? 1f : AoLuminanceFix.INSTANCE.apply(blockView, pos); } private AccessBufferBuilder outputBuffer(int renderLayer) { diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java index 2ffa5951b..26e83c133 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java @@ -18,8 +18,10 @@ package net.fabricmc.indigo.renderer.render; import it.unimi.dsi.fastutil.longs.Long2FloatOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; +import net.fabricmc.indigo.Indigo; import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder; import net.fabricmc.indigo.renderer.accessor.AccessChunkRenderer; +import net.fabricmc.indigo.renderer.aocalc.AoLuminanceFix; import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl; import net.minecraft.block.Block.OffsetType; import net.minecraft.block.BlockRenderLayer; @@ -67,6 +69,7 @@ public class ChunkRenderInfo { private final Long2FloatOpenHashMap aoLevelCache; private final BlockRenderInfo blockInfo; + private final BlockPos.Mutable chunkOrigin = new BlockPos.Mutable(); ChunkRenderTask chunkTask; ChunkRenderData chunkData; ChunkRenderer chunkRenderer; @@ -102,6 +105,7 @@ public class ChunkRenderInfo { } void prepare(ChunkRenderer chunkRenderer, BlockPos.Mutable chunkOrigin, boolean [] resultFlags) { + this.chunkOrigin.set(chunkOrigin); this.chunkData = chunkTask.getRenderData(); this.chunkRenderer = chunkRenderer; this.resultFlags = resultFlags; @@ -129,10 +133,19 @@ public class ChunkRenderInfo { void beginBlock() { final BlockState blockState = blockInfo.blockState; final BlockPos blockPos = blockInfo.blockPos; - offsetX = (float) (chunkOffsetX + blockPos.getX()); - offsetY = (float) (chunkOffsetY + blockPos.getY()); - offsetZ = (float) (chunkOffsetZ + blockPos.getZ()); - + + // When we are using the BufferBuilder input methods, the builder will + // add the chunk offset for us, so we should only apply the block offset. + if(Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY) { + offsetX = (float) (blockPos.getX()); + offsetY = (float) (blockPos.getY()); + offsetZ = (float) (blockPos.getZ()); + } else { + offsetX = (float) (chunkOffsetX + blockPos.getX()); + offsetY = (float) (chunkOffsetY + blockPos.getY()); + offsetZ = (float) (chunkOffsetZ + blockPos.getZ()); + } + if(blockState.getBlock().getOffsetType() != OffsetType.NONE) { Vec3d offset = blockState.getOffsetPos(blockInfo.blockView, blockPos); offsetX += (float)offset.x; @@ -153,7 +166,7 @@ public class ChunkRenderInfo { BlockRenderLayer layer = LAYERS[layerIndex]; if (!chunkData.isBufferInitialized(layer)) { chunkData.markBufferInitialized(layer); // start buffer - ((AccessChunkRenderer) chunkRenderer).fabric_beginBufferBuilding(builder, blockInfo.blockPos); + ((AccessChunkRenderer) chunkRenderer).fabric_beginBufferBuilding(builder, chunkOrigin); } result = (AccessBufferBuilder) builder; } @@ -188,7 +201,7 @@ public class ChunkRenderInfo { long key = pos.asLong(); float result = aoLevelCache.get(key); if (result == Float.MAX_VALUE) { - result = blockView.getBlockState(pos).getAmbientOcclusionLightLevel(blockView, pos); + result = AoLuminanceFix.INSTANCE.apply(blockView, pos); aoLevelCache.put(key, result); } return result; diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java index feeadd75e..1d6709cec 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java @@ -33,6 +33,7 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.fabricmc.indigo.renderer.RenderMaterialImpl; import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder; import net.fabricmc.indigo.renderer.helper.ColorHelper; +import net.fabricmc.indigo.renderer.helper.GeometryHelper; import net.fabricmc.indigo.renderer.mesh.EncodingFormat; import net.fabricmc.indigo.renderer.mesh.MeshImpl; import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl; @@ -127,6 +128,8 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo @Override public Maker emit() { + lightFace = GeometryHelper.lightFace(this); + ColorHelper.applyDiffuseShading(this, false); renderQuad(); clear(); return this; @@ -182,7 +185,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo c = ColorHelper.multiplyColor(quadColor, c); q.spriteColor(i, 0, ColorHelper.swapRedBlueIfNeeded(c)); } - fabricBuffer.fabric_putVanillaData(quadData, EncodingFormat.VERTEX_START_OFFSET, true); + fabricBuffer.fabric_putQuad(q); } private void renderQuad() { diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java index afb08c7cb..55e51811c 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java @@ -25,6 +25,7 @@ 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.QuadTransform; import net.fabricmc.indigo.renderer.RenderMaterialImpl.Value; +import net.fabricmc.indigo.Indigo; import net.fabricmc.indigo.renderer.IndigoRenderer; import net.fabricmc.indigo.renderer.aocalc.AoCalculator; import net.fabricmc.indigo.renderer.helper.GeometryHelper; @@ -58,6 +59,20 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con private static Value MATERIAL_FLAT = (Value) IndigoRenderer.INSTANCE.materialFinder().disableAo(0, true).find(); private static Value MATERIAL_SHADED = (Value) IndigoRenderer.INSTANCE.materialFinder().find(); + /** + * Controls 1x warning for vanilla quad vertex format when running in compatibility mode. + */ + private static boolean logCompatibilityWarning = true; + + private static boolean isCompatible(int[] vertexData) { + final boolean result = vertexData.length == 28; + 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; + } + private final int[] editorBuffer = new int[28]; private final ChunkRenderInfo chunkInfo; @@ -109,8 +124,13 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con } private void renderQuad(BakedQuad quad, Direction cullFace, Value defaultMaterial) { + final int[] vertexData = quad.getVertexData(); + if(Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY && !isCompatible(vertexData)) { + return; + } + final MutableQuadViewImpl editorQuad = this.editorQuad; - System.arraycopy(quad.getVertexData(), 0, editorBuffer, 0, 28); + System.arraycopy(vertexData, 0, editorBuffer, 0, 28); editorQuad.cullFace(cullFace); final Direction lightFace = quad.getFace(); editorQuad.lightFace(lightFace); diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java index a71f3df3f..e98fee10c 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java @@ -24,8 +24,6 @@ import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.fabricmc.indigo.renderer.aocalc.AoCalculator; import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.block.BlockRenderManager; import net.minecraft.client.render.chunk.ChunkRenderTask; import net.minecraft.client.render.chunk.ChunkRenderer; import net.minecraft.client.render.chunk.ChunkRendererRegion; @@ -34,7 +32,6 @@ 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.world.ExtendedBlockView; /** * Implementation of {@link RenderContext} used during terrain rendering. @@ -48,7 +45,6 @@ public class TerrainRenderContext extends AbstractRenderContext implements Rende private final AoCalculator aoCalc = new AoCalculator(blockInfo, chunkInfo::cachedBrightness, chunkInfo::cachedAoLevel); private final TerrainMeshConsumer meshConsumer = new TerrainMeshConsumer(blockInfo, chunkInfo, aoCalc, this::transform); private final TerrainFallbackConsumer fallbackConsumer = new TerrainFallbackConsumer(blockInfo, chunkInfo, aoCalc, this::transform); - private final BlockRenderManager blockRenderManager = MinecraftClient.getInstance().getBlockRenderManager(); public void setBlockView(ChunkRendererRegion blockView) { blockInfo.setBlockView(blockView);