From ca3aebef00c3e31a1810639a8f8dd2c8e9b06111 Mon Sep 17 00:00:00 2001 From: RogoShum <1269314290@qq.com> Date: Sat, 27 Apr 2024 01:32:33 +0800 Subject: [PATCH] update Async rebuild chunk --- gradle.properties | 2 +- .../rogo/renderingculling/api/Config.java | 10 +- .../renderingculling/api/CullingHandler.java | 95 ++++++++++--------- .../api/CullingRenderEvent.java | 4 +- .../rogo/renderingculling/api/ModLoader.java | 37 ++++++++ .../api/data/ChunkCullingMap.java | 91 +----------------- .../api/impl/ICullingShader.java | 2 +- .../renderingculling/gui/ConfigScreen.java | 17 ++-- .../gui/NeatSliderButton.java | 2 +- .../mixin/MixinShaderInstance.java | 36 +++---- .../mixin/fabric/MixinWindow.java | 2 +- .../mixin/sodium/MixinOcclusionCuller.java | 2 - .../sodium/MixinSodiumWorldRenderer.java | 4 + .../util/OcclusionCullerThread.java | 15 ++- .../util/SodiumSectionAsyncUtil.java | 29 +++++- .../lang/en_us.json | 8 +- .../lang/zh_cn.json | 8 +- .../shaders/core/chunk_culling.fsh | 88 ++++++++++------- .../shaders/core/chunk_culling.json | 2 +- .../shaders/core/entity_culling.fsh | 62 ++++++++---- .../core/instanced_entity_culling.json | 1 - src/main/resources/fabric.mod.json | 2 +- 22 files changed, 271 insertions(+), 248 deletions(-) diff --git a/gradle.properties b/gradle.properties index e730cbf..5300f06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.20.1+build.10 loader_version=0.15.9 # Mod Properties -mod_version=0.5.4 +mod_version=0.5.5 maven_group=rogo.renderingculling archives_base_name=BruteForceRenderingCulling-fabric-1.20.1 diff --git a/src/main/java/rogo/renderingculling/api/Config.java b/src/main/java/rogo/renderingculling/api/Config.java index b572a9b..62cbe86 100644 --- a/src/main/java/rogo/renderingculling/api/Config.java +++ b/src/main/java/rogo/renderingculling/api/Config.java @@ -26,7 +26,7 @@ public class Config { public static double getSampling() { if(unload()) - return 0.2; + return 0.5; return SAMPLING.getValue(); } @@ -75,10 +75,10 @@ public static boolean getAsyncChunkRebuild() { if(!shouldCullChunk()) return false; - if(CullingHandler.hasNvidium()) + if(ModLoader.hasNvidium()) return false; - if(!CullingHandler.hasSodium()) + if(!ModLoader.hasSodium()) return false; return ASYNC.getValue(); @@ -88,10 +88,10 @@ public static void setAsyncChunkRebuild(boolean value) { if(!shouldCullChunk()) return; - if(CullingHandler.hasNvidium()) + if(ModLoader.hasNvidium()) return; - if(!CullingHandler.hasSodium()) + if(!ModLoader.hasSodium()) return; ASYNC.setValue(value); diff --git a/src/main/java/rogo/renderingculling/api/CullingHandler.java b/src/main/java/rogo/renderingculling/api/CullingHandler.java index 49b950b..9db2379 100644 --- a/src/main/java/rogo/renderingculling/api/CullingHandler.java +++ b/src/main/java/rogo/renderingculling/api/CullingHandler.java @@ -3,16 +3,12 @@ import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.pipeline.TextureTarget; import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; import com.mojang.logging.LogUtils; import com.mojang.math.Axis; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Camera; -import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.client.renderer.culling.Frustum; @@ -25,7 +21,6 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; -import org.lwjgl.glfw.GLFW; import org.lwjgl.opengl.GL; import org.lwjgl.system.Checks; import org.slf4j.Logger; @@ -38,7 +33,7 @@ import rogo.renderingculling.mixin.AccessorMinecraft; import rogo.renderingculling.util.DepthContext; import rogo.renderingculling.util.LifeTimer; -import rogo.renderingculling.util.NvidiumUtil; +import rogo.renderingculling.util.OcclusionCullerThread; import rogo.renderingculling.util.ShaderLoader; import java.lang.reflect.Field; @@ -137,22 +132,6 @@ public class CullingHandler { }); } - public static String fromID(String s) { - return MOD_ID + ":" + s; - } - - public static final KeyMapping CONFIG_KEY = KeyBindingHelper.registerKeyBinding( - new KeyMapping(MOD_ID + ".key.config", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_R, - "key.category." + MOD_ID)); - - public static final KeyMapping DEBUG_KEY = KeyBindingHelper.registerKeyBinding( - new KeyMapping(MOD_ID + ".key.debug", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_X, - "key.category." + MOD_ID)); - public static void init() { try { OptiFine = Class.forName("net.optifine.shaders.Shaders"); @@ -167,7 +146,7 @@ public static void init() { } } - if (hasIris()) { + if (ModLoader.hasIris()) { try { SHADER_LOADER = Class.forName("rogo.renderingculling.util.IrisLoaderImpl").asSubclass(ShaderLoader.class).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { @@ -203,6 +182,19 @@ public static boolean shouldRenderChunk(IRenderSectionVisibility section, boolea return false; } + if (DEBUG < 2) { + if (!useOcclusionCulling) { + return true; + } + if (!section.shouldCheckVisibility(lastVisibleUpdatedFrame)) { + return true; + } else if (CHUNK_CULLING_MAP.isChunkOffsetCameraVisible(section.getPositionX(), section.getPositionY(), section.getPositionZ())) { + section.updateVisibleTick(lastVisibleUpdatedFrame); + return true; + } + return false; + } + if (Config.getAsyncChunkRebuild()) { if (!useOcclusionCulling) { return true; @@ -251,11 +243,20 @@ public static boolean shouldSkipBlockEntity(BlockEntity blockEntity, AABB aabb, } if (ENTITY_CULLING_MAP == null || !Config.getCullEntity()) return false; - if (FRUSTUM == null || !FRUSTUM.isVisible(aabb)) return true; String type = BlockEntityType.getKey(blockEntity.getType()).toString(); if (Config.getBlockEntitiesSkip().contains(type)) return false; + if (DEBUG < 2) { + if (visibleBlock.contains(pos)) { + return false; + } else if (ENTITY_CULLING_MAP.isObjectVisible(blockEntity)) { + visibleBlock.updateUsageTick(pos, clientTickCount); + return false; + } + return true; + } + long time = System.nanoTime(); boolean visible; @@ -289,6 +290,16 @@ public static boolean shouldSkipEntity(Entity entity) { return false; if (ENTITY_CULLING_MAP == null || !Config.getCullEntity()) return false; + if (DEBUG < 2) { + if (visibleEntity.contains(entity)) { + return false; + } else if (ENTITY_CULLING_MAP.isObjectVisible(entity)) { + visibleEntity.updateUsageTick(entity, clientTickCount); + return false; + } + return true; + } + long time = System.nanoTime(); boolean visible; @@ -317,7 +328,11 @@ public static boolean shouldSkipEntity(Entity entity) { public static void onProfilerPopPush(String s) { switch (s) { case "beforeRunTick" -> { - if (Minecraft.getInstance().level != null) { + if (((AccessorLevelRender) Minecraft.getInstance().levelRenderer).getNeedsFullRenderChunkUpdate() && Minecraft.getInstance().level != null) { + if(ModLoader.hasMod("embeddium")) { + fullChunkUpdateCooldown = 20; + } + LEVEL_SECTION_RANGE = Minecraft.getInstance().level.getMaxSection() - Minecraft.getInstance().level.getMinSection(); LEVEL_MIN_SECTION_ABS = Math.abs(Minecraft.getInstance().level.getMinSection()); LEVEL_MIN_POS = Minecraft.getInstance().level.getMinBuildHeight(); @@ -327,6 +342,7 @@ public static void onProfilerPopPush(String s) { case "afterRunTick" -> { ++frame; updateMapData(); + OcclusionCullerThread.shouldUpdate(); } case "captureFrustum" -> { AccessorLevelRender levelFrustum = (AccessorLevelRender) Minecraft.getInstance().levelRenderer; @@ -363,9 +379,10 @@ public static void onProfilerPopPush(String s) { } public static void onProfilerPush(String s) { - if(s.equals("onKeyboardInput")) { - ModLoader.onKeyPress(); - } if (Config.shouldCullChunk() && s.equals("apply_frustum")) { + if (s.equals("onKeyboardInput")) { + ModLoader.onKeyPress(); + } + if (Config.shouldCullChunk() && s.equals("apply_frustum")) { if (SHADER_LOADER == null || OptiFine != null) { chunkCount = 0; chunkCulling = 0; @@ -481,7 +498,7 @@ public static void checkShader() { } public static void updateDepthMap() { - CullingHandler.PROJECTION_MATRIX = new Matrix4f(RenderSystem.getProjectionMatrix()); + //CullingHandler.PROJECTION_MATRIX = new Matrix4f(RenderSystem.getProjectionMatrix()); if (anyCulling() && !checkCulling && anyNeedTransfer()) { float sampling = (float) (double) Config.getSampling(); Window window = Minecraft.getInstance().getWindow(); @@ -612,6 +629,8 @@ public static void updateMapData() { CullingHandler.ENTITY_CULLING_MAP.getEntityTable().addAllTemp(); } + + CullingHandler.ENTITY_CULLING_MAP.getEntityTable().addEntityAttribute(CullingRenderEvent.ENTITY_CULLING_INSTANCE_RENDERER::addInstanceAttrib); } fps = ((AccessorMinecraft) Minecraft.getInstance()).getFps(); @@ -697,24 +716,8 @@ public static boolean gl33() { return gl33 == 1; } - public static boolean hasMod(String s) { - return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals(s)); - } - - public static boolean hasSodium() { - return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals("sodium") || modInfo.getMetadata().getId().equals("embeddium") || modInfo.getMetadata().getId().equals("rubidium")); - } - - public static boolean hasIris() { - return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals("iris") || modInfo.getMetadata().getId().equals("oculus")); - } - - public static boolean hasNvidium() { - return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals("nvidium")) && NvidiumUtil.nvidiumBfs(); - } - public static boolean needPauseRebuild() { - return fullChunkUpdateCooldown > 0; + return false; } public static int mapChunkY(double posY) { diff --git a/src/main/java/rogo/renderingculling/api/CullingRenderEvent.java b/src/main/java/rogo/renderingculling/api/CullingRenderEvent.java index 5fc13dc..310b188 100644 --- a/src/main/java/rogo/renderingculling/api/CullingRenderEvent.java +++ b/src/main/java/rogo/renderingculling/api/CullingRenderEvent.java @@ -270,8 +270,8 @@ public static void setUniform(ShaderInstance shader) { float[] array = new float[]{pos.x, pos.y, pos.z}; shaderInstance.getCullingCameraDir().set(array); } - if (shaderInstance.getCullingFov() != null) { - shaderInstance.getCullingFov().set((float) CullingHandler.FOV + (float) (170 - CullingHandler.FOV)); + if (shaderInstance.getBoxScale() != null) { + shaderInstance.getBoxScale().set(4.0f); } if (shaderInstance.getFrustumPos() != null && CullingHandler.FRUSTUM != null) { Vec3 pos = new Vec3( diff --git a/src/main/java/rogo/renderingculling/api/ModLoader.java b/src/main/java/rogo/renderingculling/api/ModLoader.java index 8cd06d0..d8b3119 100644 --- a/src/main/java/rogo/renderingculling/api/ModLoader.java +++ b/src/main/java/rogo/renderingculling/api/ModLoader.java @@ -1,20 +1,25 @@ package rogo.renderingculling.api; +import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.network.chat.Component; import net.minecraft.world.level.Level; import org.joml.FrustumIntersection; import org.joml.Vector4f; +import org.lwjgl.glfw.GLFW; import rogo.renderingculling.event.WorldUnloadEvent; import rogo.renderingculling.gui.ConfigScreen; import rogo.renderingculling.mixin.AccessorFrustum; +import rogo.renderingculling.util.NvidiumUtil; import rogo.renderingculling.util.OcclusionCullerThread; import java.io.IOException; @@ -70,6 +75,10 @@ private void initShader() { } } + public static String fromID(String s) { + return MOD_ID + ":" + s; + } + private void registerEvents() { WorldUnloadEvent.WORLD_UNLOAD.register(this::onWorldUnload); ClientTickEvents.START_CLIENT_TICK.register(this::onStartClientTick); @@ -102,6 +111,18 @@ private void onStartClientTick(Minecraft client) { } } + public static final KeyMapping CONFIG_KEY = KeyBindingHelper.registerKeyBinding( + new KeyMapping(MOD_ID + ".key.config", + InputConstants.Type.KEYSYM, + GLFW.GLFW_KEY_R, + "key.category." + MOD_ID)); + + public static final KeyMapping DEBUG_KEY = KeyBindingHelper.registerKeyBinding( + new KeyMapping(MOD_ID + ".key.debug", + InputConstants.Type.KEYSYM, + GLFW.GLFW_KEY_X, + "key.category." + MOD_ID)); + public static void onKeyPress() { if (CONFIG_KEY.isDown()) { Minecraft.getInstance().setScreen(new ConfigScreen(Component.translatable(MOD_ID + ".config"))); @@ -124,4 +145,20 @@ public static int getB() { public static Vector4f[] getFrustumPlanes(FrustumIntersection frustum) { return ((AccessorFrustum.AccessorFrustumIntersection) frustum).planes(); } + + public static boolean hasMod(String s) { + return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals(s)); + } + + public static boolean hasSodium() { + return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals("sodium") || modInfo.getMetadata().getId().equals("embeddium") || modInfo.getMetadata().getId().equals("rubidium")); + } + + public static boolean hasIris() { + return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals("iris") || modInfo.getMetadata().getId().equals("oculus")); + } + + public static boolean hasNvidium() { + return FabricLoader.getInstance().getAllMods().stream().anyMatch(modInfo -> modInfo.getMetadata().getId().equals("nvidium")) && NvidiumUtil.nvidiumBfs(); + } } diff --git a/src/main/java/rogo/renderingculling/api/data/ChunkCullingMap.java b/src/main/java/rogo/renderingculling/api/data/ChunkCullingMap.java index b74a707..5f98215 100644 --- a/src/main/java/rogo/renderingculling/api/data/ChunkCullingMap.java +++ b/src/main/java/rogo/renderingculling/api/data/ChunkCullingMap.java @@ -19,29 +19,9 @@ public class ChunkCullingMap extends CullingMap { private int spacePartitionSize = 0; public int queueUpdateCount = 0; public int lastQueueUpdateCount = 0; - private static final int[][] DIRECTIONS = {{0, 1, 0}, {0, -1, 0}, {-1, 0, 0}, {1, 0, 0}, {0, 0, 1}, {0, 0, -1}}; - private boolean updateVisibleChunks = true; - private Set visibleChunks = new HashSet<>(); - private int cameraX; private int cameraZ; - @NotNull - private static BlockPos getOriginPos() { - Vec3 camera = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); - int cameraX = (int) camera.x >> 4; - int cameraZ = (int) camera.z >> 4; - int cameraY = CullingHandler.mapChunkY(camera.y); - - BlockPos origin = new BlockPos(cameraX, cameraY, cameraZ); - if (origin.getY() < 0) { - origin = new BlockPos(cameraX, 0, cameraZ); - } else if (origin.getY() >= CullingHandler.LEVEL_SECTION_RANGE) { - origin = new BlockPos(cameraX, CullingHandler.LEVEL_SECTION_RANGE - 1, cameraZ); - } - return origin; - } - public ChunkCullingMap(int width, int height) { super(width, height); } @@ -62,7 +42,7 @@ public void generateIndex(int renderDistance) { } public void updateCamera() { - Vec3 camera = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); + Vec3 camera = CullingHandler.CAMERA.getPosition(); cameraX = (int) camera.x >> 4; cameraZ = (int) camera.z >> 4; } @@ -71,12 +51,6 @@ public boolean isChunkOffsetCameraVisible(int x, int y, int z) { return isChunkVisible((x >> 4) - cameraX, CullingHandler.mapChunkY(y), (z >> 4) - cameraZ); } - @Override - public void readData() { - super.readData(); - updateVisibleChunks = true; - } - public boolean isChunkVisible(int posX, int posY, int posZ) { int index = 1 + (((posX + renderDistance) * spacePartitionSize * CullingHandler.LEVEL_SECTION_RANGE + (posZ + renderDistance) * CullingHandler.LEVEL_SECTION_RANGE + posY) << 2); if (index > 0 && index < cullingBuffer.limit()) { @@ -84,67 +58,4 @@ public boolean isChunkVisible(int posX, int posY, int posZ) { } return false; } - - public void updateVisibleChunks() { - if (updateVisibleChunks) { - bfsSearch(getOriginPos()); - updateVisibleChunks = false; - } - } - - public Set getVisibleChunks() { - return visibleChunks; - } - - private void bfsSearch(BlockPos origin) { - Queue queue = new ArrayDeque<>(); - Set visible = new HashSet<>(); - Set visited = new HashSet<>(); - - visited.add(new BlockPos(0, origin.getY(), 0)); - queue.offer(new BlockPos(0, origin.getY(), 0)); - visible.add(new BlockPos(origin.getX(), origin.getY() - CullingHandler.LEVEL_MIN_SECTION_ABS, origin.getZ())); - - while (!queue.isEmpty()) { - BlockPos chunkPos = queue.poll(); - BlockPos offsetChunkPos = new BlockPos((chunkPos.getX() + origin.getX()) - , (chunkPos.getY() - CullingHandler.LEVEL_MIN_SECTION_ABS) - , (chunkPos.getZ() + origin.getZ())); - BlockPos absolutePos = new BlockPos(offsetChunkPos.getX() << 4, offsetChunkPos.getY() << 4, offsetChunkPos.getZ() << 4); - - if (!CullingHandler.FRUSTUM.isVisible(new AABB(absolutePos.getX(), absolutePos.getY(), absolutePos.getZ(), absolutePos.getX() + 16, absolutePos.getY() + 16, absolutePos.getZ() + 16))) { - continue; - } else { - boolean isChunkVisible = isChunkVisible(chunkPos.getX(), chunkPos.getY(), chunkPos.getZ()); - if (CullingHandler.checkCulling) - isChunkVisible = !isChunkVisible; - - if (isChunkVisible) - visible.add(offsetChunkPos); - else - continue; - } - - for (int[] direction : DIRECTIONS) { - int newX = chunkPos.getX() + direction[0]; - int newY = chunkPos.getY() + direction[1]; - int newZ = chunkPos.getZ() + direction[2]; - - if (renderDistance < Mth.abs(newX) || - renderDistance < Mth.abs(newZ) || - newY < 0 || - newY >= CullingHandler.LEVEL_SECTION_RANGE) - continue; - - BlockPos neighborChunk = new BlockPos(newX, newY, newZ); - - if (!visited.contains(neighborChunk)) { - queue.offer(neighborChunk); - visited.add(neighborChunk); - } - } - } - - visibleChunks = visible; - } } diff --git a/src/main/java/rogo/renderingculling/api/impl/ICullingShader.java b/src/main/java/rogo/renderingculling/api/impl/ICullingShader.java index 605109a..63216dc 100644 --- a/src/main/java/rogo/renderingculling/api/impl/ICullingShader.java +++ b/src/main/java/rogo/renderingculling/api/impl/ICullingShader.java @@ -6,7 +6,7 @@ public interface ICullingShader { Uniform getRenderDistance(); Uniform getCullingCameraPos(); Uniform getCullingCameraDir(); - Uniform getCullingFov(); + Uniform getBoxScale(); Uniform getDepthSize(); Uniform getCullingSize(); Uniform getLevelHeightOffset(); diff --git a/src/main/java/rogo/renderingculling/gui/ConfigScreen.java b/src/main/java/rogo/renderingculling/gui/ConfigScreen.java index c8668d2..cfce8ef 100644 --- a/src/main/java/rogo/renderingculling/gui/ConfigScreen.java +++ b/src/main/java/rogo/renderingculling/gui/ConfigScreen.java @@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.Player; import rogo.renderingculling.api.Config; import rogo.renderingculling.api.CullingHandler; +import rogo.renderingculling.api.ModLoader; import java.util.List; import java.util.function.Consumer; @@ -107,7 +108,7 @@ public boolean keyPressed(int p_96552_, int p_96553_, int p_96554_) { @Override public boolean keyReleased(int p_94715_, int p_94716_, int p_94717_) { - if (CullingHandler.CONFIG_KEY.matches(p_94715_, p_94716_)) { + if (ModLoader.CONFIG_KEY.matches(p_94715_, p_94716_)) { if (release) { this.onClose(); return true; @@ -127,11 +128,11 @@ protected void init() { } if (player.getName().getString().equals("Dev")) { - addConfigButton(() -> CullingHandler.checkCulling, (b) -> CullingHandler.checkCulling = b, () -> Component.literal("Debug")) - .setDetailMessage(() -> Component.translatable("brute_force_rendering_culling.detail.debug")); + addConfigButton(() -> CullingHandler.checkCulling, (b) -> CullingHandler.checkCulling = b, () -> Component.literal("Debug")) + .setDetailMessage(() -> Component.translatable("brute_force_rendering_culling.detail.debug")); - addConfigButton(() -> CullingHandler.checkTexture, (b) -> CullingHandler.checkTexture = b, () -> Component.literal("Check Texture")) - .setDetailMessage(() -> Component.translatable("brute_force_rendering_culling.detail.check_texture")); + addConfigButton(() -> CullingHandler.checkTexture, (b) -> CullingHandler.checkTexture = b, () -> Component.literal("Check Texture")) + .setDetailMessage(() -> Component.translatable("brute_force_rendering_culling.detail.check_texture")); } addConfigButton(Config::getSampling, (value) -> { @@ -156,11 +157,11 @@ protected void init() { }, () -> Component.translatable("brute_force_rendering_culling.culling_map_update_delay")) .setDetailMessage(() -> Component.translatable("brute_force_rendering_culling.detail.culling_map_update_delay")); - addConfigButton(() -> Config.getCullChunk() && CullingHandler.hasSodium() && !CullingHandler.hasNvidium(), Config::getAsyncChunkRebuild, Config::setAsyncChunkRebuild, () -> Component.translatable("brute_force_rendering_culling.async")) + addConfigButton(() -> Config.getCullChunk() && ModLoader.hasSodium() && !ModLoader.hasNvidium(), Config::getAsyncChunkRebuild, Config::setAsyncChunkRebuild, () -> Component.translatable("brute_force_rendering_culling.async")) .setDetailMessage(() -> { - if (CullingHandler.hasNvidium()) { + if (ModLoader.hasNvidium()) { return Component.translatable("brute_force_rendering_culling.detail.nvidium"); - } else if (!CullingHandler.hasSodium()) { + } else if (!ModLoader.hasSodium()) { return Component.translatable("brute_force_rendering_culling.detail.sodium"); } else return Component.translatable("brute_force_rendering_culling.detail.async"); diff --git a/src/main/java/rogo/renderingculling/gui/NeatSliderButton.java b/src/main/java/rogo/renderingculling/gui/NeatSliderButton.java index 23dd102..729d68f 100644 --- a/src/main/java/rogo/renderingculling/gui/NeatSliderButton.java +++ b/src/main/java/rogo/renderingculling/gui/NeatSliderButton.java @@ -84,7 +84,7 @@ public void renderWidget(GuiGraphics guiGraphics, int p_93677_, int p_93678_, fl } public void shouDetail(GuiGraphics guiGraphics, Font font) { - if (detailMessage != null && isHovered() && !isFocused()) { + if (detailMessage != null && isHovered()) { CullingHandler.reColorToolTip = true; List components = new ArrayList<>(); String[] parts = detailMessage.get().getString().split("\\n"); diff --git a/src/main/java/rogo/renderingculling/mixin/MixinShaderInstance.java b/src/main/java/rogo/renderingculling/mixin/MixinShaderInstance.java index e7322c1..de6b46f 100644 --- a/src/main/java/rogo/renderingculling/mixin/MixinShaderInstance.java +++ b/src/main/java/rogo/renderingculling/mixin/MixinShaderInstance.java @@ -32,31 +32,31 @@ public Uniform getUniform(String p_173349_) { @Shadow private static String SHADER_CORE_PATH; - @Nullable - public Uniform CULLING_CAMERA_DIR; - @Nullable - public Uniform CULLING_FOV; - @Nullable + @javax.annotation.Nullable public Uniform CULLING_CAMERA_POS; - @Nullable + @javax.annotation.Nullable + public Uniform CULLING_CAMERA_DIR; + @javax.annotation.Nullable + public Uniform BOX_SCALE; + @javax.annotation.Nullable public Uniform RENDER_DISTANCE; - @Nullable + @javax.annotation.Nullable public Uniform DEPTH_SIZE; - @Nullable + @javax.annotation.Nullable public Uniform CULLING_SIZE; - @Nullable + @javax.annotation.Nullable public Uniform ENTITY_CULLING_SIZE; - @Nullable + @javax.annotation.Nullable public Uniform LEVEL_HEIGHT_OFFSET; - @Nullable + @javax.annotation.Nullable public Uniform LEVEL_MIN_SECTION; - @Nullable + @javax.annotation.Nullable public Uniform CULLING_FRUSTUM; - @Nullable + @javax.annotation.Nullable public Uniform FRUSTUM_POS; - @Nullable + @javax.annotation.Nullable public Uniform CULLING_VIEW_MAT; - @Nullable + @javax.annotation.Nullable public Uniform CULLING_PROJ_MAT; @Final @@ -67,7 +67,7 @@ public Uniform getUniform(String p_173349_) { public void construct(CallbackInfo ci) { this.CULLING_CAMERA_POS = this.getUniform("CullingCameraPos"); this.CULLING_CAMERA_DIR = this.getUniform("CullingCameraDir"); - this.CULLING_FOV = this.getUniform("CullingFov"); + this.BOX_SCALE = this.getUniform("BoxScale"); this.RENDER_DISTANCE = this.getUniform("RenderDistance"); this.DEPTH_SIZE = this.getUniform("DepthSize"); this.CULLING_SIZE = this.getUniform("CullingSize"); @@ -169,8 +169,8 @@ public Uniform getCullingCameraDir() { } @Override - public Uniform getCullingFov() { - return CULLING_FOV; + public Uniform getBoxScale() { + return BOX_SCALE; } @Inject(at = @At("TAIL"), method = "apply") diff --git a/src/main/java/rogo/renderingculling/mixin/fabric/MixinWindow.java b/src/main/java/rogo/renderingculling/mixin/fabric/MixinWindow.java index 84bb725..d188c34 100644 --- a/src/main/java/rogo/renderingculling/mixin/fabric/MixinWindow.java +++ b/src/main/java/rogo/renderingculling/mixin/fabric/MixinWindow.java @@ -16,7 +16,7 @@ public class MixinWindow { @Unique boolean supportGl33 = false; - @Inject(remap = false, method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;assertInInitPhase()V")) + @Inject(remap = false, method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;assertInInitPhase()V")) private void onInit(WindowEventHandler windowEventHandler, ScreenManager screenManager, DisplayData displayData, String string, String string2, CallbackInfo ci) { if (GLFW.glfwInit()) { GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3); diff --git a/src/main/java/rogo/renderingculling/mixin/sodium/MixinOcclusionCuller.java b/src/main/java/rogo/renderingculling/mixin/sodium/MixinOcclusionCuller.java index 023456a..cbdfa15 100644 --- a/src/main/java/rogo/renderingculling/mixin/sodium/MixinOcclusionCuller.java +++ b/src/main/java/rogo/renderingculling/mixin/sodium/MixinOcclusionCuller.java @@ -12,8 +12,6 @@ import rogo.renderingculling.api.Config; import rogo.renderingculling.api.CullingHandler; import rogo.renderingculling.api.impl.IRenderSectionVisibility; -import rogo.renderingculling.util.OcclusionCullerThread; -import rogo.renderingculling.util.SodiumSectionAsyncUtil; @Mixin(OcclusionCuller.class) public abstract class MixinOcclusionCuller { diff --git a/src/main/java/rogo/renderingculling/mixin/sodium/MixinSodiumWorldRenderer.java b/src/main/java/rogo/renderingculling/mixin/sodium/MixinSodiumWorldRenderer.java index dd0c21e..8872070 100644 --- a/src/main/java/rogo/renderingculling/mixin/sodium/MixinSodiumWorldRenderer.java +++ b/src/main/java/rogo/renderingculling/mixin/sodium/MixinSodiumWorldRenderer.java @@ -31,6 +31,10 @@ public void injectTerrainSetup(Camera camera, Viewport viewport, int frame, bool if (Config.shouldCullChunk()) { SodiumSectionAsyncUtil.update(viewport, ((AccessorRenderSectionManager) this.renderSectionManager).invokeSearchDistance() , ((AccessorRenderSectionManager) this.renderSectionManager).invokeShouldUseOcclusionCulling(camera, spectator)); + if(SodiumSectionAsyncUtil.needSync) { + this.renderSectionManager.markGraphDirty(); + SodiumSectionAsyncUtil.needSync = false; + } } } diff --git a/src/main/java/rogo/renderingculling/util/OcclusionCullerThread.java b/src/main/java/rogo/renderingculling/util/OcclusionCullerThread.java index 0681207..9fb22aa 100644 --- a/src/main/java/rogo/renderingculling/util/OcclusionCullerThread.java +++ b/src/main/java/rogo/renderingculling/util/OcclusionCullerThread.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import rogo.renderingculling.api.Config; import rogo.renderingculling.api.CullingHandler; +import rogo.renderingculling.api.ModLoader; public class OcclusionCullerThread extends Thread { public static OcclusionCullerThread INSTANCE; @@ -21,10 +22,10 @@ public void run() { try { if (CullingHandler.CHUNK_CULLING_MAP != null && CullingHandler.CHUNK_CULLING_MAP.isDone()) { if (Config.getAsyncChunkRebuild()) { - if (CullingHandler.hasSodium()) { + if (ModLoader.hasSodium()) { SodiumSectionAsyncUtil.asyncSearchRebuildSection(); } else { - VanillaAsyncUtil.asyncSearchRebuildSection(); + //VanillaAsyncUtil.asyncSearchRebuildSection(); } } } @@ -32,9 +33,15 @@ public void run() { if (Minecraft.getInstance().level == null) { finished = true; } - } catch (Exception ignored) { - + } catch (Exception e) { + e.printStackTrace(); } } } + + public static void shouldUpdate() { + if (ModLoader.hasSodium() && Config.getAsyncChunkRebuild()) { + SodiumSectionAsyncUtil.shouldUpdate(); + } + } } diff --git a/src/main/java/rogo/renderingculling/util/SodiumSectionAsyncUtil.java b/src/main/java/rogo/renderingculling/util/SodiumSectionAsyncUtil.java index 53c1999..eb94d45 100644 --- a/src/main/java/rogo/renderingculling/util/SodiumSectionAsyncUtil.java +++ b/src/main/java/rogo/renderingculling/util/SodiumSectionAsyncUtil.java @@ -16,6 +16,7 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Semaphore; public class SodiumSectionAsyncUtil { private static int frame = 0; @@ -29,13 +30,16 @@ public class SodiumSectionAsyncUtil { private static VisibleChunkCollector collector; private static VisibleChunkCollector shadowCollector; public static boolean renderingEntities; + private static final Semaphore shouldUpdate = new Semaphore(0); + public static boolean needSync; public static void fromSectionManager(Long2ReferenceMap sections, Level world) { SodiumSectionAsyncUtil.occlusionCuller = new OcclusionCuller(sections, world); } public static void asyncSearchRebuildSection() { - if(CullingHandler.enabledShader() && shadowViewport != null) { + shouldUpdate.acquireUninterruptibly(); + if (CullingHandler.enabledShader() && shadowViewport != null) { frame++; CullingHandler.useOcclusionCulling = false; AsynchronousChunkCollector shadowCollector = new AsynchronousChunkCollector(frame); @@ -49,12 +53,21 @@ public static void asyncSearchRebuildSection() { AsynchronousChunkCollector collector = new AsynchronousChunkCollector(frame); occlusionCuller.findVisible(collector, viewport, searchDistance, useOcclusionCulling, frame); SodiumSectionAsyncUtil.collector = collector; + + if(CullingHandler.CHUNK_CULLING_MAP != null) + CullingHandler.CHUNK_CULLING_MAP.queueUpdateCount++; + Map> rebuildList = SodiumSectionAsyncUtil.collector.getRebuildLists(); + for(ArrayDeque arrayDeque : rebuildList.values()) { + if (!arrayDeque.isEmpty()) { + needSync = true; + break; + } + } } - CullingHandler.CHUNK_CULLING_MAP.queueUpdateCount++; } public static void update(Viewport viewport, float searchDistance, boolean useOcclusionCulling) { - if(CullingHandler.renderingShader()) { + if (CullingHandler.renderingShader()) { SodiumSectionAsyncUtil.shadowViewport = viewport; SodiumSectionAsyncUtil.shadowSearchDistance = searchDistance; SodiumSectionAsyncUtil.shadowUseOcclusionCulling = useOcclusionCulling; @@ -73,6 +86,12 @@ public static VisibleChunkCollector getShadowCollector() { return SodiumSectionAsyncUtil.shadowCollector; } + public static void shouldUpdate() { + if (shouldUpdate.availablePermits() < 1) { + shouldUpdate.release(); + } + } + public static class AsynchronousChunkCollector extends VisibleChunkCollector { private final HashMap renderListMap = new HashMap<>(); private final EnumMap> syncRebuildLists; @@ -108,8 +127,8 @@ public void visit(RenderSection section, boolean visible) { @Override public Map> getRebuildLists() { super.getRebuildLists().forEach(((chunkUpdateType, renderSections) -> { - for(RenderSection section : renderSections) { - if (!section.isDisposed()) { + for (RenderSection section : renderSections) { + if (!section.isDisposed() && section.getBuildCancellationToken() == null) { syncRebuildLists.get(chunkUpdateType).add(section); } } diff --git a/src/main/resources/assets/brute_force_rendering_culling/lang/en_us.json b/src/main/resources/assets/brute_force_rendering_culling/lang/en_us.json index ecdadad..660f42d 100644 --- a/src/main/resources/assets/brute_force_rendering_culling/lang/en_us.json +++ b/src/main/resources/assets/brute_force_rendering_culling/lang/en_us.json @@ -23,12 +23,12 @@ "brute_force_rendering_culling.disable": "Disable", "brute_force_rendering_culling.detail.cull_entity": "Cull entities visually invisible", "brute_force_rendering_culling.detail.cull_chunk": "Cull chunks visually invisible", - "brute_force_rendering_culling.detail.async": "Asynchronously updates visible chunks in a separate thread and synchronizes with the main rendering thread. This can accelerate chunk loading speed during movement and improve frame rates.\n\nYou can increase the number of threads for loading blocks in the game settings to assist with this functionality. In the testing phase, if the game crashes during chunk loading, please try turning off this setting.", - "brute_force_rendering_culling.detail.sampler": "Scaling ratio of the depth texture used for culling. Higher ratios result in more precise culling and better effects. \n\nDevices with better graphics card performance or lower game resolutions can increase this value. Not recommended to be below 20%.", - "brute_force_rendering_culling.detail.culling_map_update_delay": "Frames delayed before culling texture updates to the CPU, preventing main thread stutter caused by incomplete data transmission. \n\nDebug by observing culling map update times.\n\nEnabling shaders will slow down data transmission, resulting in at least 1 frame delay.", + "brute_force_rendering_culling.detail.async": "Asynchronously updates visible chunks in a separate thread and synchronizes with the main rendering thread. \nThis can accelerate chunk loading speed during movement and improve frame rates.\n\nYou can increase the number of threads for loading blocks in the game settings to assist with this functionality. \nIn the testing phase, if the game crashes during chunk loading, please try turning off this setting.", + "brute_force_rendering_culling.detail.sampler": "The scaling ratio of the depth texture used for culling. The higher the ratio, the more accurate the culling and the better the effect.\n\nIf increasing the ratio has no negative impact on frame rate, it can be increased as much as possible. Not recommended to be below 20%.", + "brute_force_rendering_culling.detail.culling_map_update_delay": "The number of frames delayed before the culling texture is updated to the CPU, preventing main thread stutter caused by incomplete data transmission. \nWhen the value is high, the block flickering phenomenon caused by rotating the field of view will become more severe.\n\nDebug by observing culling map update times. \nEnabling shaders will slow down data transmission, resulting in at least 1 frame delay.", "brute_force_rendering_culling.detail.check_texture": "For testing purposes, enables checking of depth and culling texture functionality when the data monitoring panel is open.", "brute_force_rendering_culling.detail.debug": "For testing purposes, effective only in vanilla Minecraft, used to view culled chunks.", - "brute_force_rendering_culling.detail.nvidium": "warn:Incompatible with Nvidium", + "brute_force_rendering_culling.detail.nvidium": "warn:Incompatible with Nvidium's Async bfs feature", "brute_force_rendering_culling.detail.sodium": "warn:This feature requires of Sodium(Embeddium).", "brute_force_rendering_culling.detail.gl33": "warn:Need OpenGL 3.3 supported", diff --git a/src/main/resources/assets/brute_force_rendering_culling/lang/zh_cn.json b/src/main/resources/assets/brute_force_rendering_culling/lang/zh_cn.json index 6ffd4ff..074600c 100644 --- a/src/main/resources/assets/brute_force_rendering_culling/lang/zh_cn.json +++ b/src/main/resources/assets/brute_force_rendering_culling/lang/zh_cn.json @@ -23,12 +23,12 @@ "brute_force_rendering_culling.disable": "关闭", "brute_force_rendering_culling.detail.cull_entity": "剔除视觉上不可见的实体", "brute_force_rendering_culling.detail.cull_chunk": "剔除视觉上不可见的区块", - "brute_force_rendering_culling.detail.async": "使用独立线程异步更新可见区块,并同步到主渲染线程。可以加速移动时的区块构建速度,提升帧数。\n\n可以适当提高游戏设置的多线程加载区块数量辅助此功能。处于测试阶段,如在加载区块时崩溃请尝试关掉此设置。", - "brute_force_rendering_culling.detail.sampler": "剔除所用深度纹理的缩放比例,比例越高剔除越精准、效果越好。\n\n显卡性能较好的设备、游戏分辨率较低的设备可以拉高此数值。不建议低于20%。", - "brute_force_rendering_culling.detail.culling_map_update_delay": "剔除纹理更新到CPU之前所推迟的帧数,防止数据未完全传输造成主线程卡顿。\n\n可观察剔除图更新耗时进行调试。\n\n开启光影会使数据传输变慢,至少会有1帧延迟。", + "brute_force_rendering_culling.detail.async": "使用独立线程异步更新可见区块,并同步到主渲染线程。\n可以加速移动时的区块构建速度,提升帧数。\n\n可以适当提高游戏设置的多线程加载区块数量辅助此功能。\n处于测试阶段,如在加载区块时崩溃请尝试关掉此设置。", + "brute_force_rendering_culling.detail.sampler": "剔除所用深度纹理的缩放比例,比例越高剔除越精准、效果越好。\n\n如果提高比例之后对帧数无负面影响,能提多高提多高。不建议低于20%。", + "brute_force_rendering_culling.detail.culling_map_update_delay": "剔除纹理更新到CPU之前所推迟的帧数,防止数据未完全传输造成主线程卡顿。\n数值较高时,旋转视角造成的区块闪烁现象会变得严重。\n\n可观察剔除图更新耗时进行调试。\n开启光影会使数据传输变慢,至少会有1帧延迟。", "brute_force_rendering_culling.detail.check_texture": "测试用,开启数据监控面板时可以查看深度纹理与剔除纹理工作是否正常。", "brute_force_rendering_culling.detail.debug": "测试用,仅在原版生效,用于查看被剔除区块。", - "brute_force_rendering_culling.detail.nvidium": "warn:无法与Nvidium共用", + "brute_force_rendering_culling.detail.nvidium": "warn:无法与Nvidium的Async bfs功能共用", "brute_force_rendering_culling.detail.sodium": "warn:此功能需要Sodium(Embeddium)", "brute_force_rendering_culling.detail.gl33": "warn:需要显卡支持OpenGL 3.3", diff --git a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.fsh b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.fsh index b4fec29..55136de 100644 --- a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.fsh +++ b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.fsh @@ -10,11 +10,11 @@ uniform mat4 CullingViewMat; uniform mat4 CullingProjMat; uniform vec3 CullingCameraPos; uniform vec3 CullingCameraDir; -uniform float CullingFov; uniform vec3 FrustumPos; uniform float RenderDistance; uniform int LevelHeightOffset; uniform int LevelMinSection; +uniform float BoxScale; flat in int spacePartitionSize; flat in vec4[6] frustum; @@ -130,8 +130,7 @@ void main() { chunkPos = vec3(chunkPos.x, chunkY*16, chunkPos.z)+vec3(8.0); float chunkCenterDepth = worldToScreenSpace(moveTowardsCamera(chunkPos, 16)).z; - - if (calculateDistance(chunkPos, CullingCameraPos) < 256) { + if (calculateDistance(chunkPos, CullingCameraPos) < 1024) { fragColor = vec4(1.0, 1.0, 1.0, 1.0); return; } @@ -141,62 +140,83 @@ void main() { return; } + float sizeOffset = 16.0; vec3 aabb[8] = vec3[]( - chunkPos+vec3(-8.0, -8.0, -8.0), chunkPos+vec3(8.0, -8.0, -8.0), - chunkPos+vec3(-8.0, 8.0, -8.0), chunkPos+vec3(8.0, 8.0, -8.0), - chunkPos+vec3(-8.0, -8.0, 8.0), chunkPos+vec3(8.0, -8.0, 8.0), - chunkPos+vec3(-8.0, 8.0, 8.0), chunkPos+vec3(8.0, 8.0, 8.0) + chunkPos+vec3(-sizeOffset, -sizeOffset, -sizeOffset), chunkPos+vec3(sizeOffset, -sizeOffset, -sizeOffset), + chunkPos+vec3(-sizeOffset, sizeOffset, -sizeOffset), chunkPos+vec3(sizeOffset, sizeOffset, -sizeOffset), + chunkPos+vec3(-sizeOffset, -sizeOffset, sizeOffset), chunkPos+vec3(sizeOffset, -sizeOffset, sizeOffset), + chunkPos+vec3(-sizeOffset, sizeOffset, sizeOffset), chunkPos+vec3(sizeOffset, sizeOffset, sizeOffset) ); - float maxX = -1; - float maxY = -1; - float minX = 1; - float minY = 1; + float maxX = -0.1; + float maxY = -0.1; + float minX = 1.1; + float minY = 1.1; bool inside = false; - float fovRadians = radians(CullingFov); - float halfFovRadians = fovRadians / 2.0; - float cosHalfFov = cos(halfFovRadians); + vec3 colmun0 = CullingViewMat[0].xyz; + vec3 colmun1 = CullingViewMat[1].xyz; + vec3 colmun2 = CullingViewMat[2].xyz; + + vec3 cameraUp = vec3(colmun0.y, colmun1.y, colmun2.y); + vec3 cameraRight = vec3(colmun0.x, colmun1.x, colmun2.x); for (int i = 0; i < 8; ++i) { - if(dot(normalize(aabb[i] - CullingCameraPos), normalize(CullingCameraDir)) < cosHalfFov) { - continue; + vec3 screenPos = worldToScreenSpace(aabb[i]); + if (screenPos.x >= 0 && screenPos.x <= 1 + && screenPos.y >= 0 && screenPos.y <= 1 + && screenPos.z >= 0 && screenPos.z <= 1) { + } else { - inside = true; + vec3 vectorDir = normalize(aabb[i]-CullingCameraPos); + + float xDot = dot(vectorDir, cameraRight); + if (xDot < 0.0 && screenPos.x > 0.5) { + screenPos = vec3(0.0, screenPos.y, screenPos.z); + } + if (xDot > 0.0 && screenPos.x < 0.5) { + screenPos = vec3(1.0, screenPos.y, screenPos.z); + } + + float yDot = dot(vectorDir, cameraUp); + if (yDot < 0.0 && screenPos.y > 0.5) { + screenPos = vec3(screenPos.x, 0.0, screenPos.z); + } + if (yDot > 0.0 && screenPos.y < 0.5) { + screenPos = vec3(screenPos.x, 1.0, screenPos.z); + } } - vec3 screenPos = worldToScreenSpace(aabb[i]); - if(screenPos.x > maxX) + if (screenPos.x > maxX) maxX = screenPos.x; - if(screenPos.y > maxY) + if (screenPos.y > maxY) maxY = screenPos.y; - if(screenPos.x < minX) + if (screenPos.x < minX) minX = screenPos.x; - if(screenPos.y < minY) + if (screenPos.y < minY) minY = screenPos.y; } - float chunkDepth = LinearizeDepth(chunkCenterDepth); + float chunkDepth = LinearizeDepth(chunkCenterDepth)-BoxScale; if(chunkDepth < 0) { fragColor = vec4(1.0, 1.0, 1.0, 1.0); return; } - if (!inside) { - fragColor = vec4(0.0, 0.0, 1.0, 1.0); - return; - } + minX = min(1.0, max(0.0, minX)); + maxX = min(1.0, max(0.0, maxX)); + maxY = min(1.0, max(0.0, maxY)); + minY = min(1.0, max(0.0, minY)); - int idx = getSampler( - min(1.0, max(0.0, maxX))-min(1.0, max(0.0, minX)), - min(1.0, max(0.0, maxY))-min(1.0, max(0.0, minY))); + int idx = getSampler(maxX-minX, + maxY-minY); float xStep = 1.0/DepthScreenSize[idx].x; float yStep = 1.0/DepthScreenSize[idx].y; - minX = min(1.0, max(0.0, minX-xStep)); - maxX = min(1.0, max(0.0, maxX+xStep)); - maxY = min(1.0, max(0.0, maxY+yStep)); - minY = min(1.0, max(0.0, minY-yStep)); + minX = max(minX-xStep, 0.0); + maxX = min(maxX+xStep, 1.0); + minY = max(minY-yStep, 0.0); + maxY = min(maxY+yStep, 1.0); for(float x = minX; x <= maxX; x += xStep) { for(float y = minY; y <= maxY; y += yStep) { diff --git a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.json b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.json index 159ca5a..69feefe 100644 --- a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.json +++ b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/chunk_culling.json @@ -22,7 +22,7 @@ { "name": "DepthSize", "type": "float", "count": 8, "values": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] }, { "name": "CullingCameraPos", "type": "float", "count": 3, "values": [ 1.0, 1.0, 1.0] }, { "name": "CullingCameraDir", "type": "float", "count": 3, "values": [ 1.0, 1.0, 1.0] }, - { "name": "CullingFov", "type": "float", "count": 1, "values": [ 90.0] }, + { "name": "BoxScale", "type": "float", "count": 1, "values": [ 2.0 ] }, { "name": "FrustumPos", "type": "float", "count": 3, "values": [ 1.0, 1.0, 1.0] }, { "name": "RenderDistance", "type": "float", "count": 1, "values": [ 0.0] }, { "name": "LevelHeightOffset", "type": "int", "count": 1, "values": [ 16 ] }, diff --git a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/entity_culling.fsh b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/entity_culling.fsh index 94cca65..d7c96f3 100644 --- a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/entity_culling.fsh +++ b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/entity_culling.fsh @@ -4,7 +4,6 @@ uniform vec2 EntityCullingSize; uniform mat4 CullingViewMat; uniform vec3 CullingCameraPos; uniform vec3 CullingCameraDir; -uniform float CullingFov; uniform mat4 CullingProjMat; uniform float DepthOffset; uniform vec3 FrustumPos; @@ -124,22 +123,43 @@ void main() { Pos+vec3(-halfWidth, halfHeight, halfWidth), Pos+vec3(halfWidth, halfHeight, halfWidth) ); - float maxX = -1; - float maxY = -1; - float minX = 1; - float minY = 1; + float maxX = -0.1; + float maxY = -0.1; + float minX = 1.1; + float minY = 1.1; bool inside = false; - float fovRadians = radians(CullingFov); - float halfFovRadians = fovRadians / 2.0; - float cosHalfFov = cos(halfFovRadians); + vec3 colmun0 = CullingViewMat[0].xyz; + vec3 colmun1 = CullingViewMat[1].xyz; + vec3 colmun2 = CullingViewMat[2].xyz; + + vec3 cameraUp = vec3(colmun0.y, colmun1.y, colmun2.y); + vec3 cameraRight = vec3(colmun0.x, colmun1.x, colmun2.x); for (int i = 0; i < 8; ++i) { - if (dot(normalize(aabb[i] - CullingCameraPos), normalize(CullingCameraDir)) < cosHalfFov) { - continue; - } else { + vec3 screenPos = worldToScreenSpace(aabb[i]); + if (screenPos.x >= 0 && screenPos.x <= 1 + && screenPos.y >= 0 && screenPos.y <= 1 + && screenPos.z >= 0 && screenPos.z <= 1) { inside = true; + } else { + vec3 vectorDir = normalize(aabb[i]-CullingCameraPos); + + float xDot = dot(vectorDir, cameraRight); + if (xDot < 0.0 && screenPos.x > 0.5) { + screenPos = vec3(0.0, screenPos.y, screenPos.z); + } + if (xDot > 0.0 && screenPos.x < 0.5) { + screenPos = vec3(1.0, screenPos.y, screenPos.z); + } + + float yDot = dot(vectorDir, cameraUp); + if (yDot < 0.0 && screenPos.y > 0.5) { + screenPos = vec3(screenPos.x, 0.0, screenPos.z); + } + if (yDot > 0.0 && screenPos.y < 0.5) { + screenPos = vec3(screenPos.x, 1.0, screenPos.z); + } } - vec3 screenPos = worldToScreenSpace(aabb[i]); if (screenPos.x > maxX) maxX = screenPos.x; @@ -156,17 +176,21 @@ void main() { return; } - int idx = getSampler( - min(1.0, max(0.0, maxX))-min(1.0, max(0.0, minX)), - min(1.0, max(0.0, maxY))-min(1.0, max(0.0, minY))); + minX = min(1.0, max(0.0, minX)); + maxX = min(1.0, max(0.0, maxX)); + maxY = min(1.0, max(0.0, maxY)); + minY = min(1.0, max(0.0, minY)); + + int idx = getSampler(maxX-minX, + maxY-minY); float xStep = 1.0/DepthScreenSize[idx].x; float yStep = 1.0/DepthScreenSize[idx].y; - minX = min(1.0, max(0.0, minX-xStep)); - maxX = min(1.0, max(0.0, maxX+xStep)); - maxY = min(1.0, max(0.0, maxY+yStep)); - minY = min(1.0, max(0.0, minY-yStep)); + minX = max(minX-xStep, 0.0); + maxX = min(maxX+xStep, 1.0); + minY = max(minY-yStep, 0.0); + maxY = min(maxY+yStep, 1.0); float entityDepth = LinearizeDepth(worldToScreenSpace(moveTowardsCamera(Pos, sqrt(halfWidth*halfWidth+halfWidth*halfWidth))).z); for (float x = minX; x <= maxX; x += xStep) { diff --git a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/instanced_entity_culling.json b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/instanced_entity_culling.json index 51bc03a..22b1bf2 100644 --- a/src/main/resources/assets/brute_force_rendering_culling/shaders/core/instanced_entity_culling.json +++ b/src/main/resources/assets/brute_force_rendering_culling/shaders/core/instanced_entity_culling.json @@ -19,7 +19,6 @@ { "name": "EntityCullingSize", "type": "float", "count": 2, "values": [1.0, 1.0] }, { "name": "CullingCameraDir", "type": "float", "count": 3, "values": [ 1.0, 1.0, 1.0] }, { "name": "CullingCameraPos", "type": "float", "count": 3, "values": [ 1.0, 1.0, 1.0 ] }, - { "name": "CullingFov", "type": "float", "count": 1, "values": [ 90.0] }, { "name": "DepthSize", "type": "float", "count": 8, "values": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] }, { "name": "FrustumPos", "type": "float", "count": 3, "values": [ 1.0, 1.0, 1.0] }, { "name": "CullingFrustum", "type": "float", "count": 24, "values": [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index b6bc473..d986f0f 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "brute_force_rendering_culling", - "version": "0.5.4", + "version": "0.5.5", "name": "Brute force Rendering Culling", "description": "", "authors": [