From bf4864981b91d5b9d1019528aff33b3e85d80e47 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+peppercode1@users.noreply.github.com> Date: Thu, 23 Feb 2023 10:13:38 +0000 Subject: [PATCH] Indigo shade related fixes and other changes (#2898) * Apply disabled shade from vanilla quads directly to material - Remove QuadViewImpl.shade * Fix enhanced AO calculation and respect non-terrain culling state - Fix AoCalculator using AO face data computed with a potentially different shade state - Move non-cached computation code to separate method in AoCalculator - Turn AoCalculator's brightnessFunc and aoFunc into abstract methods - Do not check null check world in non-terrain AO calculation since it cannot be null - Pass through lightFace and shade state as method arguments in AoCalculator methods to prevent additional lookups - Do not check for the axis aligned flag in AbstractQuadRenderer.shadeFlatQuad - Respect cull parameter passed to non-terrain rendering by merging TerrainBlockRenderInfo into BlockRenderInfo - Use reusable search pos when calling Block.shouldDrawSide to prevent additional BlockPos allocation - Change BlockRenderContext.render and TerrainRenderContext.tessellateBlock to return void since return value is no longer used - Remove QuadViewImpl.vertexStart since it is unused * Add suggestions - Mark Direction parameter to BlockRenderInfo.shouldDrawFace as Nullable - Reuse MaterialFinder in FrameBakedModel (cherry picked from commit 3a95925af4ebaa352fcf631b9b3e6f99b14062b3) (cherry picked from commit 1adbf277eefc4a542d67acca3e94aea3b3f0e6ef) --- .../simple/client/FrameBakedModel.java | 9 +- .../indigo/renderer/RenderMaterialImpl.java | 8 + .../indigo/renderer/aocalc/AoCalculator.java | 391 +++++++++--------- .../renderer/mesh/MutableQuadViewImpl.java | 7 +- .../indigo/renderer/mesh/QuadViewImpl.java | 12 +- .../renderer/render/AbstractQuadRenderer.java | 7 +- .../renderer/render/BlockRenderContext.java | 36 +- .../renderer/render/BlockRenderInfo.java | 39 +- .../render/TerrainBlockRenderInfo.java | 56 --- .../render/TerrainFallbackConsumer.java | 1 - .../renderer/render/TerrainRenderContext.java | 20 +- .../renderer/MixinBlockModelRenderer.java | 6 +- 12 files changed, 275 insertions(+), 317 deletions(-) delete mode 100644 fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainBlockRenderInfo.java diff --git a/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/simple/client/FrameBakedModel.java b/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/simple/client/FrameBakedModel.java index 58c7a6cf3..e96b77588 100644 --- a/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/simple/client/FrameBakedModel.java +++ b/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/simple/client/FrameBakedModel.java @@ -37,9 +37,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; -import net.fabricmc.fabric.api.renderer.v1.Renderer; import net.fabricmc.fabric.api.renderer.v1.RendererAccess; import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; +import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; @@ -57,9 +57,10 @@ final class FrameBakedModel implements BakedModel, FabricBakedModel { this.frameMesh = frameMesh; this.frameSprite = frameSprite; - Renderer renderer = RendererAccess.INSTANCE.getRenderer(); - this.translucentMaterial = renderer.materialFinder().blendMode(0, BlendMode.TRANSLUCENT).find(); - this.translucentEmissiveMaterial = renderer.materialFinder().blendMode(0, BlendMode.TRANSLUCENT).emissive(0, true).find(); + MaterialFinder finder = RendererAccess.INSTANCE.getRenderer().materialFinder(); + this.translucentMaterial = finder.blendMode(0, BlendMode.TRANSLUCENT).find(); + finder.clear(); + this.translucentEmissiveMaterial = finder.blendMode(0, BlendMode.TRANSLUCENT).emissive(0, true).find(); } @Override diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/RenderMaterialImpl.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/RenderMaterialImpl.java index 0f5653045..4e86f40e0 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/RenderMaterialImpl.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/RenderMaterialImpl.java @@ -52,6 +52,14 @@ public abstract class RenderMaterialImpl { return VALUES[index]; } + public static Value setDisableDiffuse(Value material, int textureIndex, boolean disable) { + if (material.disableDiffuse(textureIndex) != disable) { + return byIndex(disable ? (material.bits | DIFFUSE_FLAG) : (material.bits & ~DIFFUSE_FLAG)); + } + + return material; + } + protected int bits; public BlendMode blendMode(int textureIndex) { diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java index 0991eae5e..32af3ef5b 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java @@ -39,8 +39,6 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3f; import net.minecraft.world.BlockRenderView; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.fabricmc.fabric.impl.client.indigo.Indigo; import net.fabricmc.fabric.impl.client.indigo.renderer.accessor.AccessAmbientOcclusionCalculator; import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoFace.WeightFunction; @@ -52,19 +50,7 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo; /** * Adaptation of inner, non-static class in BlockModelRenderer that serves same purpose. */ -@Environment(EnvType.CLIENT) -public class AoCalculator { - @FunctionalInterface - public interface BrightnessFunc { - int apply(BlockPos pos, BlockState state); - } - - /** Used to receive a method reference in constructor for ao value lookup. */ - @FunctionalInterface - public interface AoFunc { - float apply(BlockPos pos, BlockState state); - } - +public abstract class AoCalculator { /** * Vanilla models with cubic quads have vertices in a certain order, which allows * us to map them using a lookup. Adapted from enum in vanilla AoCalculator. @@ -84,12 +70,14 @@ public class AoCalculator { private final AccessAmbientOcclusionCalculator vanillaCalc; private final BlockPos.Mutable lightPos = new BlockPos.Mutable(); private final BlockPos.Mutable searchPos = new BlockPos.Mutable(); - private final BlockRenderInfo blockInfo; - private final BrightnessFunc brightnessFunc; - private final AoFunc aoFunc; + protected final BlockRenderInfo blockInfo; + + public abstract int light(BlockPos pos, BlockState state); + + public abstract float ao(BlockPos pos, BlockState state); /** caches results of {@link #computeFace(Direction, boolean, boolean)} for the current block. */ - private final AoFaceData[] faceData = new AoFaceData[12]; + private final AoFaceData[] faceData = new AoFaceData[24]; /** indicates which elements of {@link #faceData} have been computed for the current block. */ private int completionFlags = 0; @@ -101,13 +89,11 @@ public class AoCalculator { public final float[] ao = new float[4]; public final int[] light = new int[4]; - public AoCalculator(BlockRenderInfo blockInfo, BrightnessFunc brightnessFunc, AoFunc aoFunc) { + public AoCalculator(BlockRenderInfo blockInfo) { this.blockInfo = blockInfo; - this.brightnessFunc = brightnessFunc; - this.aoFunc = aoFunc; this.vanillaCalc = VanillaAoHelper.get(); - for (int i = 0; i < 12; i++) { + for (int i = 0; i < 24; i++) { faceData[i] = new AoFaceData(); } } @@ -123,12 +109,7 @@ public class AoCalculator { switch (config) { case VANILLA: - // prevent NPE in error case of failed reflection for vanilla calculator access - if (vanillaCalc == null) { - calcFastVanilla(quad); - } else { - calcVanilla(quad); - } + calcVanilla(quad); // no point in comparing vanilla with itself shouldCompare = false; @@ -156,7 +137,7 @@ public class AoCalculator { calcEnhanced(quad); } - if (shouldCompare && vanillaCalc != null) { + if (shouldCompare) { float[] vanillaAo = new float[4]; int[] vanillaLight = new int[4]; calcVanilla(quad, vanillaAo, vanillaLight); @@ -188,11 +169,11 @@ public class AoCalculator { private void calcVanilla(MutableQuadViewImpl quad, float[] aoDest, int[] lightDest) { vanillaAoControlBits.clear(); - final Direction face = quad.lightFace(); + final Direction lightFace = quad.lightFace(); quad.toVanilla(0, vertexData, 0, false); - VanillaAoHelper.updateShape(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, vertexData, face, vanillaAoData, vanillaAoControlBits); - vanillaCalc.fabric_apply(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, quad.lightFace(), vanillaAoData, vanillaAoControlBits, quad.hasShade()); + VanillaAoHelper.updateShape(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, vertexData, lightFace, vanillaAoData, vanillaAoControlBits); + vanillaCalc.fabric_apply(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, lightFace, vanillaAoData, vanillaAoControlBits, quad.hasShade()); System.arraycopy(vanillaCalc.fabric_colorMultiplier(), 0, aoDest, 0, 4); System.arraycopy(vanillaCalc.fabric_brightness(), 0, lightDest, 0, 4); @@ -207,9 +188,9 @@ public class AoCalculator { } if ((flags & CUBIC_FLAG) == 0) { - vanillaPartialFace(quad, (flags & LIGHT_FACE_FLAG) != 0); + vanillaPartialFace(quad, quad.lightFace(), (flags & LIGHT_FACE_FLAG) != 0, quad.hasShade()); } else { - vanillaFullFace(quad, (flags & LIGHT_FACE_FLAG) != 0); + vanillaFullFace(quad, quad.lightFace(), (flags & LIGHT_FACE_FLAG) != 0, quad.hasShade()); } } @@ -217,28 +198,26 @@ public class AoCalculator { switch (quad.geometryFlags()) { case AXIS_ALIGNED_FLAG | CUBIC_FLAG | LIGHT_FACE_FLAG: case AXIS_ALIGNED_FLAG | LIGHT_FACE_FLAG: - vanillaPartialFace(quad, true); + vanillaPartialFace(quad, quad.lightFace(), true, quad.hasShade()); break; case AXIS_ALIGNED_FLAG | CUBIC_FLAG: case AXIS_ALIGNED_FLAG: - blendedPartialFace(quad); + blendedPartialFace(quad, quad.lightFace(), quad.hasShade()); break; default: - irregularFace(quad); + irregularFace(quad, quad.hasShade()); break; } } - private void vanillaFullFace(QuadViewImpl quad, boolean isOnLightFace) { - final Direction lightFace = quad.lightFace(); - computeFace(lightFace, isOnLightFace, quad.hasShade()).toArray(ao, light, VERTEX_MAP[lightFace.getId()]); + private void vanillaFullFace(QuadViewImpl quad, Direction lightFace, boolean isOnLightFace, boolean shade) { + computeFace(lightFace, isOnLightFace, shade).toArray(ao, light, VERTEX_MAP[lightFace.getId()]); } - private void vanillaPartialFace(QuadViewImpl quad, boolean isOnLightFace) { - final Direction lightFace = quad.lightFace(); - AoFaceData faceData = computeFace(lightFace, isOnLightFace, quad.hasShade()); + private void vanillaPartialFace(QuadViewImpl quad, Direction lightFace, boolean isOnLightFace, boolean shade) { + AoFaceData faceData = computeFace(lightFace, isOnLightFace, shade); final WeightFunction wFunc = AoFace.get(lightFace).weightFunc; final float[] w = this.w; @@ -249,36 +228,35 @@ public class AoCalculator { } } - /** used in {@link #blendedInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace)} as return variable to avoid new allocation. */ + /** used in {@link #blendedInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace, boolean shade)} as return variable to avoid new allocation. */ AoFaceData tmpFace = new AoFaceData(); /** Returns linearly interpolated blend of outer and inner face based on depth of vertex in face. */ - private AoFaceData blendedInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace) { + private AoFaceData blendedInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace, boolean shade) { final float w1 = AoFace.get(lightFace).depthFunc.apply(quad, vertexIndex); final float w0 = 1 - w1; - return AoFaceData.weightedMean(computeFace(lightFace, true, quad.hasShade()), w0, computeFace(lightFace, false, quad.hasShade()), w1, tmpFace); + return AoFaceData.weightedMean(computeFace(lightFace, true, shade), w0, computeFace(lightFace, false, shade), w1, tmpFace); } /** - * Like {@link #blendedInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace)} but optimizes if depth is 0 or 1. + * Like {@link #blendedInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace, boolean shade)} but optimizes if depth is 0 or 1. * Used for irregular faces when depth varies by vertex to avoid unneeded interpolation. */ - private AoFaceData gatherInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace) { + private AoFaceData gatherInsetFace(QuadViewImpl quad, int vertexIndex, Direction lightFace, boolean shade) { final float w1 = AoFace.get(lightFace).depthFunc.apply(quad, vertexIndex); if (MathHelper.approximatelyEquals(w1, 0)) { - return computeFace(lightFace, true, quad.hasShade()); + return computeFace(lightFace, true, shade); } else if (MathHelper.approximatelyEquals(w1, 1)) { - return computeFace(lightFace, false, quad.hasShade()); + return computeFace(lightFace, false, shade); } else { final float w0 = 1 - w1; - return AoFaceData.weightedMean(computeFace(lightFace, true, quad.hasShade()), w0, computeFace(lightFace, false, quad.hasShade()), w1, tmpFace); + return AoFaceData.weightedMean(computeFace(lightFace, true, shade), w0, computeFace(lightFace, false, shade), w1, tmpFace); } } - private void blendedPartialFace(QuadViewImpl quad) { - final Direction lightFace = quad.lightFace(); - AoFaceData faceData = blendedInsetFace(quad, 0, lightFace); + private void blendedPartialFace(QuadViewImpl quad, Direction lightFace, boolean shade) { + AoFaceData faceData = blendedInsetFace(quad, 0, lightFace, shade); final WeightFunction wFunc = AoFace.get(lightFace).weightFunc; for (int i = 0; i < 4; i++) { @@ -291,7 +269,7 @@ public class AoCalculator { /** used exclusively in irregular face to avoid new heap allocations each call. */ private final Vec3f vertexNormal = new Vec3f(); - private void irregularFace(MutableQuadViewImpl quad) { + private void irregularFace(MutableQuadViewImpl quad, boolean shade) { final Vec3f faceNorm = quad.faceNormal(); Vec3f normal; final float[] w = this.w; @@ -307,7 +285,7 @@ public class AoCalculator { if (!MathHelper.approximatelyEquals(0f, x)) { final Direction face = x > 0 ? Direction.EAST : Direction.WEST; - final AoFaceData fd = gatherInsetFace(quad, i, face); + final AoFaceData fd = gatherInsetFace(quad, i, face, shade); AoFace.get(face).weightFunc.apply(quad, i, w); final float n = x * x; final float a = fd.weigtedAo(w); @@ -325,7 +303,7 @@ public class AoCalculator { if (!MathHelper.approximatelyEquals(0f, y)) { final Direction face = y > 0 ? Direction.UP : Direction.DOWN; - final AoFaceData fd = gatherInsetFace(quad, i, face); + final AoFaceData fd = gatherInsetFace(quad, i, face, shade); AoFace.get(face).weightFunc.apply(quad, i, w); final float n = y * y; final float a = fd.weigtedAo(w); @@ -343,7 +321,7 @@ public class AoCalculator { if (!MathHelper.approximatelyEquals(0f, z)) { final Direction face = z > 0 ? Direction.SOUTH : Direction.NORTH; - final AoFaceData fd = gatherInsetFace(quad, i, face); + final AoFaceData fd = gatherInsetFace(quad, i, face, shade); AoFace.get(face).weightFunc.apply(quad, i, w); final float n = z * z; final float a = fd.weigtedAo(w); @@ -362,6 +340,19 @@ public class AoCalculator { } } + private AoFaceData computeFace(Direction lightFace, boolean isOnBlockFace, boolean shade) { + final int faceDataIndex = shade ? (isOnBlockFace ? lightFace.getId() : lightFace.getId() + 6) : (isOnBlockFace ? lightFace.getId() + 12 : lightFace.getId() + 18); + final int mask = 1 << faceDataIndex; + final AoFaceData result = faceData[faceDataIndex]; + + if ((completionFlags & mask) == 0) { + completionFlags |= mask; + computeFace(result, lightFace, isOnBlockFace, shade); + } + + return result; + } + /** * Computes smoothed brightness and Ao shading for four corners of a block face. * Outer block face is what you normally see and what you get when the second @@ -370,155 +361,145 @@ public class AoCalculator { * in vanilla logic for some blocks that aren't full opaque cubes. * Except for parameterization, the logic itself is practically identical to vanilla. */ - private AoFaceData computeFace(Direction lightFace, boolean isOnBlockFace, boolean shade) { - final int faceDataIndex = isOnBlockFace ? lightFace.getId() : lightFace.getId() + 6; - final int mask = 1 << faceDataIndex; - final AoFaceData result = faceData[faceDataIndex]; + private void computeFace(AoFaceData result, Direction lightFace, boolean isOnBlockFace, boolean shade) { + final BlockRenderView world = blockInfo.blockView; + final BlockPos pos = blockInfo.blockPos; + final BlockState blockState = blockInfo.blockState; + final BlockPos.Mutable lightPos = this.lightPos; + final BlockPos.Mutable searchPos = this.searchPos; + BlockState searchState; - if ((completionFlags & mask) == 0) { - completionFlags |= mask; - - final BlockRenderView world = blockInfo.blockView; - final BlockPos pos = blockInfo.blockPos; - final BlockState blockState = blockInfo.blockState; - final BlockPos.Mutable lightPos = this.lightPos; - final BlockPos.Mutable searchPos = this.searchPos; - BlockState searchState; - - if (isOnBlockFace) { - lightPos.set(pos, lightFace); - } else { - lightPos.set(pos); - } - - AoFace aoFace = AoFace.get(lightFace); - - // Vanilla was further offsetting the positions for opaque block checks in the - // direction of the light face, but it was actually mis-sampling and causing - // visible artifacts in certain situations - - searchPos.set(lightPos, aoFace.neighbors[0]); - searchState = world.getBlockState(searchPos); - final int light0 = brightnessFunc.apply(searchPos, searchState); - final float ao0 = aoFunc.apply(searchPos, searchState); - - if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { - searchPos.move(lightFace); - searchState = world.getBlockState(searchPos); - } - - final boolean isClear0 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; - - searchPos.set(lightPos, aoFace.neighbors[1]); - searchState = world.getBlockState(searchPos); - final int light1 = brightnessFunc.apply(searchPos, searchState); - final float ao1 = aoFunc.apply(searchPos, searchState); - - if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { - searchPos.move(lightFace); - searchState = world.getBlockState(searchPos); - } - - final boolean isClear1 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; - - searchPos.set(lightPos, aoFace.neighbors[2]); - searchState = world.getBlockState(searchPos); - final int light2 = brightnessFunc.apply(searchPos, searchState); - final float ao2 = aoFunc.apply(searchPos, searchState); - - if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { - searchPos.move(lightFace); - searchState = world.getBlockState(searchPos); - } - - final boolean isClear2 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; - - searchPos.set(lightPos, aoFace.neighbors[3]); - searchState = world.getBlockState(searchPos); - final int light3 = brightnessFunc.apply(searchPos, searchState); - final float ao3 = aoFunc.apply(searchPos, searchState); - - if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { - searchPos.move(lightFace); - searchState = world.getBlockState(searchPos); - } - - final boolean isClear3 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; - - // c = corner - values at corners of face - int cLight0, cLight1, cLight2, cLight3; - float cAo0, cAo1, cAo2, cAo3; - - // If neighbors on both sides of the corner are opaque, then apparently we use the light/shade - // from one of the sides adjacent to the corner. If either neighbor is clear (no light subtraction) - // then we use values from the outwardly diagonal corner. (outwardly = position is one more away from light face) - if (!isClear2 && !isClear0) { - cAo0 = ao0; - cLight0 = light0; - } else { - searchPos.set(lightPos).move(aoFace.neighbors[0]).move(aoFace.neighbors[2]); - searchState = world.getBlockState(searchPos); - cAo0 = aoFunc.apply(searchPos, searchState); - cLight0 = brightnessFunc.apply(searchPos, searchState); - } - - if (!isClear3 && !isClear0) { - cAo1 = ao0; - cLight1 = light0; - } else { - searchPos.set(lightPos).move(aoFace.neighbors[0]).move(aoFace.neighbors[3]); - searchState = world.getBlockState(searchPos); - cAo1 = aoFunc.apply(searchPos, searchState); - cLight1 = brightnessFunc.apply(searchPos, searchState); - } - - if (!isClear2 && !isClear1) { - cAo2 = ao1; - cLight2 = light1; - } else { - searchPos.set(lightPos).move(aoFace.neighbors[1]).move(aoFace.neighbors[2]); - searchState = world.getBlockState(searchPos); - cAo2 = aoFunc.apply(searchPos, searchState); - cLight2 = brightnessFunc.apply(searchPos, searchState); - } - - if (!isClear3 && !isClear1) { - cAo3 = ao1; - cLight3 = light1; - } else { - searchPos.set(lightPos).move(aoFace.neighbors[1]).move(aoFace.neighbors[3]); - searchState = world.getBlockState(searchPos); - cAo3 = aoFunc.apply(searchPos, searchState); - cLight3 = brightnessFunc.apply(searchPos, searchState); - } - - // If on block face or neighbor isn't occluding, "center" will be neighbor brightness - // Doesn't use light pos because logic not based solely on this block's geometry - int lightCenter; - searchPos.set(pos, lightFace); - searchState = world.getBlockState(searchPos); - - if (isOnBlockFace || !searchState.isOpaqueFullCube(world, searchPos)) { - lightCenter = brightnessFunc.apply(searchPos, searchState); - } else { - lightCenter = brightnessFunc.apply(pos, blockState); - } - - float aoCenter = aoFunc.apply(lightPos, world.getBlockState(lightPos)); - float worldBrightness = world.getBrightness(lightFace, shade); - - result.a0 = ((ao3 + ao0 + cAo1 + aoCenter) * 0.25F) * worldBrightness; - result.a1 = ((ao2 + ao0 + cAo0 + aoCenter) * 0.25F) * worldBrightness; - result.a2 = ((ao2 + ao1 + cAo2 + aoCenter) * 0.25F) * worldBrightness; - result.a3 = ((ao3 + ao1 + cAo3 + aoCenter) * 0.25F) * worldBrightness; - - result.l0(meanBrightness(light3, light0, cLight1, lightCenter)); - result.l1(meanBrightness(light2, light0, cLight0, lightCenter)); - result.l2(meanBrightness(light2, light1, cLight2, lightCenter)); - result.l3(meanBrightness(light3, light1, cLight3, lightCenter)); + if (isOnBlockFace) { + lightPos.set(pos, lightFace); + } else { + lightPos.set(pos); } - return result; + AoFace aoFace = AoFace.get(lightFace); + + // Vanilla was further offsetting the positions for opaque block checks in the + // direction of the light face, but it was actually mis-sampling and causing + // visible artifacts in certain situations + + searchPos.set(lightPos, aoFace.neighbors[0]); + searchState = world.getBlockState(searchPos); + final int light0 = light(searchPos, searchState); + final float ao0 = ao(searchPos, searchState); + + if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { + searchPos.move(lightFace); + searchState = world.getBlockState(searchPos); + } + + final boolean isClear0 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; + + searchPos.set(lightPos, aoFace.neighbors[1]); + searchState = world.getBlockState(searchPos); + final int light1 = light(searchPos, searchState); + final float ao1 = ao(searchPos, searchState); + + if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { + searchPos.move(lightFace); + searchState = world.getBlockState(searchPos); + } + + final boolean isClear1 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; + + searchPos.set(lightPos, aoFace.neighbors[2]); + searchState = world.getBlockState(searchPos); + final int light2 = light(searchPos, searchState); + final float ao2 = ao(searchPos, searchState); + + if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { + searchPos.move(lightFace); + searchState = world.getBlockState(searchPos); + } + + final boolean isClear2 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; + + searchPos.set(lightPos, aoFace.neighbors[3]); + searchState = world.getBlockState(searchPos); + final int light3 = light(searchPos, searchState); + final float ao3 = ao(searchPos, searchState); + + if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET) { + searchPos.move(lightFace); + searchState = world.getBlockState(searchPos); + } + + final boolean isClear3 = !searchState.shouldBlockVision(world, searchPos) || searchState.getOpacity(world, searchPos) == 0; + + // c = corner - values at corners of face + int cLight0, cLight1, cLight2, cLight3; + float cAo0, cAo1, cAo2, cAo3; + + // If neighbors on both sides of the corner are opaque, then apparently we use the light/shade + // from one of the sides adjacent to the corner. If either neighbor is clear (no light subtraction) + // then we use values from the outwardly diagonal corner. (outwardly = position is one more away from light face) + if (!isClear2 && !isClear0) { + cAo0 = ao0; + cLight0 = light0; + } else { + searchPos.set(lightPos).move(aoFace.neighbors[0]).move(aoFace.neighbors[2]); + searchState = world.getBlockState(searchPos); + cAo0 = ao(searchPos, searchState); + cLight0 = light(searchPos, searchState); + } + + if (!isClear3 && !isClear0) { + cAo1 = ao0; + cLight1 = light0; + } else { + searchPos.set(lightPos).move(aoFace.neighbors[0]).move(aoFace.neighbors[3]); + searchState = world.getBlockState(searchPos); + cAo1 = ao(searchPos, searchState); + cLight1 = light(searchPos, searchState); + } + + if (!isClear2 && !isClear1) { + cAo2 = ao1; + cLight2 = light1; + } else { + searchPos.set(lightPos).move(aoFace.neighbors[1]).move(aoFace.neighbors[2]); + searchState = world.getBlockState(searchPos); + cAo2 = ao(searchPos, searchState); + cLight2 = light(searchPos, searchState); + } + + if (!isClear3 && !isClear1) { + cAo3 = ao1; + cLight3 = light1; + } else { + searchPos.set(lightPos).move(aoFace.neighbors[1]).move(aoFace.neighbors[3]); + searchState = world.getBlockState(searchPos); + cAo3 = ao(searchPos, searchState); + cLight3 = light(searchPos, searchState); + } + + // If on block face or neighbor isn't occluding, "center" will be neighbor brightness + // Doesn't use light pos because logic not based solely on this block's geometry + int lightCenter; + searchPos.set(pos, lightFace); + searchState = world.getBlockState(searchPos); + + if (isOnBlockFace || !searchState.isOpaqueFullCube(world, searchPos)) { + lightCenter = light(searchPos, searchState); + } else { + lightCenter = light(pos, blockState); + } + + float aoCenter = ao(lightPos, world.getBlockState(lightPos)); + float worldBrightness = world.getBrightness(lightFace, shade); + + result.a0 = ((ao3 + ao0 + cAo1 + aoCenter) * 0.25F) * worldBrightness; + result.a1 = ((ao2 + ao0 + cAo0 + aoCenter) * 0.25F) * worldBrightness; + result.a2 = ((ao2 + ao1 + cAo2 + aoCenter) * 0.25F) * worldBrightness; + result.a3 = ((ao3 + ao1 + cAo3 + aoCenter) * 0.25F) * worldBrightness; + + result.l0(meanBrightness(light3, light0, cLight1, lightCenter)); + result.l1(meanBrightness(light2, light0, cLight0, lightCenter)); + result.l2(meanBrightness(light2, light1, cLight2, lightCenter)); + result.l3(meanBrightness(light3, light1, cLight3, lightCenter)); } /** diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java index c02113a36..60e40ec7c 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl.java @@ -38,6 +38,7 @@ import net.minecraft.util.math.Direction; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer; +import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl; import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl.Value; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.NormalHelper; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.TextureHelper; @@ -116,9 +117,13 @@ public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEm data[baseIndex + HEADER_BITS] = EncodingFormat.cullFace(0, cullFace); nominalFace(quad.getFace()); colorIndex(quad.getColorIndex()); + + if (!quad.hasShade()) { + material = RenderMaterialImpl.setDisableDiffuse((Value) material, 0, true); + } + material(material); tag(0); - shade(quad.hasShade()); isGeometryInvalid = true; return this; } diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java index c386e3a39..2e940f88b 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/QuadViewImpl.java @@ -18,7 +18,6 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.mesh; import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat.HEADER_BITS; import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat.HEADER_COLOR_INDEX; -import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat.HEADER_STRIDE; import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat.HEADER_TAG; import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat.QUAD_STRIDE; import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat.VERTEX_COLOR; @@ -52,7 +51,6 @@ public class QuadViewImpl implements QuadView { /** True when geometry flags or light face may not match geometry. */ protected boolean isGeometryInvalid = true; protected final Vec3f faceNormal = new Vec3f(); - private boolean shade = true; /** Size and where it comes from will vary in subtypes. But in all cases quad is fully encoded to array. */ protected int[] data; @@ -268,15 +266,7 @@ public class QuadViewImpl implements QuadView { return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_V]); } - public int vertexStart() { - return baseIndex + HEADER_STRIDE; - } - public boolean hasShade() { - return shade && !material().disableDiffuse(0); - } - - public void shade(boolean shade) { - this.shade = shade; + return !material().disableDiffuse(0); } } diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractQuadRenderer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractQuadRenderer.java index 2fb815bd1..e0fd7dddc 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractQuadRenderer.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractQuadRenderer.java @@ -36,7 +36,6 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform; import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl; import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper; -import net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl; /** @@ -234,9 +233,9 @@ public abstract class AbstractQuadRenderer { * even for un-shaded quads. These are also applied with AO shading but that is done in AO calculator. */ private void shadeFlatQuad(MutableQuadViewImpl quad) { - if ((quad.geometryFlags() & GeometryHelper.AXIS_ALIGNED_FLAG) == 0 || quad.hasVertexNormals()) { - // Quads that aren't direction-aligned or that have vertex normals need to be shaded - // using interpolation - vanilla can't handle them. Generally only applies to modded models. + if (quad.hasVertexNormals()) { + // Quads that have vertex normals need to be shaded using interpolation - vanilla can't + // handle them. Generally only applies to modded models. final float faceShade = blockInfo.blockView.getBrightness(quad.lightFace(), quad.hasShade()); for (int i = 0; i < 4; i++) { diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderContext.java index 7d6b8831a..0eaa957fd 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderContext.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderContext.java @@ -21,7 +21,6 @@ import java.util.function.Consumer; 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; @@ -43,10 +42,20 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoLuminanceFix; */ public class BlockRenderContext extends AbstractRenderContext { private final BlockRenderInfo blockInfo = new BlockRenderInfo(); - private final AoCalculator aoCalc = new AoCalculator(blockInfo, this::brightness, this::aoLevel); + + private final AoCalculator aoCalc = new AoCalculator(blockInfo) { + @Override + public int light(BlockPos pos, BlockState state) { + return WorldRenderer.getLightmapCoordinates(blockInfo.blockView, state, pos); + } + + @Override + public float ao(BlockPos pos, BlockState state) { + return AoLuminanceFix.INSTANCE.apply(blockInfo.blockView, pos, state); + } + }; private VertexConsumer bufferBuilder; - private boolean didOutput = false; // 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; @@ -94,25 +103,11 @@ public class BlockRenderContext extends AbstractRenderContext { } }; - private int brightness(BlockPos pos, BlockState state) { - if (blockInfo.blockView == null) { - return LightmapTextureManager.MAX_LIGHT_COORDINATE; - } - - return WorldRenderer.getLightmapCoordinates(blockInfo.blockView, state, pos); - } - - private float aoLevel(BlockPos pos, BlockState state) { - final BlockRenderView blockView = blockInfo.blockView; - return blockView == null ? 1f : AoLuminanceFix.INSTANCE.apply(blockView, pos, state); - } - private VertexConsumer outputBuffer(RenderLayer renderLayer) { - didOutput = true; return bufferBuilder; } - public boolean render(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, Random random, long seed, int overlay) { + public void render(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, boolean cull, Random random, long seed, int overlay) { this.bufferBuilder = buffer; this.matrix = matrixStack.peek().getPositionMatrix(); this.normalMatrix = matrixStack.peek().getNormalMatrix(); @@ -120,9 +115,8 @@ public class BlockRenderContext extends AbstractRenderContext { this.seed = seed; this.overlay = overlay; - this.didOutput = false; aoCalc.clear(); - blockInfo.setBlockView(blockView); + blockInfo.prepareForWorld(blockView, cull); blockInfo.prepareForBlock(state, pos, model.useAmbientOcclusion()); ((FabricBakedModel) model).emitBlockQuads(blockView, state, pos, randomSupplier, this); @@ -131,8 +125,6 @@ public class BlockRenderContext extends AbstractRenderContext { this.bufferBuilder = null; this.random = null; this.seed = seed; - - return didOutput; } @Override diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java index d99696f74..cde47e1ab 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo.java @@ -19,6 +19,9 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render; import java.util.Random; import java.util.function.Supplier; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.color.block.BlockColors; @@ -39,7 +42,8 @@ import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; */ public class BlockRenderInfo { private final BlockColors blockColorMap = MinecraftClient.getInstance().getBlockColors(); - public final Random random = new Random(); + private final BlockPos.Mutable searchPos = new BlockPos.Mutable(); + private final Random random = new Random(); public BlockRenderView blockView; public BlockPos blockPos; public BlockState blockState; @@ -47,6 +51,10 @@ public class BlockRenderInfo { boolean defaultAo; RenderLayer defaultLayer; + private boolean enableCulling; + private int cullCompletionFlags; + private int cullResultFlags; + public final Supplier<Random> randomSupplier = () -> { final Random result = random; long seed = this.seed; @@ -60,18 +68,22 @@ public class BlockRenderInfo { return result; }; - public void setBlockView(BlockRenderView blockView) { + public void prepareForWorld(BlockRenderView blockView, boolean enableCulling) { this.blockView = blockView; + this.enableCulling = enableCulling; } public void prepareForBlock(BlockState blockState, BlockPos blockPos, boolean modelAO) { this.blockPos = blockPos; this.blockState = blockState; - // in the unlikely case seed actually matches this, we'll simply retrieve it more than one + // in the unlikely case seed actually matches this, we'll simply retrieve it more than once seed = -1L; defaultAo = modelAO && MinecraftClient.isAmbientOcclusionEnabled() && blockState.getLuminance() == 0; defaultLayer = RenderLayers.getBlockLayer(blockState); + + cullCompletionFlags = 0; + cullResultFlags = 0; } public void release() { @@ -83,8 +95,25 @@ public class BlockRenderInfo { return 0xFF000000 | blockColorMap.getColor(blockState, blockView, blockPos, colorIndex); } - boolean shouldDrawFace(Direction face) { - return true; + boolean shouldDrawFace(@Nullable Direction face) { + if (face == null || !enableCulling) { + return true; + } + + final int mask = 1 << face.getId(); + + if ((cullCompletionFlags & mask) == 0) { + cullCompletionFlags |= mask; + + if (Block.shouldDrawSide(blockState, blockView, blockPos, face, searchPos.set(blockPos, face))) { + cullResultFlags |= mask; + return true; + } else { + return false; + } + } else { + return (cullResultFlags & mask) != 0; + } } RenderLayer effectiveRenderLayer(BlendMode blendMode) { diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainBlockRenderInfo.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainBlockRenderInfo.java deleted file mode 100644 index c7404ea4b..000000000 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainBlockRenderInfo.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.client.indigo.renderer.render; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; - -public class TerrainBlockRenderInfo extends BlockRenderInfo { - private int cullCompletionFlags; - private int cullResultFlags; - - @Override - public void prepareForBlock(BlockState blockState, BlockPos blockPos, boolean modelAO) { - super.prepareForBlock(blockState, blockPos, modelAO); - cullCompletionFlags = 0; - cullResultFlags = 0; - } - - @Override - boolean shouldDrawFace(Direction face) { - if (face == null) { - return true; - } - - final int mask = 1 << face.getId(); - - if ((cullCompletionFlags & mask) == 0) { - cullCompletionFlags |= mask; - - if (Block.shouldDrawSide(blockState, blockView, blockPos, face, blockPos.offset(face))) { - cullResultFlags |= mask; - return true; - } else { - return false; - } - } else { - return (cullResultFlags & mask) != 0; - } - } -} diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainFallbackConsumer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainFallbackConsumer.java index 4dd8b7d9f..d76b73e4a 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainFallbackConsumer.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainFallbackConsumer.java @@ -18,7 +18,6 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render; import java.util.List; import java.util.Random; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java index 0df538529..89d104248 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java @@ -20,8 +20,8 @@ import java.util.function.Consumer; import net.minecraft.block.BlockState; import net.minecraft.client.render.chunk.BlockBufferBuilderStorage; +import net.minecraft.client.render.chunk.ChunkBuilder; 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.client.util.math.MatrixStack; @@ -46,9 +46,19 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator; public class TerrainRenderContext extends AbstractRenderContext { public static final ThreadLocal<TerrainRenderContext> POOL = ThreadLocal.withInitial(TerrainRenderContext::new); - private final TerrainBlockRenderInfo blockInfo = new TerrainBlockRenderInfo(); + private final BlockRenderInfo blockInfo = new BlockRenderInfo(); private final ChunkRenderInfo chunkInfo = new ChunkRenderInfo(); - private final AoCalculator aoCalc = new AoCalculator(blockInfo, chunkInfo::cachedBrightness, chunkInfo::cachedAoLevel); + private final AoCalculator aoCalc = new AoCalculator(blockInfo) { + @Override + public int light(BlockPos pos, BlockState state) { + return chunkInfo.cachedBrightness(pos, state); + } + + @Override + public float ao(BlockPos pos, BlockState state) { + return chunkInfo.cachedAoLevel(pos, state); + } + }; private final AbstractMeshConsumer meshConsumer = new AbstractMeshConsumer(blockInfo, chunkInfo::getInitializedBuffer, aoCalc, this::transform) { @Override @@ -84,8 +94,8 @@ public class TerrainRenderContext extends AbstractRenderContext { } }; - public void prepare(ChunkRendererRegion blockView, BuiltChunk chunkRenderer, ChunkData chunkData, BlockBufferBuilderStorage builders) { - blockInfo.setBlockView(blockView); + public void prepare(ChunkRendererRegion blockView, BuiltChunk chunkRenderer, ChunkBuilder.ChunkData chunkData, BlockBufferBuilderStorage builders) { + blockInfo.prepareForWorld(blockView, true); chunkInfo.prepare(blockView, chunkRenderer, chunkData, builders); } diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinBlockModelRenderer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinBlockModelRenderer.java index 5ca38118a..ae1c9e497 100644 --- a/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinBlockModelRenderer.java +++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/mixin/client/indigo/renderer/MixinBlockModelRenderer.java @@ -50,11 +50,11 @@ public abstract class MixinBlockModelRenderer implements AccessBlockModelRendere protected abstract void getQuadDimensions(BlockRenderView blockView, BlockState blockState, BlockPos blockPos, int[] vertexData, Direction face, float[] aoData, BitSet controlBits); @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) { + private void hookRender(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrix, VertexConsumer buffer, boolean cull, Random rand, long seed, int overlay, CallbackInfoReturnable<Boolean> ci) { if (!((FabricBakedModel) model).isVanillaAdapter()) { 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)); + context.render(blockView, model, state, pos, matrix, buffer, cull, rand, seed, overlay); + ci.cancel(); } }