From 4c8c8c868065438018c23c2afbf7f078ba2d4c52 Mon Sep 17 00:00:00 2001 From: Toni Date: Sat, 24 Feb 2024 20:40:04 -0500 Subject: [PATCH] add new leaf culling impl, frametime FPS graph, overhaul hostile entity distance culling --- .../client/gui/SodiumGameOptionPages.java | 13 +++- .../sodium/client/gui/SodiumGameOptions.java | 23 +++++++ .../compile/pipeline/BlockOcclusionCache.java | 27 +++++++- .../compile/pipeline/BlockRenderContext.java | 4 ++ .../chunk/compile/pipeline/BlockRenderer.java | 25 +++++++ .../entitydistance/EntityDispatcherMixin.java | 9 ++- .../embeddium/extras/ExtrasConfig.java | 19 +++++- .../embeddium/extras/ExtrasOptions.java | 3 +- .../extras/fps/DebugOverlayEvent.java | 55 ++++++++++++++- .../extras/leafculling/LeafCulling.java | 68 +++++++++++++++++++ .../extras/pages/EntityCullingPage.java | 21 ++++++ .../resources/assets/sodium/lang/en_us.json | 12 +++- 12 files changed, 269 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/embeddedt/embeddium/extras/leafculling/LeafCulling.java diff --git a/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java b/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java index ae9764ca..a806f50b 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java @@ -2,7 +2,6 @@ import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.pipeline.RenderTarget; -import me.jellysquid.mods.sodium.client.SodiumClientMod; import me.jellysquid.mods.sodium.client.compat.modernui.MuiGuiScaleHook; import me.jellysquid.mods.sodium.client.gl.arena.staging.MappedStagingBuffer; import me.jellysquid.mods.sodium.client.gl.device.RenderDevice; @@ -255,6 +254,18 @@ public static OptionPage performance() { .build() ); + groups.add(OptionGroup.createBuilder() + .add(OptionImpl.createBuilder(SodiumGameOptions.LeafCullingQuality.class, sodiumOpts) + .setName(Component.translatable("xenon.extras.options.leaf_culling.name")) + .setTooltip(Component.translatable("xenon.extras.options.leaf_culling.tooltip")) + .setControl(option -> new CyclingControl<>(option, SodiumGameOptions.LeafCullingQuality.class)) + .setBinding((opts, value) -> opts.performance.leafCullingQuality = value, opts -> opts.performance.leafCullingQuality) + .setImpact(OptionImpact.MEDIUM) + .setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD) + .build() + ).build() + ); + groups.add(OptionGroup.createBuilder() .add(OptionImpl.createBuilder(boolean.class, sodiumOpts) .setName(Component.translatable("sodium.options.use_block_face_culling.name")) diff --git a/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptions.java b/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptions.java index 261567e6..61d56d83 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptions.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptions.java @@ -46,6 +46,7 @@ public static class PerformanceSettings { public boolean animateOnlyVisibleTextures = true; public boolean useEntityCulling = true; + public LeafCullingQuality leafCullingQuality = LeafCullingQuality.SOLID_AGGRESSIVE; public boolean useFogOcclusion = true; public boolean useBlockFaceCulling = true; public boolean useCompactVertexFormat = true; @@ -96,6 +97,28 @@ public boolean isFancy(GraphicsStatus graphicsMode) { } } + public enum LeafCullingQuality implements TextProvider { + NONE("options.leaf_culling.none"), + HOLLOW("options.leaf_culling.hollow"), + SOLID("options.leaf_culling.solid"), + SOLID_AGGRESSIVE("options.leaf_culling.solid_aggressive"); + + private final Component name; + + LeafCullingQuality(String name) { + this.name = Component.translatable(name); + } + + @Override + public Component getLocalizedName() { + return this.name; + } + + public boolean isSolid() { + return this == SOLID || this == SOLID_AGGRESSIVE; + } + } + private static final Gson GSON = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .setPrettyPrinting() diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java index 38934b63..689819e9 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java @@ -1,13 +1,17 @@ package me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline; import it.unimi.dsi.fastutil.objects.Object2ByteLinkedOpenHashMap; +import me.jellysquid.mods.sodium.client.SodiumClientMod; +import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.LeavesBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.BooleanOp; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; +import org.embeddedt.embeddium.extras.leafculling.LeafCulling; public class BlockOcclusionCache { private static final byte UNCACHED_VALUE = (byte) 127; @@ -34,7 +38,28 @@ public boolean shouldDrawSide(BlockState selfState, BlockGetter view, BlockPos p BlockState adjState = view.getBlockState(adjPos); - if (selfState.skipRendering(adjState, facing) || (adjState.hidesNeighborFace(view, pos, selfState, facing.getOpposite()) && selfState.supportsExternalFaceHiding())) { + var skipRendering = selfState.skipRendering(adjState, facing); + var hideNeighbor = adjState.hidesNeighborFace(view, pos, selfState, facing.getOpposite()); + + if (selfState.getBlock() instanceof LeavesBlock ) + { + if (SodiumClientMod.options().performance.leafCullingQuality == SodiumGameOptions.LeafCullingQuality.HOLLOW) + skipRendering = LeafCulling.shouldCullSide(view, pos, facing, 2); + + if (adjState.getBlock() instanceof LeavesBlock && SodiumClientMod.options().performance.leafCullingQuality.isSolid()) + { + var cullSelf = LeafCulling.surroundedByLeaves(view, pos); + var cullOther = LeafCulling.surroundedByLeaves(view, adjPos); + + if (!cullSelf && cullOther) + return false; + + if (cullSelf && cullOther) + return false; + } + } + + if (skipRendering || (hideNeighbor && selfState.supportsExternalFaceHiding())) { return false; } else if (adjState.canOcclude()) { VoxelShape selfShape = selfState.getFaceOcclusionShape(view, pos, facing); diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java index 3e07f36f..a843bf50 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java @@ -108,4 +108,8 @@ public ModelData modelData() { public RenderType renderLayer() { return this.renderLayer; } + + public void setRenderLayer(RenderType layer) { + this.renderLayer = layer; + } } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java index ee9aa6a9..eba0443a 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java @@ -2,8 +2,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import me.jellysquid.mods.sodium.client.SodiumClientMod; import me.jellysquid.mods.sodium.client.compat.ccl.SinkingVertexBuilder; import me.jellysquid.mods.sodium.client.compat.forge.ForgeBlockRenderer; +import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; import me.jellysquid.mods.sodium.client.model.color.ColorProvider; import me.jellysquid.mods.sodium.client.model.color.ColorProviderRegistry; import me.jellysquid.mods.sodium.client.model.light.LightMode; @@ -30,11 +32,13 @@ import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.LeavesBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.SingleThreadedRandomSource; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.ForgeConfig; import org.embeddedt.embeddium.api.BlockRendererRegistry; +import org.embeddedt.embeddium.extras.leafculling.LeafCulling; import java.util.Arrays; import java.util.List; @@ -120,6 +124,27 @@ public void renderModel(BlockRenderContext ctx, ChunkBuildBuffers buffers) { } for (Direction face : DirectionUtil.ALL_DIRECTIONS) { + + // custom leaf block rendering + if (ctx.state().getBlock() instanceof LeavesBlock + && SodiumClientMod.options().performance.leafCullingQuality.isSolid() + && LeafCulling.surroundedByLeaves(ctx.localSlice(), ctx.pos())) + { + var renderLayer = ctx.renderLayer(); + ctx.setRenderLayer(RenderType.solid()); + + List quads = this.getGeometry(ctx, face); + var leafmaterial = DefaultMaterials.forRenderLayer(ctx.renderLayer()); + var leafmeshBuilder = buffers.get(leafmaterial); + + if (!quads.isEmpty() && this.isFaceVisible(ctx, face)) { + this.renderQuadList(ctx, leafmaterial, lighter, colorizer, renderOffset, leafmeshBuilder, quads, face); + } + + ctx.setRenderLayer(renderLayer); + continue; + } + List quads = this.getGeometry(ctx, face); if (!quads.isEmpty() && this.isFaceVisible(ctx, face)) { diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/extras/entitydistance/EntityDispatcherMixin.java b/src/main/java/me/jellysquid/mods/sodium/mixin/extras/entitydistance/EntityDispatcherMixin.java index 271d908b..23e93320 100644 --- a/src/main/java/me/jellysquid/mods/sodium/mixin/extras/entitydistance/EntityDispatcherMixin.java +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/extras/entitydistance/EntityDispatcherMixin.java @@ -3,6 +3,9 @@ import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.monster.Monster; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,13 +20,15 @@ public class EntityDispatcherMixin { public void inject$shouldRender(E entity, Frustum clippingHelper, double cameraX, double cameraY, double cameraZ, CallbackInfoReturnable cir) { if (!ExtrasConfig.entityDistanceCullingCache) return; + var isHostile = entity instanceof Monster; + if (!((IWhitelistCheck) entity.getType()).embPlus$isAllowed() && !ExtrasTools.isEntityWithinDistance( entity, cameraX, cameraY, cameraZ, - ExtrasConfig.entityCullingDistanceYCache, - ExtrasConfig.entityCullingDistanceXCache + isHostile ? ExtrasConfig.hostileDistanceYCache : ExtrasConfig.entityCullingDistanceYCache, + isHostile ? ExtrasConfig.hostileDistanceXCache : ExtrasConfig.entityCullingDistanceXCache )) { cir.setReturnValue(false); } diff --git a/src/main/java/org/embeddedt/embeddium/extras/ExtrasConfig.java b/src/main/java/org/embeddedt/embeddium/extras/ExtrasConfig.java index e91a1bbb..99bec3f3 100644 --- a/src/main/java/org/embeddedt/embeddium/extras/ExtrasConfig.java +++ b/src/main/java/org/embeddedt/embeddium/extras/ExtrasConfig.java @@ -7,6 +7,7 @@ import me.jellysquid.mods.sodium.mixin.extras.borderless.accessors.MainWindowAccessor; import net.minecraft.client.Minecraft; import net.minecraft.client.Options; +import net.minecraft.util.Mth; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec.*; @@ -79,6 +80,7 @@ public class ExtrasConfig { public static final IntValue tileEntityCullingDistanceX; public static final IntValue tileEntityCullingDistanceY; public static final BooleanValue entityDistanceCulling; + public static final IntValue hostileEntityModifier; public static final IntValue entityCullingDistanceX; public static final IntValue entityCullingDistanceY; public static final ConfigValue> entityWhitelist; // QUICK CHECK @@ -89,6 +91,8 @@ public class ExtrasConfig { public static volatile boolean entityDistanceCullingCache; public static volatile int entityCullingDistanceXCache; public static volatile int entityCullingDistanceYCache; + public static volatile int hostileDistanceXCache; + public static volatile int hostileDistanceYCache; // OTHERS public static final EnumValue borderlessAttachModeF11; @@ -125,7 +129,7 @@ public class ExtrasConfig { fpsDisplayMode = BUILDER .comment("Configure FPS Display mode", "Complete mode gives you min FPS count and average count") - .defineEnum("fpsDisplay", FPSDisplayMode.ADVANCED); + .defineEnum("fpsDisplay", FPSDisplayMode.FRAMETIME); fpsDisplayGravity = BUILDER .comment("Configure FPS Display gravity", "Places counter on specified corner of your screen") @@ -255,8 +259,9 @@ public class ExtrasConfig { // xenonextras -> performance -> distanceCulling -> entities BUILDER.push("entities"); entityDistanceCulling = BUILDER - .comment("Toggles distance culling for entities", "Maybe you use another mod for that :(") + .comment("Toggles distance culling for entities") .define("enable", true); + entityCullingDistanceX = BUILDER .comment("Configure horizontal max distance before cull entities", "Value is squared, default was 64^2 (or 64x64)") .defineInRange("cullingMaxDistanceX", 4096, 0, Integer.MAX_VALUE); @@ -265,6 +270,10 @@ public class ExtrasConfig { .comment("Configure vertical max distance before cull entities", "Value is raw") .defineInRange("cullingMaxDistanceY", 32, 0, 512); + hostileEntityModifier = BUILDER + .comment("Configure modifier applied to hostile entities", "Value is raw, 50% - 200%") + .defineInRange("hostileEntityModifier", 100, 25, 200); + entityWhitelist = BUILDER .comment("List of all Entities to be ignored by distance culling", "Uses ResourceLocation to identify it", "Example 1: \"minecraft:bat\" - Ignores bats only", "Example 2: \"alexsmobs:*\" - ignores all entities for alexmobs mod") .defineListAllowEmpty(Collections.singletonList("whitelist"), Arrays.asList(DEFAULT_ENTITIES_WHITELIST), (s) -> s.toString().contains(":")); @@ -340,6 +349,10 @@ public static void updateCache(ModConfigEvent ignored) { entityCullingDistanceXCache = entityCullingDistanceX.get(); entityCullingDistanceYCache = entityCullingDistanceY.get(); + var x = Mth.sqrt(entityCullingDistanceXCache) * (hostileEntityModifier.get() / 100f); + hostileDistanceXCache = (int) (x * x); + hostileDistanceYCache = (int) (entityCullingDistanceYCache * (hostileEntityModifier.get() / 100f)); + SodiumClientMod.logger().warn("Cache updated successfully"); } @@ -367,7 +380,7 @@ public enum AttachMode { /* CONFIG VALUES */ public enum FPSDisplayMode { - OFF, SIMPLE, ADVANCED; + OFF, SIMPLE, ADVANCED, FRAMETIME; public boolean off() { return this == OFF; diff --git a/src/main/java/org/embeddedt/embeddium/extras/ExtrasOptions.java b/src/main/java/org/embeddedt/embeddium/extras/ExtrasOptions.java index e965a286..6fd9a1c1 100644 --- a/src/main/java/org/embeddedt/embeddium/extras/ExtrasOptions.java +++ b/src/main/java/org/embeddedt/embeddium/extras/ExtrasOptions.java @@ -36,7 +36,8 @@ public static void setFPSOptions(List groups, SodiumOptionsStorage .setControl((option) -> new CyclingControl<>(option, ExtrasConfig.FPSDisplayMode.class, new Component[]{ Component.translatable("xenon.extras.options.common.off"), Component.translatable("xenon.extras.options.common.simple"), - Component.translatable("xenon.extras.options.common.advanced") + Component.translatable("xenon.extras.options.common.advanced"), + Component.translatable("xenon.extras.options.common.frametime") })) .setBinding( (opts, value) -> ExtrasConfig.fpsDisplayMode.set(value), diff --git a/src/main/java/org/embeddedt/embeddium/extras/fps/DebugOverlayEvent.java b/src/main/java/org/embeddedt/embeddium/extras/fps/DebugOverlayEvent.java index 51d5b6ed..f4038c5b 100644 --- a/src/main/java/org/embeddedt/embeddium/extras/fps/DebugOverlayEvent.java +++ b/src/main/java/org/embeddedt/embeddium/extras/fps/DebugOverlayEvent.java @@ -5,8 +5,10 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.util.FrameTimer; +import net.minecraft.util.Mth; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RenderGuiEvent; import net.minecraftforge.client.event.RenderGuiOverlayEvent; @@ -62,7 +64,7 @@ private static void renderFPSChar(Minecraft mc, GuiGraphics graphics, Font font, // FPS switch (mode) { case SIMPLE -> DISPLAY.append(calculateFPS$getColor(mc)).add(fix(fps)).add(" ").add(MSG_FPS.getString()).add(ChatFormatting.RESET); - case ADVANCED -> { + case FRAMETIME, ADVANCED -> { DISPLAY.append(calculateFPS$getColor(mc)).add(fix(fps)).add(ChatFormatting.RESET); DISPLAY.append(calculateMinFPS$getColor(mc)).add(MSG_MIN).add(" ").add(fix(minFPS)).add(ChatFormatting.RESET); DISPLAY.append(calculateAvgFPS$getColor(mc)).add(MSG_AVG).add(" ").add(fix(avgFPS)).add(ChatFormatting.RESET); @@ -103,10 +105,61 @@ private static void renderFPSChar(Minecraft mc, GuiGraphics graphics, Font font, } graphics.drawString(font, displayString, posX, posY, 0xffffffff, true); + + if (mode == ExtrasConfig.FPSDisplayMode.FRAMETIME) + drawChart(graphics, Minecraft.getInstance().getFrameTimer(), 0, (int) (graphics.guiWidth() / 5.5f), (int) (posY + font.lineHeight + 1)); + DISPLAY.release(); graphics.pose().popPose(); } + + private static void drawChart(GuiGraphics graphics, FrameTimer timer, int x, int width, int height) { + var mc = Minecraft.getInstance(); + + int logStart = timer.getLogStart(); + int logEnd = timer.getLogEnd(); + long[] along = timer.getLog(); + int xPos = x; + int widthDiff = Math.max(0, along.length - width); + int wrapped = timer.wrapIndex(logStart + widthDiff); + + int guiHeight = height;//graphics.guiHeight(); + + while(wrapped != logEnd) { + int barHeight = timer.scaleSampleTo(along[wrapped], 30, 60) / 4; + int heightMax = 30; + int color = getSampleColor(Mth.clamp(barHeight, 0, heightMax), 0, heightMax / 2, heightMax); + graphics.fill(RenderType.guiOverlay(), xPos, guiHeight, xPos + 1, guiHeight + barHeight, color); + + ++xPos; + wrapped = timer.wrapIndex(wrapped + 1); + } + + } + + private static int getSampleColor(int height, int heightMin, int heightMid, int heightMax) { + return height < heightMid + ? colorLerp(1712789271, -1140870125, (float)height / (float)heightMid) + : colorLerp(-1140870125, -1140908238, (float)(height - heightMid) / (float)(heightMax - heightMid)); + } + + private static int colorLerp(int col1, int col2, float factor) { + int i = col1 >> 24 & 255; + int j = col1 >> 16 & 255; + int k = col1 >> 8 & 255; + int l = col1 & 255; + int m = col2 >> 24 & 255; + int n = col2 >> 16 & 255; + int o = col2 >> 8 & 255; + int p = col2 & 255; + int q = Mth.clamp((int)Mth.lerp(factor, (float)i, (float)m), 0, 255); + int r = Mth.clamp((int)Mth.lerp(factor, (float)j, (float)n), 0, 255); + int s = Mth.clamp((int)Mth.lerp(factor, (float)k, (float)o), 0, 255); + int t = Mth.clamp((int)Mth.lerp(factor, (float)l, (float)p), 0, 255); + return q << 24 | r << 16 | s << 8 | t; + } + private static ChatFormatting calculateFPS$getColor(Minecraft mc) { fps = mc.getFps(); return ExtrasTools.colorByLow(fps); diff --git a/src/main/java/org/embeddedt/embeddium/extras/leafculling/LeafCulling.java b/src/main/java/org/embeddedt/embeddium/extras/leafculling/LeafCulling.java new file mode 100644 index 00000000..58eec33d --- /dev/null +++ b/src/main/java/org/embeddedt/embeddium/extras/leafculling/LeafCulling.java @@ -0,0 +1,68 @@ +package org.embeddedt.embeddium.extras.leafculling; + +import me.jellysquid.mods.sodium.client.SodiumClientMod; +import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.AirBlock; +import net.minecraft.world.level.block.LeavesBlock; + +public class LeafCulling { + private static final Direction[] VALUES = Direction.values(); + + public static boolean isFacingAir(BlockGetter view, BlockPos pos, Direction facing) { + var vec = facing.getNormal(); + return view.getBlockState(pos.offset(vec)).getBlock() instanceof AirBlock; + } + + public static boolean surroundedByLeaves(BlockGetter view, BlockPos pos) { + var isAggressiveMode = SodiumClientMod.options().performance.leafCullingQuality == SodiumGameOptions.LeafCullingQuality.SOLID_AGGRESSIVE; + for (Direction dir : VALUES) { + if (isAggressiveMode && (dir == Direction.DOWN || dir == Direction.UP)) + continue; + + var dirPos = pos.offset(dir.getNormal()); + var blockstate = view.getBlockState(dirPos); + if (blockstate.getBlock() instanceof LeavesBlock) + continue; + + if (blockstate.isSolidRender(view, pos)) + continue; + + return false; + } + + return true; + } + + public static boolean shouldCullSide(BlockGetter view, BlockPos pos, Direction facing, int depth) { + + + if (isFacingAir(view, pos, facing)) + return false; + + var vec = facing.getNormal(); + var cull = true; + for (int i = 1; i <= depth; i++) { + var state = view.getBlockState(pos.offset(vec.multiply(i))); + cull &= state != null && state.getBlock() instanceof LeavesBlock; + } + return cull; + +// var normal = facing.getNormal(); +// var vec = pos.offset(normal); +// +// +// boolean hasAirBlock = false; +// for (Direction dir : Direction.values()) { +// var dirPos = vec.offset(dir.getNormal()); +// if (!view.getBlockState(dirPos).isSolidRender(view, dirPos)) { +// hasAirBlock = true; +// break; +// } +// } +// +// return !hasAirBlock; + } +} diff --git a/src/main/java/org/embeddedt/embeddium/extras/pages/EntityCullingPage.java b/src/main/java/org/embeddedt/embeddium/extras/pages/EntityCullingPage.java index 86292000..5ea2781e 100644 --- a/src/main/java/org/embeddedt/embeddium/extras/pages/EntityCullingPage.java +++ b/src/main/java/org/embeddedt/embeddium/extras/pages/EntityCullingPage.java @@ -10,6 +10,7 @@ import me.jellysquid.mods.sodium.client.gui.options.control.TickBoxControl; import me.jellysquid.mods.sodium.client.gui.options.storage.SodiumOptionsStorage; import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; import org.embeddedt.embeddium.extras.ExtrasConfig; import java.util.ArrayList; @@ -47,6 +48,7 @@ private static ImmutableList create() { int result = value * value; ExtrasConfig.entityCullingDistanceX.set(result); ExtrasConfig.entityCullingDistanceXCache = result; + ExtrasConfig.hostileDistanceXCache = (int) (value * value * (ExtrasConfig.hostileEntityModifier.get() / 100f)); }, (options) -> Math.toIntExact(Math.round(Math.sqrt(ExtrasConfig.entityCullingDistanceXCache)))) .setImpact(OptionImpact.HIGH) @@ -60,17 +62,36 @@ private static ImmutableList create() { (options, value) -> { ExtrasConfig.entityCullingDistanceY.set(value); ExtrasConfig.entityCullingDistanceYCache = value; + ExtrasConfig.hostileDistanceYCache = (int) (value * (ExtrasConfig.hostileEntityModifier.get() / 100f)); }, (options) -> ExtrasConfig.entityCullingDistanceYCache) .setImpact(OptionImpact.HIGH) .build(); + var hostileEntityModifier = OptionImpl.createBuilder(int.class, performanceOptionsStorage) + .setName(Component.translatable("xenon.extras.options.culling.entity.distance.hostile.title")) + .setTooltip(Component.translatable("xenon.extras.options.culling.entity.distance.hostile.desc")) + .setControl((option) -> new SliderControl(option, 25, 200, 5, ControlValueFormatter.percentage())) + .setBinding( + (options, value) -> { + ExtrasConfig.hostileEntityModifier.set(value); + + var x = Mth.sqrt(ExtrasConfig.entityCullingDistanceXCache) * (value / 100f); + var y = ExtrasConfig.hostileDistanceYCache; + + ExtrasConfig.hostileDistanceXCache = (int) (x * x); + ExtrasConfig.hostileDistanceYCache = (int) (y * (value / 100f)); + }, + (options) -> ExtrasConfig.hostileEntityModifier.get()) + .setImpact(OptionImpact.HIGH) + .build(); groups.add(OptionGroup .createBuilder() .add(enableDistanceChecks) .add(maxEntityDistance) .add(maxEntityDistanceVertical) + .add(hostileEntityModifier) .build() ); diff --git a/src/main/resources/assets/sodium/lang/en_us.json b/src/main/resources/assets/sodium/lang/en_us.json index 024402e9..4f7c3651 100644 --- a/src/main/resources/assets/sodium/lang/en_us.json +++ b/src/main/resources/assets/sodium/lang/en_us.json @@ -75,6 +75,7 @@ "xenon.extras.options.common.on": "On", "xenon.extras.options.common.simple": "Simple", "xenon.extras.options.common.advanced": "Advanced", + "xenon.extras.options.common.frametime": "Frametime", "xenon.extras.options.common.attach": "Attach", "xenon.extras.options.common.replace": "Replace", "xenon.extras.options.common.experimental": "[EXPERIMENTAL]", @@ -97,6 +98,9 @@ "xenon.extras.options.culling.tile.distance.vertical.title": "Block Entities Max Distance (Vertical)", "xenon.extras.options.culling.tile.distance.vertical.desc": "Hides block entities underneath this many blocks, improving performance above caves (if you have your machines in caves, for some reason). This should ideally be set lower than the horizontal distance.", + "xenon.extras.options.culling.entity.distance.hostile.title": "Hostile Entity Modifier", + "xenon.extras.options.culling.entity.distance.hostile.desc": "Allows separate control over the distance at which hostile vs. passive entities are culled.", + "xenon.extras.options.darkness.page": "True Darkness", "xenon.extras.options.darkness.mode.title": "Darkness Mode", "xenon.extras.options.darkness.mode.desc": "Makes the rest of the world more realistically dark. Does not effect daytime or torch light.\nControls how dark is considered true darkness.", @@ -205,6 +209,12 @@ "xenon.extras.options.others.borderless.attachmode.title": "Borderless Fullscreen on F11", "xenon.extras.options.others.borderless.attachmode.desc": "Configures how Borderless Fullscreen should be attached\n\nATTACH - Adds it between windowed and Fullscreen\nREPLACE - Replaced Fullscreen with Borderless Fullscreen\nOFF - Disables Borderless Fullscreen attachment to F11 key", "xenon.extras.options.others.languagescreen.fastreload.title": "Fast Language Reload", - "xenon.extras.options.others.languagescreen.fastreload.desc": "If enabled, Language updates only reload language instead of all resources, a 99.9% extra of speed" + "xenon.extras.options.others.languagescreen.fastreload.desc": "If enabled, Language updates only reload language instead of all resources, a 99.9% extra of speed", + "xenon.extras.options.leaf_culling.name": "Leaf Culling Mode", + "xenon.extras.options.leaf_culling.tooltip": "If enabled, leaves behind other leaves will be culled to improve performance. Hollow will aggressively cull faces, and Solid mode will enable fast solid block rendering of leaves behind other leaves.", + "options.leaf_culling.none": "None", + "options.leaf_culling.hollow": "Hollow", + "options.leaf_culling.solid": "Solid", + "options.leaf_culling.solid_aggressive": "Solid Aggressive" }