diff --git a/README.md b/README.md index a35e79b4..450699bc 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,19 @@ -# Nvidium +This is an unofficial fork of the Nvidium mod, porting it to NeoForge. The original mod's author is cortex. +Links to the author: -[![Modrinth](https://img.shields.io/modrinth/dt/nvidium?logo=modrinth)](https://modrinth.com/mod/nvidium) +https://modrinth.com/user/cortex -Nvidium is an alternate rendering backing for sodium, it uses cutting edge nvidia features to render huge amounts of -terrain geometry at very playable framerates. +https://github.com/MCRcortex -### Requires sodium and an nvidia gtx 1600 series or newer to run (turing+ architecture) \ No newline at end of file +Link to the original mod: + +https://modrinth.com/mod/nvidium + +# Nvidium [Neoforge] UNOFFICIAL + + + + +Nothing from the mod was cut or changed in terms of logic. Everything remains as before, but now on the previously unsupported Neoforge. + +### The mod still only supports Nvidia graphics cards, and still only from the 16xx series and above. diff --git a/build.gradle b/build.gradle index a6119c0b..00e69133 100644 --- a/build.gradle +++ b/build.gradle @@ -1,78 +1,111 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge build system. + * Licensed under LGPL-3.0-only + */ + + + plugins { - id 'fabric-loom' version '1.7-SNAPSHOT' + id 'java-library' id 'maven-publish' + + id 'net.neoforged.moddev' version '1.0.17' } -def gitCommitHash = { -> - def stdout = new ByteArrayOutputStream() - exec { - commandLine 'git', 'rev-parse', '--short', 'HEAD' - standardOutput = stdout - } - return stdout.toString().trim() +tasks.named('wrapper', Wrapper) { + distributionType = Wrapper.DistributionType.BIN } -def buildtime = System.currentTimeSeconds() version = project.mod_version -group = project.maven_group +group = project.mod_group_id -sourceCompatibility = JavaVersion.VERSION_21 -targetCompatibility = JavaVersion.VERSION_21 +repositories { + mavenLocal() + mavenCentral() + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + + maven { url "https://maven.irisshaders.net/"} +} + + +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + + +neoForge { + version = project.neoforge_version -apply plugin: "fabric-loom" -loom { - mixin.defaultRefmapName = "nvidium.refmap.json" runs { - it.configureEach { - vmArgs("-Xmx8G", "-XX:+UseZGC") + client { + client() + + jvmArguments.addAll("-Xmx8G", "-XX:+UseZGC") + } + server { + server() } } -} + mods { -processResources { - inputs.properties("version": project.version, "commit": gitCommitHash, "buildtime":buildtime) - - archivesBaseName = "nvidium" - filesMatching("fabric.mod.json") { - expand "commit": gitCommitHash, "version": project.version, "buildtime": buildtime + "${project.mod_id}" { + sourceSet(sourceSets.main) + } } } -repositories { - exclusiveContent { - forRepository { - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - } - } - filter { - includeGroup "maven.modrinth" + +def gitCommitHash = { -> + def stdout = new ByteArrayOutputStream() + try { + exec { + commandLine 'git', 'rev-parse', '--short', 'HEAD' + standardOutput = stdout } + return stdout.toString().trim() + } catch (Exception e) { + return "unknown" + } +} + + +processResources { + def buildProps = [ + "version": project.version, + "commit": gitCommitHash(), + "minecraft_version": project.minecraft_version, + "mod_id": project.mod_id + ] + + + filesMatching("META-INF/neoforge.mods.toml") { + expand buildProps } + inputs.properties(buildProps) } dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - // Fabric API - modImplementation(fabricApi.module("fabric-api-base", project.fabric_version)) - modImplementation(fabricApi.module("fabric-block-view-api-v2", project.fabric_version)) - modImplementation(fabricApi.module("fabric-rendering-fluids-v1", project.fabric_version)) - modImplementation("net.fabricmc.fabric-api:fabric-rendering-data-attachment-v1:0.3.40+73761d2e3b") - modImplementation(fabricApi.module("fabric-resource-loader-v0", project.fabric_version)) + // --- Sodium --- + + implementation "maven.modrinth:sodium:mc1.21.1-0.6.13-neoforge" + + // --- Iris (Optional) --- + compileOnly "maven.modrinth:iris:${project.iris_version}" - modImplementation "maven.modrinth:sodium:mc1.21-0.5.11" - //modImplementation "maven.modrinth:c2me-fabric:0.2.0+alpha.10.49+1.19.4" - //modImplementation "maven.modrinth:chunks-fade-in:v1.0.3-1.19.4" - //modImplementation "maven.modrinth:immersiveportals:v2.7.3-mc1.19.4" - modCompileOnly "maven.modrinth:iris:1.7.0+1.20.6" } + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index a0a7780a..7797bd2d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,20 @@ -# Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G -# Fabric Properties -# check these on https://modmuss50.me/fabric.html +# Nvidium Properties +# Modified by 1Influence for NeoForge port -minecraft_version=1.21 -yarn_mappings=1.21+build.2 -loader_version=0.15.11 +org.gradle.jvmargs=-Xmx2G -Dfile.encoding=UTF-8 -#Fabric api -fabric_version=0.100.1+1.21 -# Mod Properties mod_version=0.3.0 -maven_group=me.cortex -archives_base_name=nvidium -# Dependencies -# check this on https://modmuss50.me/fabric.html +mod_group_id=me.cortex +mod_id=nvidium + + +minecraft_version=1.21 + +neoforge_version=21.0.167 + + + +sodium_version=mc1.21.1-0.6.13-neoforge + +iris_version=1.8.12+1.21.1-neoforge \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index b02216ba..c5cc2a33 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,22 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge build system. + * Licensed under LGPL-3.0-only + */ + pluginManagement { repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - mavenCentral() gradlePluginPortal() + mavenCentral() + maven { url = 'https://maven.neoforged.net/releases' } + } } + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} + +rootProject.name = 'nvidium' \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/Nvidium.java b/src/main/java/me/cortex/nvidium/Nvidium.java index b2a1dbf3..5b96efa6 100644 --- a/src/main/java/me/cortex/nvidium/Nvidium.java +++ b/src/main/java/me/cortex/nvidium/Nvidium.java @@ -1,10 +1,21 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium; import me.cortex.nvidium.config.NvidiumConfig; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; -import net.minecraft.util.Util; +import net.minecraft.Util; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.neoforge.common.NeoForge; import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GLCapabilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,41 +24,46 @@ public class Nvidium { public static final Logger LOGGER = LoggerFactory.getLogger("Nvidium"); public static boolean IS_COMPATIBLE = false; public static boolean IS_ENABLED = false; - public static boolean IS_DEBUG = System.getProperty("nvidium.isDebug", "false").equals("TRUE"); + public static boolean IS_DEBUG = Boolean.parseBoolean(System.getProperty("nvidium.isDebug", "false")); public static boolean SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER = true; public static boolean FORCE_DISABLE = false; public static NvidiumConfig config = NvidiumConfig.loadOrCreate(); static { - ModContainer mod = (ModContainer) FabricLoader.getInstance().getModContainer("nvidium").orElseThrow(NullPointerException::new); - var version = mod.getMetadata().getVersion().getFriendlyString(); - var commit = mod.getMetadata().getCustomValue("commit").getAsString(); - MOD_VERSION = version+"-"+commit; + ModContainer mod = ModList.get().getModContainerById("nvidium") + .orElseThrow(() -> new NullPointerException("Nvidium mod container not found")); + var version = mod.getModInfo().getVersion().toString(); + var commit = "unknown"; + MOD_VERSION = version + "-" + commit; } public static void checkSystemIsCapable() { - var cap = GL.getCapabilities(); + GLCapabilities cap = GL.getCapabilities(); boolean supported = cap.GL_NV_mesh_shader && cap.GL_NV_uniform_buffer_unified_memory && cap.GL_NV_vertex_buffer_unified_memory && cap.GL_NV_representative_fragment_test && cap.GL_ARB_sparse_buffer && cap.GL_NV_bindless_multi_draw_indirect; + IS_COMPATIBLE = supported; + if (IS_COMPATIBLE) { LOGGER.info("All capabilities met"); } else { - LOGGER.warn("Not all requirements met, disabling nvidium"); + LOGGER.warn("Not all requirements met, disabling Nvidium"); } - if (IS_COMPATIBLE && Util.getOperatingSystem() == Util.OperatingSystem.LINUX) { - LOGGER.warn("Linux currently uses fallback terrain buffer due to driver inconsistencies, expect increase vram usage"); + + if (IS_COMPATIBLE && Util.getPlatform() == Util.OS.LINUX) { + LOGGER.warn("Linux currently uses fallback terrain buffer due to driver inconsistencies, expect increased VRAM usage"); SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER = false; } if (IS_COMPATIBLE) { LOGGER.info("Enabling Nvidium"); } + IS_ENABLED = IS_COMPATIBLE; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/NvidiumWorldRenderer.java b/src/main/java/me/cortex/nvidium/NvidiumWorldRenderer.java index 285b6584..56debfb6 100644 --- a/src/main/java/me/cortex/nvidium/NvidiumWorldRenderer.java +++ b/src/main/java/me/cortex/nvidium/NvidiumWorldRenderer.java @@ -1,3 +1,11 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium; import me.cortex.nvidium.gl.RenderDevice; @@ -6,24 +14,23 @@ import me.cortex.nvidium.sodiumCompat.NvidiumCompactChunkVertex; import me.cortex.nvidium.util.DownloadTaskStream; import me.cortex.nvidium.util.UploadingBufferStream; -import me.jellysquid.mods.sodium.client.SodiumClientMod; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderMatrices; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; -import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.impl.CompactChunkVertex; -import me.jellysquid.mods.sodium.client.render.viewport.Viewport; -import net.minecraft.client.render.Camera; -import net.minecraft.client.texture.Sprite; +import net.caffeinemc.mods.sodium.client.SodiumClientMod; +import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.caffeinemc.mods.sodium.client.render.viewport.frustum.Frustum; +import net.minecraft.client.Camera; +import net.minecraft.client.particle.SpriteSet; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4fc; -import org.joml.Matrix4x3fc; +import org.joml.Vector3d; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.lwjgl.opengl.GL11.glGetInteger; -import static org.lwjgl.opengl.GL11.glNewList; import static org.lwjgl.opengl.NVXGPUMemoryInfo.GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX; public class NvidiumWorldRenderer { @@ -41,9 +48,9 @@ public class NvidiumWorldRenderer { private long max_geometry_memory; private long last_sample_time; - //Note: the reason that asyncChunkTracker is passed in as an already constructed object is cause of the amount of argmuents it takes to construct it + //Note: the reason that asyncChunkTracker is passed in as an already constructed object is cause of the amount of arguments it takes to construct it public NvidiumWorldRenderer(AsyncOcclusionTracker asyncChunkTracker) { - int frames = SodiumClientMod.options().advanced.cpuRenderAheadLimit+1; + int frames = SodiumClientMod.options().advanced.cpuRenderAheadLimit + 1; //32 mb upload buffer this.uploadStream = new UploadingBufferStream(device, 32000000); //8 mb download buffer @@ -51,10 +58,9 @@ public NvidiumWorldRenderer(AsyncOcclusionTracker asyncChunkTracker) { update_allowed_memory(); //this.sectionManager = new SectionManager(device, max_geometry_memory*1024*1024, uploadStream, 150, 24, CompactChunkVertex.STRIDE); - this.sectionManager = new SectionManager(device, max_geometry_memory*1024*1024, uploadStream, NvidiumCompactChunkVertex.STRIDE, this); + this.sectionManager = new SectionManager(device, max_geometry_memory * 1024 * 1024, uploadStream, NvidiumCompactChunkVertex.STRIDE, this); this.renderPipeline = new RenderPipeline(device, uploadStream, downloadStream, sectionManager); - this.asyncChunkTracker = asyncChunkTracker; } @@ -77,7 +83,10 @@ public void reloadShaders() { renderPipeline.reloadShaders(); } - public void renderFrame(Viewport viewport, ChunkRenderMatrices matrices, double x, double y, double z) { + public void renderFrame(ChunkRenderMatrices matrices, double x, double y, double z) { + + Viewport viewport = new Viewport((Frustum) matrices.modelView(), (Vector3d) matrices.projection()); + renderPipeline.renderFrame(viewport, matrices, x, y, z); while (sectionManager.terrainAreana.getUsedMB() > (max_geometry_memory - 100)) { @@ -103,14 +112,14 @@ public void uploadBuildResult(ChunkBuildOutput buildOutput) { } public void addDebugInfo(ArrayList debugInfo) { - debugInfo.add("Using nvidium renderer: "+ Nvidium.MOD_VERSION); + debugInfo.add("Using nvidium renderer: " + Nvidium.MOD_VERSION); /* debugInfo.add("Memory limit: " + max_geometry_memory + " mb"); debugInfo.add("Terrain Memory MB: " +); debugInfo.add(String.format("Fragmentation: %.2f", sectionManager.terrainAreana.getFragmentation()*100)); debugInfo.add("Regions: " + sectionManager.getRegionManager().regionCount() + "/" + sectionManager.getRegionManager().maxRegions()); */ - debugInfo.add("Mem" + (Nvidium.SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER?"":" (fallback)") + ": " + (Nvidium.SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER?this.sectionManager.terrainAreana.getAllocatedMB():this.sectionManager.terrainAreana.getUsedMB()) + "/"+ this.max_geometry_memory + String.format(", F: %.2f", sectionManager.terrainAreana.getFragmentation()*100)); + debugInfo.add("Mem" + (Nvidium.SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER ? "" : " (fallback)") + ": " + (Nvidium.SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER ? this.sectionManager.terrainAreana.getAllocatedMB() : this.sectionManager.terrainAreana.getUsedMB()) + "/" + this.max_geometry_memory + String.format(", F: %.2f", sectionManager.terrainAreana.getFragmentation() * 100)); debugInfo.add("Regions: " + sectionManager.getRegionManager().regionCount() + "/" + sectionManager.getRegionManager().maxRegions()); if (this.asyncChunkTracker != null) { debugInfo.add("A-BFS: " + asyncChunkTracker.getIterationTime() + " Q: " + Arrays.toString(this.asyncChunkTracker.getBuildQueueSizes()));//Async BFS iteration time:, Build queue sizes: @@ -121,7 +130,7 @@ public void addDebugInfo(ArrayList debugInfo) { private void update_allowed_memory() { if (Nvidium.config.automatic_memory) { - max_geometry_memory = (glGetInteger(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX) / 1024) + (sectionManager==null?0:sectionManager.terrainAreana.getMemoryUsed()/(1024*1024)); + max_geometry_memory = (glGetInteger(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX) / 1024) + (sectionManager == null ? 0 : sectionManager.terrainAreana.getMemoryUsed() / (1024 * 1024)); max_geometry_memory -= 1024;//Minus 1gb of vram max_geometry_memory = Math.max(2048, max_geometry_memory);//Minimum 2 gb of vram } else { @@ -129,7 +138,7 @@ private void update_allowed_memory() { } } - public void update(Camera camera, Viewport viewport, int frame, boolean spectator) { + public void update(Camera camera, Viewport viewport, boolean spectator) { if (asyncChunkTracker != null) { asyncChunkTracker.update(viewport, camera, spectator); } @@ -156,11 +165,11 @@ public SectionManager getSectionManager() { } @Nullable - public Sprite[] getAnimatedSpriteSet() { + public SpriteSet[] getAnimatedSpriteSet() { if (asyncChunkTracker != null) { return asyncChunkTracker.getVisibleAnimatedSprites(); } else { - return new Sprite[0]; + return new SpriteSet[0]; } } @@ -179,7 +188,8 @@ public int getAsyncBfsVisibilityCount() { return -1; } } + public int getMaxGeometryMemory() { return (int) max_geometry_memory; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/RenderPipeline.java b/src/main/java/me/cortex/nvidium/RenderPipeline.java index 68bbc1a6..e1a7fae2 100644 --- a/src/main/java/me/cortex/nvidium/RenderPipeline.java +++ b/src/main/java/me/cortex/nvidium/RenderPipeline.java @@ -1,3 +1,11 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium; import com.mojang.blaze3d.platform.GlStateManager; @@ -15,10 +23,10 @@ import me.cortex.nvidium.util.DownloadTaskStream; import me.cortex.nvidium.util.TickableManager; import me.cortex.nvidium.util.UploadingBufferStream; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderMatrices; -import me.jellysquid.mods.sodium.client.render.viewport.Viewport; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.math.BlockPos; + +import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.minecraft.client.Minecraft; import org.joml.*; import org.lwjgl.opengl.GL11C; import org.lwjgl.system.MemoryUtil; @@ -180,8 +188,8 @@ public void renderFrame(Viewport frustum, ChunkRenderMatrices crm, double px, do //Clear the first gl error, not our fault //glGetError(); - int screenWidth = MinecraftClient.getInstance().getWindow().getFramebufferWidth(); - int screenHeight = MinecraftClient.getInstance().getWindow().getFramebufferHeight(); + int screenWidth = Minecraft.getInstance().getWindow().getScreenWidth(); + int screenHeight = Minecraft.getInstance().getWindow().getScreenHeight(); int visibleRegions = 0; @@ -294,7 +302,7 @@ public void renderFrame(Viewport frustum, ChunkRenderMatrices crm, double px, do addr += 4; MemoryUtil.memPutFloat(addr, RenderSystem.getShaderFogEnd());//FogEnd addr += 4; - MemoryUtil.memPutInt(addr, RenderSystem.getShaderFogShape().getId());//IsSphericalFog + MemoryUtil.memPutInt(addr, RenderSystem.getShaderFogShape().ordinal());//IsSphericalFog addr += 4; MemoryUtil.memPutShort(addr, (short) visibleRegions); addr += 2; @@ -454,7 +462,12 @@ public void renderTranslucent() { { glEnable(GL_DEPTH_TEST); RenderSystem.enableBlend(); - RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.blendFuncSeparate( + GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, + GlStateManager.SourceFactor.ONE, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA + ); translucencyTerrainRasterizer.raster(prevRegionCount, translucencyCommandBuffer.getDeviceAddress()); RenderSystem.disableBlend(); RenderSystem.defaultBlendFunc(); diff --git a/src/main/java/me/cortex/nvidium/api0/NvidiumAPI.java b/src/main/java/me/cortex/nvidium/api0/NvidiumAPI.java index cc0e82d4..77ace925 100644 --- a/src/main/java/me/cortex/nvidium/api0/NvidiumAPI.java +++ b/src/main/java/me/cortex/nvidium/api0/NvidiumAPI.java @@ -1,8 +1,16 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.api0; import me.cortex.nvidium.Nvidium; import me.cortex.nvidium.sodiumCompat.INvidiumWorldRendererGetter; -import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; import org.joml.Matrix4fc; import org.joml.Matrix4x3fc; diff --git a/src/main/java/me/cortex/nvidium/config/ConfigGuiBuilder.java b/src/main/java/me/cortex/nvidium/config/ConfigGuiBuilder.java index 424c8065..0be952a8 100644 --- a/src/main/java/me/cortex/nvidium/config/ConfigGuiBuilder.java +++ b/src/main/java/me/cortex/nvidium/config/ConfigGuiBuilder.java @@ -1,27 +1,36 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.config; import com.google.common.collect.ImmutableList; import me.cortex.nvidium.Nvidium; import me.cortex.nvidium.sodiumCompat.NvidiumOptionFlags; -import me.jellysquid.mods.sodium.client.gui.options.*; -import me.jellysquid.mods.sodium.client.gui.options.control.ControlValueFormatter; -import me.jellysquid.mods.sodium.client.gui.options.control.CyclingControl; -import me.jellysquid.mods.sodium.client.gui.options.control.SliderControl; -import me.jellysquid.mods.sodium.client.gui.options.control.TickBoxControl; -import net.minecraft.text.Text; +import net.caffeinemc.mods.sodium.client.gui.options.*; +import net.caffeinemc.mods.sodium.client.gui.options.control.ControlValueFormatter; +import net.caffeinemc.mods.sodium.client.gui.options.control.CyclingControl; +import net.caffeinemc.mods.sodium.client.gui.options.control.SliderControl; +import net.caffeinemc.mods.sodium.client.gui.options.control.TickBoxControl; +import net.minecraft.network.chat.Component; import java.util.ArrayList; import java.util.List; public class ConfigGuiBuilder { private static final NvidiumConfigStore store = new NvidiumConfigStore(); + public static void addNvidiumGui(List pages) { List groups = new ArrayList<>(); groups.add(OptionGroup.createBuilder() .add(OptionImpl.createBuilder(boolean.class, store) - .setName(Text.literal("Disable nvidium")) - .setTooltip(Text.literal("Used to disable nvidium (DOES NOT SAVE, WILL RE-ENABLE AFTER A RE-LAUNCH)")) + .setName(Component.literal("Disable nvidium")) + .setTooltip(Component.literal("Used to disable nvidium (DOES NOT SAVE, WILL RE-ENABLE AFTER A RE-LAUNCH)")) .setControl(TickBoxControl::new) .setImpact(OptionImpact.HIGH) .setBinding((opts, value) -> Nvidium.FORCE_DISABLE = value, opts -> Nvidium.FORCE_DISABLE) @@ -32,8 +41,8 @@ public static void addNvidiumGui(List pages) { if (Nvidium.IS_COMPATIBLE && !Nvidium.IS_ENABLED && !Nvidium.FORCE_DISABLE) { groups.add(OptionGroup.createBuilder() .add(OptionImpl.createBuilder(boolean.class, store) - .setName(Text.literal("Nvidium disabled due to shaders being loaded")) - .setTooltip(Text.literal("Nvidium disabled due to shaders being loaded")) + .setName(Component.literal("Nvidium disabled due to shaders being loaded")) + .setTooltip(Component.literal("Nvidium disabled due to shaders being loaded")) .setControl(TickBoxControl::new) .setImpact(OptionImpact.VARIES) .setBinding((opts, value) -> {}, opts -> false) @@ -41,106 +50,117 @@ public static void addNvidiumGui(List pages) { .build() ).build()); } + groups.add(OptionGroup.createBuilder() .add(OptionImpl.createBuilder(int.class, store) - .setName(Text.translatable("nvidium.options.region_keep_distance.name")) - .setTooltip(Text.translatable("nvidium.options.region_keep_distance.tooltip")) - .setControl(option -> new SliderControl(option, 32, 256, 1, x->Text.literal(x==32?"Vanilla":(x==256?"Keep All":x+" chunks")))) + .setName(Component.translatable("nvidium.options.region_keep_distance.name")) + .setTooltip(Component.translatable("nvidium.options.region_keep_distance.tooltip")) + .setControl(option -> new SliderControl(option, 32, 256, 1, + x -> Component.literal(x == 32 ? "Vanilla" : (x == 256 ? "Keep All" : x + " chunks")))) .setImpact(OptionImpact.VARIES) - .setEnabled(Nvidium.IS_ENABLED) + .setEnabled(() -> Nvidium.IS_ENABLED) .setBinding((opts, value) -> opts.region_keep_distance = value, opts -> opts.region_keep_distance) .setFlags() .build() - ).add(OptionImpl.createBuilder(boolean.class, store) - .setName(Text.translatable("nvidium.options.enable_temporal_coherence.name")) - .setTooltip(Text.translatable("nvidium.options.enable_temporal_coherence.tooltip")) + ) + .add(OptionImpl.createBuilder(boolean.class, store) + .setName(Component.translatable("nvidium.options.enable_temporal_coherence.name")) + .setTooltip(Component.translatable("nvidium.options.enable_temporal_coherence.tooltip")) .setControl(TickBoxControl::new) .setImpact(OptionImpact.MEDIUM) - .setEnabled(Nvidium.IS_ENABLED) + .setEnabled(() -> Nvidium.IS_ENABLED) .setBinding((opts, value) -> opts.enable_temporal_coherence = value, opts -> opts.enable_temporal_coherence) .setFlags() .build() - ).add(OptionImpl.createBuilder(boolean.class, store) - .setName(Text.translatable("nvidium.options.async_bfs.name")) - .setTooltip(Text.translatable("nvidium.options.async_bfs.tooltip")) + ) + .add(OptionImpl.createBuilder(boolean.class, store) + .setName(Component.translatable("nvidium.options.async_bfs.name")) + .setTooltip(Component.translatable("nvidium.options.async_bfs.tooltip")) .setControl(TickBoxControl::new) .setImpact(OptionImpact.HIGH) - .setEnabled(Nvidium.IS_ENABLED) + .setEnabled(() -> Nvidium.IS_ENABLED) .setBinding((opts, value) -> opts.async_bfs = value, opts -> opts.async_bfs) .setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD) .build() - ).add(OptionImpl.createBuilder(boolean.class, store) - .setName(Text.translatable("nvidium.options.automatic_memory_limit.name")) - .setTooltip(Text.translatable("nvidium.options.automatic_memory_limit.tooltip")) + ) + .add(OptionImpl.createBuilder(boolean.class, store) + .setName(Component.translatable("nvidium.options.automatic_memory_limit.name")) + .setTooltip(Component.translatable("nvidium.options.automatic_memory_limit.tooltip")) .setControl(TickBoxControl::new) .setImpact(OptionImpact.VARIES) - .setEnabled(Nvidium.IS_ENABLED) + .setEnabled(() -> Nvidium.IS_ENABLED) .setBinding((opts, value) -> opts.automatic_memory = value, opts -> opts.automatic_memory) .setFlags() - .build()) + .build() + ) .add(OptionImpl.createBuilder(int.class, store) - .setName(Text.translatable("nvidium.options.max_gpu_memory.name")) - .setTooltip(Text.translatable("nvidium.options.max_gpu_memory.tooltip")) - .setControl(option -> new SliderControl(option, 2048, 32768, 512, ControlValueFormatter.translateVariable("nvidium.options.mb"))) + .setName(Component.translatable("nvidium.options.max_gpu_memory.name")) + .setTooltip(Component.translatable("nvidium.options.max_gpu_memory.tooltip")) + .setControl(option -> new SliderControl(option, 2048, 32768, 512, + ControlValueFormatter.translateVariable("nvidium.options.mb"))) .setImpact(OptionImpact.VARIES) - .setEnabled(Nvidium.IS_ENABLED && !Nvidium.config.automatic_memory) + .setEnabled(() -> Nvidium.IS_ENABLED && !Nvidium.config.automatic_memory) .setBinding((opts, value) -> opts.max_geometry_memory = value, opts -> opts.max_geometry_memory) - .setFlags(Nvidium.SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER?new OptionFlag[0]:new OptionFlag[]{OptionFlag.REQUIRES_RENDERER_RELOAD}) + .setFlags(Nvidium.SUPPORTS_PERSISTENT_SPARSE_ADDRESSABLE_BUFFER ? new OptionFlag[0] : new OptionFlag[]{OptionFlag.REQUIRES_RENDERER_RELOAD}) .build() - ).add(OptionImpl.createBuilder(boolean.class, store) - .setName(Text.translatable("nvidium.options.render_fog.name")) - .setTooltip(Text.translatable("nvidium.options.render_fog.tooltip")) + ) + .add(OptionImpl.createBuilder(boolean.class, store) + .setName(Component.translatable("nvidium.options.render_fog.name")) + .setTooltip(Component.translatable("nvidium.options.render_fog.tooltip")) .setControl(TickBoxControl::new) .setBinding((opts, value) -> opts.render_fog = value, opts -> opts.render_fog) - .setEnabled(Nvidium.IS_ENABLED) + .setEnabled(() -> Nvidium.IS_ENABLED) .setImpact(OptionImpact.MEDIUM) .setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD) .build() - ).add(OptionImpl.createBuilder(TranslucencySortingLevel.class, store) - .setName(Text.translatable("nvidium.options.translucency_sorting.name")) - .setTooltip(Text.translatable("nvidium.options.translucency_sorting.tooltip")) + ) + .add(OptionImpl.createBuilder(TranslucencySortingLevel.class, store) + .setName(Component.translatable("nvidium.options.translucency_sorting.name")) + .setTooltip(Component.translatable("nvidium.options.translucency_sorting.tooltip")) .setControl( opts -> new CyclingControl<>( opts, TranslucencySortingLevel.class, - new Text[]{ - Text.translatable("nvidium.options.translucency_sorting.none"), - Text.translatable("nvidium.options.translucency_sorting.sections"), - Text.translatable("nvidium.options.translucency_sorting.quads") + new Component[]{ + Component.translatable("nvidium.options.translucency_sorting.none"), + Component.translatable("nvidium.options.translucency_sorting.sections"), + Component.translatable("nvidium.options.translucency_sorting.quads") } ) ) .setBinding((opts, value) -> opts.translucency_sorting_level = value, opts -> opts.translucency_sorting_level) - .setEnabled(Nvidium.IS_ENABLED) + .setEnabled(() -> Nvidium.IS_ENABLED) .setImpact(OptionImpact.MEDIUM) - //Technically, only need to reload when going from NONE->SECTIONS + // Technically, only need to reload when going from NONE->SECTIONS .setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD) .build() - ).add(OptionImpl.createBuilder(StatisticsLoggingLevel.class, store) - .setName(Text.translatable("nvidium.options.statistics_level.name")) - .setTooltip(Text.translatable("nvidium.options.statistics_level.tooltip")) + ) + .add(OptionImpl.createBuilder(StatisticsLoggingLevel.class, store) + .setName(Component.translatable("nvidium.options.statistics_level.name")) + .setTooltip(Component.translatable("nvidium.options.statistics_level.tooltip")) .setControl( opts -> new CyclingControl<>( opts, StatisticsLoggingLevel.class, - new Text[]{ - Text.translatable("nvidium.options.statistics_level.none"), - Text.translatable("nvidium.options.statistics_level.frustum"), - Text.translatable("nvidium.options.statistics_level.regions"), - Text.translatable("nvidium.options.statistics_level.sections"), - Text.translatable("nvidium.options.statistics_level.quads") + new Component[]{ + Component.translatable("nvidium.options.statistics_level.none"), + Component.translatable("nvidium.options.statistics_level.frustum"), + Component.translatable("nvidium.options.statistics_level.regions"), + Component.translatable("nvidium.options.statistics_level.sections"), + Component.translatable("nvidium.options.statistics_level.quads") } ) ) .setBinding((opts, value) -> opts.statistics_level = value, opts -> opts.statistics_level) - .setEnabled(Nvidium.IS_ENABLED) + .setEnabled(() -> Nvidium.IS_ENABLED) .setImpact(OptionImpact.LOW) .setFlags(NvidiumOptionFlags.REQUIRES_SHADER_RELOAD) .build() ) .build()); + if (Nvidium.IS_COMPATIBLE) { - pages.add(new OptionPage(Text.translatable("nvidium.options.pages.nvidium"), ImmutableList.copyOf(groups))); + pages.add(new OptionPage(Component.translatable("nvidium.options.pages.nvidium"), ImmutableList.copyOf(groups))); } } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/config/NvidiumConfig.java b/src/main/java/me/cortex/nvidium/config/NvidiumConfig.java index 634ff564..9616df9e 100644 --- a/src/main/java/me/cortex/nvidium/config/NvidiumConfig.java +++ b/src/main/java/me/cortex/nvidium/config/NvidiumConfig.java @@ -1,10 +1,18 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.config; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import me.cortex.nvidium.Nvidium; -import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.Minecraft; import java.io.FileReader; import java.io.IOException; @@ -28,7 +36,6 @@ public class NvidiumConfig { public StatisticsLoggingLevel statistics_level = StatisticsLoggingLevel.NONE; - private static final Gson GSON = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .setPrettyPrinting() @@ -36,6 +43,7 @@ public class NvidiumConfig { .create(); private NvidiumConfig() {} + public static NvidiumConfig loadOrCreate() { var path = getConfigPath(); if (Files.exists(path)) { @@ -58,8 +66,9 @@ public void save() { } private static Path getConfigPath() { - return FabricLoader.getInstance() - .getConfigDir() + + return Minecraft.getInstance().gameDirectory.toPath() + .resolve("config") .resolve("nvidium-config.json"); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/config/NvidiumConfigStore.java b/src/main/java/me/cortex/nvidium/config/NvidiumConfigStore.java index d48e46a9..caf05817 100644 --- a/src/main/java/me/cortex/nvidium/config/NvidiumConfigStore.java +++ b/src/main/java/me/cortex/nvidium/config/NvidiumConfigStore.java @@ -1,8 +1,17 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.config; import me.cortex.nvidium.Nvidium; import me.cortex.nvidium.config.NvidiumConfig; -import me.jellysquid.mods.sodium.client.gui.options.storage.OptionStorage; +import net.caffeinemc.mods.sodium.client.gui.options.storage.OptionStorage; + public class NvidiumConfigStore implements OptionStorage { private final NvidiumConfig config; diff --git a/src/main/java/me/cortex/nvidium/managers/AsyncOcclusionTracker.java b/src/main/java/me/cortex/nvidium/managers/AsyncOcclusionTracker.java index f3df829b..ff2680c9 100644 --- a/src/main/java/me/cortex/nvidium/managers/AsyncOcclusionTracker.java +++ b/src/main/java/me/cortex/nvidium/managers/AsyncOcclusionTracker.java @@ -1,20 +1,29 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.managers; import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.longs.Long2ReferenceMap; import me.cortex.nvidium.sodiumCompat.IRenderSectionExtension; -import me.jellysquid.mods.sodium.client.SodiumClientMod; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkUpdateType; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionFlags; -import me.jellysquid.mods.sodium.client.render.chunk.occlusion.OcclusionCuller; -import me.jellysquid.mods.sodium.client.render.viewport.Viewport; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.Camera; -import net.minecraft.client.texture.Sprite; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.world.World; +import net.caffeinemc.mods.sodium.client.SodiumClientMod; +import net.caffeinemc.mods.sodium.client.render.chunk.ChunkUpdateType; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionFlags; +import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.OcclusionCuller; +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.util.Mth; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -26,7 +35,7 @@ public class AsyncOcclusionTracker { private final OcclusionCuller occlusionCuller; private final Thread cullThread; - private final World world; + private final net.minecraft.world.level.Level world; private volatile boolean running = true; private volatile int frame = 0; @@ -36,7 +45,7 @@ public class AsyncOcclusionTracker { private final AtomicReference> atomicBfsResult = new AtomicReference<>(); private final AtomicReference> blockEntitySectionsRef = new AtomicReference<>(new ArrayList<>()); - private final AtomicReference visibleAnimatedSpritesRef = new AtomicReference<>(); + private final AtomicReference visibleAnimatedSpritesRef = new AtomicReference<>(); private final Map> outputRebuildQueue; @@ -46,7 +55,7 @@ public class AsyncOcclusionTracker { private volatile int chunkVisibilityCount = 0; - public AsyncOcclusionTracker(int renderDistance, Long2ReferenceMap sections, World world, Map> outputRebuildQueue) { + public AsyncOcclusionTracker(int renderDistance, Long2ReferenceMap sections, net.minecraft.world.level.Level world, Map> outputRebuildQueue) { this.occlusionCuller = new OcclusionCuller(sections, world); this.cullThread = new Thread(this::run); this.cullThread.setName("Cull thread"); @@ -59,7 +68,6 @@ public AsyncOcclusionTracker(int renderDistance, Long2ReferenceMap chunkUpdates = new ArrayList<>(); List blockEntitySections = new ArrayList<>(); - Set animatedSpriteSet = animateVisibleSpritesOnly?new HashSet<>():null; + Set animatedSpriteSet = animateVisibleSpritesOnly ? new HashSet<>() : null; int[] visibleGeometryCounter = new int[1]; - final OcclusionCuller.Visitor visitor = (section, visible) -> { - if (section.getPendingUpdate() != null && section.getBuildCancellationToken() == null) { - if ((!((IRenderSectionExtension)section).isSubmittedRebuild()) && !((IRenderSectionExtension)section).isSeen()) {//If it is in submission queue or seen dont enqueue + + final OcclusionCuller.Visitor visitor = (section) -> { + if (section.getPendingUpdate() != null) { + if ((!((IRenderSectionExtension)section).isSubmittedRebuild()) && !((IRenderSectionExtension)section).isSeen()) { + //If it is in submission queue or seen dont enqueue //Set that the section has been seen ((IRenderSectionExtension)section).isSeen(true); chunkUpdates.add(section); } } - if (!visible) { - return; - } - if ((section.getFlags()&(1< getLatestSectionsWithEntities() { } @Nullable - public Sprite[] getVisibleAnimatedSprites() { + public SpriteSet[] getVisibleAnimatedSprites() { return visibleAnimatedSpritesRef.get(); } @@ -234,4 +262,4 @@ public int[] getBuildQueueSizes() { public int getLastVisibilityCount() { return this.chunkVisibilityCount; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/managers/RegionManager.java b/src/main/java/me/cortex/nvidium/managers/RegionManager.java index e320206f..4b8d10fe 100644 --- a/src/main/java/me/cortex/nvidium/managers/RegionManager.java +++ b/src/main/java/me/cortex/nvidium/managers/RegionManager.java @@ -1,3 +1,11 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.managers; @@ -7,8 +15,9 @@ import me.cortex.nvidium.gl.buffers.IDeviceMappedBuffer; import me.cortex.nvidium.util.IdProvider; import me.cortex.nvidium.util.UploadingBufferStream; -import me.jellysquid.mods.sodium.client.render.viewport.Viewport; -import net.minecraft.util.math.ChunkSectionPos; + +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.minecraft.core.SectionPos; import org.lwjgl.system.MemoryUtil; import java.util.ArrayDeque; @@ -214,7 +223,7 @@ public void removeSection(int sectionId) { } public int allocateSection(int sectionX, int sectionY, int sectionZ) { - long regionKey = ChunkSectionPos.asLong(sectionX>>3, sectionY>>2, sectionZ>>3); + long regionKey = SectionPos.asLong(sectionX >> 3, sectionY >> 2, sectionZ >> 3); int regionId = this.regionMap.computeIfAbsent(regionKey, k -> this.idProvider.provide()); //The region doesnt exist so we must create a new one @@ -318,7 +327,7 @@ public void setRegionTransformId(int x, int y, int z, int id) { if (id < 0 || id >= MAX_TRANSFORMATION_COUNT) { throw new IllegalArgumentException("Transformation id out of bounds"); } - long regionKey = ChunkSectionPos.asLong(x, y, z); + long regionKey = SectionPos.asLong(x, y, z); int oldId = this.regionTransformationIdMapping.put(regionKey, id); if (oldId != id) { //The region has a new id so need to set and propagate the data @@ -358,7 +367,7 @@ private Region(int id, int rx, int ry, int rz) { Arrays.fill(this.id2pos, -1); MemoryUtil.memSet(sectionData, 0, 256 * SectionManager.SECTION_SIZE); - this.key = ChunkSectionPos.asLong(rx, ry, rz); + this.key = SectionPos.asLong(rx, ry, rz); this.id = id; this.rx = rx; diff --git a/src/main/java/me/cortex/nvidium/managers/RegionVisibilityTracker.java b/src/main/java/me/cortex/nvidium/managers/RegionVisibilityTracker.java index 91179b40..0f4736cd 100644 --- a/src/main/java/me/cortex/nvidium/managers/RegionVisibilityTracker.java +++ b/src/main/java/me/cortex/nvidium/managers/RegionVisibilityTracker.java @@ -1,3 +1,11 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.managers; import me.cortex.nvidium.gl.RenderDevice; @@ -5,7 +13,10 @@ import me.cortex.nvidium.gl.shader.Shader; import me.cortex.nvidium.sodiumCompat.ShaderLoader; import me.cortex.nvidium.util.DownloadTaskStream; -import net.minecraft.util.Identifier; + + +import net.minecraft.resources.ResourceLocation; + import org.lwjgl.system.MemoryUtil; import static me.cortex.nvidium.gl.shader.ShaderType.FRAGMENT; @@ -16,9 +27,10 @@ import static org.lwjgl.opengl.NVMeshShader.glDrawMeshTasksNV; public class RegionVisibilityTracker { + private final Shader shader = Shader.make() - .addSource(MESH, ShaderLoader.parse(Identifier.of("nvidium", "occlusion/queries/region/mesh.glsl"))) - .addSource(FRAGMENT, ShaderLoader.parse(Identifier.of("nvidium", "occlusion/queries/region/fragment.frag"))) + .addSource(MESH, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "occlusion/queries/region/mesh.glsl"))) + .addSource(FRAGMENT, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "occlusion/queries/region/fragment.frag"))) .compile(); private final DownloadTaskStream downStream; @@ -79,4 +91,4 @@ public int findMostLikelyLeastSeenRegion(int maxIndex) { } return id; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/managers/SectionManager.java b/src/main/java/me/cortex/nvidium/managers/SectionManager.java index 58335fb9..74389857 100644 --- a/src/main/java/me/cortex/nvidium/managers/SectionManager.java +++ b/src/main/java/me/cortex/nvidium/managers/SectionManager.java @@ -1,3 +1,11 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.managers; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; @@ -11,15 +19,17 @@ import me.cortex.nvidium.util.BufferArena; import me.cortex.nvidium.util.SegmentedManager; import me.cortex.nvidium.util.UploadingBufferStream; -import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.math.ChunkSectionPos; +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.caffeinemc.mods.sodium.client.util.NativeBuffer; +import net.minecraft.core.SectionPos; import org.joml.Vector3i; import org.joml.Vector4i; import org.lwjgl.system.MemoryUtil; +import java.nio.ByteBuffer; + public class SectionManager { public static final int SECTION_SIZE = 32; @@ -53,7 +63,7 @@ public void uploadChunkBuildResult(ChunkBuildOutput result) { var output = ((IRepackagedResult)result).getOutput(); RenderSection section = result.render; - long sectionKey = ChunkSectionPos.asLong(section.getChunkX(), section.getChunkY(), section.getChunkZ()); + long sectionKey = SectionPos.asLong(section.getChunkX(), section.getChunkY(), section.getChunkZ()); if (output == null || output.quads() == 0) { deleteSection(sectionKey); @@ -86,25 +96,27 @@ public void uploadChunkBuildResult(ChunkBuildOutput result) { this.section2terrain.put(sectionKey, terrainAddress); + + NativeBuffer geometryNativeBuffer = output.geometry(); + ByteBuffer geometryBuffer = geometryNativeBuffer.getDirectBuffer(); + long geometryUpload = terrainAreana.upload(uploadStream, terrainAddress); - MemoryUtil.memCopy(MemoryUtil.memAddress(output.geometry().getDirectBuffer()), geometryUpload, output.geometry().getLength()); - } + MemoryUtil.memCopy(MemoryUtil.memAddress(geometryBuffer), geometryUpload, geometryBuffer.remaining()); + } //Get the section id or allocate a new instance for it int sectionIdx = this.section2id.computeIfAbsent( sectionKey, - key -> this.regionManager.allocateSection(ChunkSectionPos.unpackX(key), ChunkSectionPos.unpackY(key), ChunkSectionPos.unpackZ(key)) + key -> this.regionManager.allocateSection(SectionPos.x(key), SectionPos.y(key), SectionPos.z(key)) ); - long metadata = regionManager.setSectionData(sectionIdx); boolean hideSectionBitSet = this.hiddenSectionKeys.contains(sectionKey); Vector3i min = output.min(); Vector3i size = output.size(); - //bits 18->26 taken by section id (used for translucency sorting/rendering) // 26->32 is free int px = section.getChunkX()<<8 | size.x<<4 | min.x; @@ -123,7 +135,7 @@ public void uploadChunkBuildResult(ChunkBuildOutput result) { } public void setHideBit(int x, int y, int z, boolean hide) { - long sectionKey = ChunkSectionPos.asLong(x, y, z); + long sectionKey = SectionPos.asLong(x, y, z); if (hide) { //Do a fast return if it was already hidden @@ -146,7 +158,7 @@ public void setHideBit(int x, int y, int z, boolean hide) { } public void deleteSection(RenderSection section) { - deleteSection(ChunkSectionPos.asLong(section.getChunkX(), section.getChunkY(), section.getChunkZ())); + deleteSection(SectionPos.asLong(section.getChunkX(), section.getChunkY(), section.getChunkZ())); } private void deleteSection(long sectionKey) { @@ -177,19 +189,15 @@ public RegionManager getRegionManager() { public void removeRegionById(int regionId) { if (!this.regionManager.regionExists(regionId)) return; long rk = this.regionManager.regionIdToKey(regionId); - int X = ChunkSectionPos.unpackX(rk)<<3; - int Y = ChunkSectionPos.unpackY(rk)<<2; - int Z = ChunkSectionPos.unpackZ(rk)<<3; + int X = SectionPos.x(rk) << 3; + int Y = SectionPos.y(rk) << 2; + int Z = SectionPos.z(rk) << 3; for (int x = X; x < X+8; x++) { for (int y = Y; y < Y+4; y++) { for (int z = Z; z < Z+8; z++) { - this.deleteSection(ChunkSectionPos.asLong(x, y, z)); + this.deleteSection(SectionPos.asLong(x, y, z)); } } } } -} - - - - +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/minecraft/LightMapAccessor.java b/src/main/java/me/cortex/nvidium/mixin/minecraft/LightMapAccessor.java index 0421c190..5c3eb359 100644 --- a/src/main/java/me/cortex/nvidium/mixin/minecraft/LightMapAccessor.java +++ b/src/main/java/me/cortex/nvidium/mixin/minecraft/LightMapAccessor.java @@ -1,12 +1,20 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.minecraft; -import net.minecraft.client.render.LightmapTextureManager; -import net.minecraft.client.texture.NativeImageBackedTexture; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.texture.DynamicTexture; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(LightmapTextureManager.class) +@Mixin(LightTexture.class) public interface LightMapAccessor { - @Accessor() - NativeImageBackedTexture getTexture(); -} + @Accessor("lightTexture") + DynamicTexture getTexture(); +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinBackgroundRenderer.java b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinBackgroundRenderer.java index 76e6cf07..b15f044d 100644 --- a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinBackgroundRenderer.java +++ b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinBackgroundRenderer.java @@ -1,15 +1,23 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.minecraft; import me.cortex.nvidium.Nvidium; -import net.minecraft.client.render.BackgroundRenderer; +import net.minecraft.client.renderer.FogRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; -@Mixin(BackgroundRenderer.class) - +@Mixin(FogRenderer.class) public class MixinBackgroundRenderer { - @ModifyConstant(method = "applyFog", constant = @Constant(floatValue = 192.0F)) + + @ModifyConstant(method = "setupFog", constant = @Constant(floatValue = 192.0F)) private static float changeFog(float fog) { if (Nvidium.IS_ENABLED) { return 9999999f; diff --git a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinGameRenderer.java b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinGameRenderer.java index 5858f06e..bc0e68e3 100644 --- a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinGameRenderer.java +++ b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinGameRenderer.java @@ -1,7 +1,15 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.minecraft; import me.cortex.nvidium.Nvidium; -import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.renderer.GameRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -9,8 +17,8 @@ @Mixin(GameRenderer.class) public class MixinGameRenderer { - @Inject(method = "getFarPlaneDistance", at = @At("HEAD"), cancellable = true) - public void method_32796(CallbackInfoReturnable cir) { + @Inject(method = "getDepthFar", at = @At("HEAD"), cancellable = true) + private void getDepthFar(CallbackInfoReturnable cir) { if (Nvidium.IS_ENABLED) { cir.setReturnValue(16 * 512f); cir.cancel(); diff --git a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWindow.java b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWindow.java index 481c983f..eb4c4955 100644 --- a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWindow.java +++ b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWindow.java @@ -1,10 +1,15 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.minecraft; +import com.mojang.blaze3d.platform.Window; import me.cortex.nvidium.Nvidium; -import net.minecraft.client.WindowEventHandler; -import net.minecraft.client.WindowSettings; -import net.minecraft.client.util.MonitorTracker; -import net.minecraft.client.util.Window; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -12,8 +17,8 @@ @Mixin(Window.class) public class MixinWindow { - @Inject(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL;createCapabilities()Lorg/lwjgl/opengl/GLCapabilities;", shift = At.Shift.AFTER)) - private void init(WindowEventHandler eventHandler, MonitorTracker monitorTracker, WindowSettings settings, String videoMode, String title, CallbackInfo ci) { + @Inject(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL;createCapabilities()Lorg/lwjgl/opengl/GLCapabilities;", shift = At.Shift.AFTER, remap = false), remap = false) + private void init(CallbackInfo ci) { Nvidium.checkSystemIsCapable(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWorldRenderer.java b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWorldRenderer.java index 2d27a764..fedaab0c 100644 --- a/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWorldRenderer.java +++ b/src/main/java/me/cortex/nvidium/mixin/minecraft/MixinWorldRenderer.java @@ -1,15 +1,24 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.minecraft; import me.cortex.nvidium.Nvidium; -import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.LevelRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -@Mixin(WorldRenderer.class) +@Mixin(LevelRenderer.class) public class MixinWorldRenderer { - @Redirect(method = "render", at = @At(value = "INVOKE", target = "Ljava/lang/Math;max(FF)F"), require = 0) + @Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Ljava/lang/Math;max(FF)F"), require = 0) private float redirectMax(float a, float b) { if (Nvidium.IS_ENABLED) { return a; @@ -17,13 +26,18 @@ private float redirectMax(float a, float b) { return Math.max(a, b); } - @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;getViewDistance()F")) - private float changeRD(GameRenderer instance) { - float viewDistance = instance.getViewDistance(); + @ModifyArg(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/FogRenderer;setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V", ordinal = 1), index = 2) + private float modifyRenderDistance(float original) { if (Nvidium.IS_ENABLED) { var dist = Nvidium.config.region_keep_distance * 16; - return dist == 32 * 16 ? viewDistance : (dist == 256 * 16 ? 9999999 : dist); + if (dist == 32 * 16) { + return original; + } else if (dist == 256 * 16) { + return 9999999; + } else { + return dist; + } } - return viewDistance; + return original; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuildOutput.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuildOutput.java index ec11d489..71015a38 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuildOutput.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuildOutput.java @@ -1,8 +1,16 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import me.cortex.nvidium.sodiumCompat.IRepackagedResult; import me.cortex.nvidium.sodiumCompat.RepackagedSectionOutput; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -11,20 +19,24 @@ @Mixin(value = ChunkBuildOutput.class, remap = false) public class MixinChunkBuildOutput implements IRepackagedResult { - @Unique private RepackagedSectionOutput repackagedSectionOutput; + @Unique + private RepackagedSectionOutput repackagedSectionOutput; + @Override public RepackagedSectionOutput getOutput() { return repackagedSectionOutput; } + @Override public void set(RepackagedSectionOutput output) { repackagedSectionOutput = output; } - @Inject(method = "delete", at = @At("HEAD")) + @Inject(method = "destroy", at = @At("HEAD")) private void cleanup(CallbackInfo ci) { if (repackagedSectionOutput != null) { repackagedSectionOutput.delete(); + repackagedSectionOutput = null; } } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilder.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilder.java index 3dcd0a00..4daaa765 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilder.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilder.java @@ -1,21 +1,40 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import me.cortex.nvidium.Nvidium; -import me.jellysquid.mods.sodium.client.render.chunk.compile.executor.ChunkBuilder; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.executor.ChunkBuilder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.util.List; +import org.spongepowered.asm.mixin.injection.ModifyArg; @Mixin(value = ChunkBuilder.class, remap = false) public class MixinChunkBuilder { - @Redirect(method = "getSchedulingBudget", at = @At(value = "INVOKE", target = "Ljava/util/List;size()I")) - private int moreSchedulingBudget(List threads) { - int budget = threads.size(); + @ModifyArg( + method = "getHighEffortSchedulingBudget", + at = @At(value = "INVOKE", target = "Ljava/lang/Math;max(II)I", ordinal = 0) + ) + private int modifyHighEffortBudget(int original) { + if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { + return original * 3; + } + return original; + } + + @ModifyArg( + method = "getLowEffortSchedulingBudget", + at = @At(value = "INVOKE", target = "Ljava/lang/Math;max(II)I", ordinal = 0) + ) + private int modifyLowEffortBudget(int original) { if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { - budget *= 3; + return original * 3; } - return budget; + return original; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilderMeshingTask.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilderMeshingTask.java index 89edeff3..fb108fd0 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilderMeshingTask.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkBuilderMeshingTask.java @@ -1,12 +1,22 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import me.cortex.nvidium.Nvidium; import me.cortex.nvidium.sodiumCompat.IRepackagedResult; import me.cortex.nvidium.sodiumCompat.SodiumResultCompatibility; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildContext; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; -import me.jellysquid.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; -import me.jellysquid.mods.sodium.client.util.task.CancellationToken; + + +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildContext; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; +import net.caffeinemc.mods.sodium.client.util.task.CancellationToken; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,7 +24,7 @@ @Mixin(value = ChunkBuilderMeshingTask.class, remap = false) public class MixinChunkBuilderMeshingTask { - @Inject(method = "execute(Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;)Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", at = @At("TAIL")) + @Inject(method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", at = @At("TAIL")) private void repackageResults(ChunkBuildContext buildContext, CancellationToken cancellationToken, CallbackInfoReturnable cir) { if (Nvidium.IS_ENABLED) { var result = cir.getReturnValue(); diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkJobQueue.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkJobQueue.java index 18f2f86b..bddabfcb 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkJobQueue.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinChunkJobQueue.java @@ -1,3 +1,11 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import org.spongepowered.asm.mixin.Mixin; @@ -5,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -@Mixin(targets = {"me.jellysquid.mods.sodium.client.render.chunk.compile.executor.ChunkJobQueue"},remap = false) +@Mixin(targets = {"net.caffeinemc.mods.sodium.client.render.chunk.compile.executor.ChunkJobQueue"},remap = false) public class MixinChunkJobQueue { @Redirect(method = "shutdown", at = @At(value = "INVOKE", target = "Ljava/lang/Runtime;availableProcessors()I")) private int returnAlot(Runtime instance) { diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinOptionFlag.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinOptionFlag.java index 9705d721..b432bfba 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinOptionFlag.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinOptionFlag.java @@ -1,7 +1,16 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import me.cortex.nvidium.sodiumCompat.NvidiumOptionFlags; -import me.jellysquid.mods.sodium.client.gui.options.OptionFlag; + +import net.caffeinemc.mods.sodium.client.gui.options.OptionFlag; import org.apache.commons.lang3.ArrayUtils; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderRegionManager.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderRegionManager.java index 4f85565f..d42d803e 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderRegionManager.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderRegionManager.java @@ -1,35 +1,45 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import me.cortex.nvidium.Nvidium; import me.cortex.nvidium.NvidiumWorldRenderer; import me.cortex.nvidium.sodiumCompat.INvidiumWorldRendererSetter; -import me.jellysquid.mods.sodium.client.gl.device.CommandList; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; -import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegion; -import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegionManager; +import net.caffeinemc.mods.sodium.client.gl.device.CommandList; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.BuilderTaskOutput; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegionManager; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Collection; @Mixin(value = RenderRegionManager.class, remap = false) public abstract class MixinRenderRegionManager implements INvidiumWorldRendererSetter { + @Unique + private NvidiumWorldRenderer renderer; - @Shadow protected abstract void uploadMeshes(CommandList commandList, RenderRegion region, Collection results); - - @Unique private NvidiumWorldRenderer renderer; + @Inject(method = "uploadResults", at = @At("HEAD"), cancellable = true, remap = false) + private void onUploadResults(CommandList commandList, Collection results, CallbackInfo ci) { + if (Nvidium.IS_ENABLED && renderer != null) { + for (BuilderTaskOutput result : results) { - @Redirect(method = "uploadMeshes(Lme/jellysquid/mods/sodium/client/gl/device/CommandList;Ljava/util/Collection;)V", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/region/RenderRegionManager;uploadMeshes(Lme/jellysquid/mods/sodium/client/gl/device/CommandList;Lme/jellysquid/mods/sodium/client/render/chunk/region/RenderRegion;Ljava/util/Collection;)V")) - private void redirectUpload(RenderRegionManager instance, CommandList cmdList, RenderRegion pass, Collection uploadQueue) { - if (Nvidium.IS_ENABLED) { - uploadQueue.forEach(renderer::uploadBuildResult); - } else { - uploadMeshes(cmdList, pass, uploadQueue); + if (result instanceof ChunkBuildOutput buildOutput) { + renderer.uploadBuildResult(buildOutput); + } + } + ci.cancel(); } } @@ -37,4 +47,4 @@ private void redirectUpload(RenderRegionManager instance, CommandList cmdList, R public void setWorldRenderer(NvidiumWorldRenderer renderer) { this.renderer = renderer; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSection.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSection.java index f15fac17..ce0dc7e9 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSection.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSection.java @@ -1,39 +1,17 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; -import it.unimi.dsi.fastutil.longs.Long2ReferenceMap; -import me.cortex.nvidium.Nvidium; -import me.cortex.nvidium.NvidiumWorldRenderer; -import me.cortex.nvidium.managers.AsyncOcclusionTracker; -import me.cortex.nvidium.sodiumCompat.INvidiumWorldRendererGetter; -import me.cortex.nvidium.sodiumCompat.INvidiumWorldRendererSetter; import me.cortex.nvidium.sodiumCompat.IRenderSectionExtension; -import me.cortex.nvidium.sodiumCompat.IrisCheck; -import me.jellysquid.mods.sodium.client.gl.device.CommandList; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderMatrices; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkUpdateType; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; -import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegionManager; -import me.jellysquid.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; -import me.jellysquid.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; -import me.jellysquid.mods.sodium.client.render.viewport.Viewport; -import net.minecraft.client.render.Camera; -import net.minecraft.client.world.ClientWorld; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; @Mixin(value = RenderSection.class, remap = false) public class MixinRenderSection implements IRenderSectionExtension { diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSectionManager.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSectionManager.java index b80552da..b5213d95 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSectionManager.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinRenderSectionManager.java @@ -1,3 +1,11 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import it.unimi.dsi.fastutil.longs.Long2ReferenceMap; @@ -5,20 +13,21 @@ import me.cortex.nvidium.NvidiumWorldRenderer; import me.cortex.nvidium.managers.AsyncOcclusionTracker; import me.cortex.nvidium.sodiumCompat.*; -import me.jellysquid.mods.sodium.client.SodiumClientMod; -import me.jellysquid.mods.sodium.client.gl.device.CommandList; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderMatrices; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkUpdateType; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; -import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegionManager; -import me.jellysquid.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; -import me.jellysquid.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; -import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; -import me.jellysquid.mods.sodium.client.render.texture.SpriteUtil; -import me.jellysquid.mods.sodium.client.render.viewport.Viewport; -import net.minecraft.client.render.Camera; -import net.minecraft.client.world.ClientWorld; +import net.caffeinemc.mods.sodium.client.SodiumClientMod; +import net.caffeinemc.mods.sodium.client.gl.device.CommandList; +import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; +import net.caffeinemc.mods.sodium.client.render.chunk.ChunkUpdateType; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; +import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegionManager; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; +import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.SectionPos; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -27,21 +36,18 @@ import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; -import java.util.Map; @Mixin(value = RenderSectionManager.class, remap = false) -public class MixinRenderSectionManager implements INvidiumWorldRendererGetter { +public abstract class MixinRenderSectionManager implements INvidiumWorldRendererGetter { @Shadow @Final private RenderRegionManager regions; @Shadow @Final private Long2ReferenceMap sectionByPosition; - @Shadow private @NotNull Map> rebuildLists; @Shadow @Final private int renderDistance; + @Shadow @Final private ClientLevel level; + @Unique private NvidiumWorldRenderer renderer; - @Unique private Viewport viewport; @Unique private static void updateNvidiumIsEnabled() { @@ -49,17 +55,18 @@ private static void updateNvidiumIsEnabled() { } @Inject(method = "", at = @At("TAIL")) - private void init(ClientWorld world, int renderDistance, CommandList commandList, CallbackInfo ci) { + private void init(ClientLevel world, int renderDistance, CommandList commandList, CallbackInfo ci) { updateNvidiumIsEnabled(); if (Nvidium.IS_ENABLED) { if (renderer != null) throw new IllegalStateException("Cannot have multiple world renderers"); - renderer = new NvidiumWorldRenderer(Nvidium.config.async_bfs?new AsyncOcclusionTracker(renderDistance, sectionByPosition, world, rebuildLists):null); + + renderer = new NvidiumWorldRenderer(null); ((INvidiumWorldRendererSetter)regions).setWorldRenderer(renderer); } } - @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/compile/executor/ChunkBuilder;(Lnet/minecraft/client/world/ClientWorld;Lme/jellysquid/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType;)V", remap = true), index = 1) + @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkBuilder;(Lnet/minecraft/client/multiplayer/ClientLevel;Lnet/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType;)V"), index = 1) private ChunkVertexType modifyVertexType(ChunkVertexType vertexType) { updateNvidiumIsEnabled(); if (Nvidium.IS_ENABLED) { @@ -68,7 +75,6 @@ private ChunkVertexType modifyVertexType(ChunkVertexType vertexType) { return vertexType; } - @Inject(method = "destroy", at = @At("TAIL")) private void destroy(CallbackInfo ci) { if (Nvidium.IS_ENABLED) { @@ -80,7 +86,7 @@ private void destroy(CallbackInfo ci) { } } - @Redirect(method = "onSectionRemoved", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/RenderSection;delete()V")) + @Redirect(method = "onSectionRemoved", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSection;delete()V")) private void deleteSection(RenderSection section) { if (Nvidium.IS_ENABLED) { if (Nvidium.config.region_keep_distance == 32) { @@ -90,20 +96,19 @@ private void deleteSection(RenderSection section) { section.delete(); } - @Inject(method = "update", at = @At("HEAD")) - private void trackViewport(Camera camera, Viewport viewport, int frame, boolean spectator, CallbackInfo ci) { - this.viewport = viewport; - } - @Inject(method = "renderLayer", at = @At("HEAD"), cancellable = true) - public void renderLayer(ChunkRenderMatrices matrices, TerrainRenderPass pass, double x, double y, double z, CallbackInfo ci) { + private void renderLayer(ChunkRenderMatrices matrices, TerrainRenderPass pass, double x, double y, double z, CallbackInfo ci) { if (Nvidium.IS_ENABLED) { ci.cancel(); pass.startDrawing(); if (pass == DefaultTerrainRenderPasses.SOLID) { - renderer.renderFrame(viewport, matrices, x, y, z); + if (renderer != null) { + renderer.renderFrame(matrices, x, y, z); + } } else if (pass == DefaultTerrainRenderPasses.TRANSLUCENT) { - renderer.renderTranslucent(); + if (renderer != null) { + renderer.renderTranslucent(); + } } pass.endDrawing(); } @@ -113,7 +118,9 @@ public void renderLayer(ChunkRenderMatrices matrices, TerrainRenderPass pass, do private void redirectDebug(CallbackInfoReturnable> cir) { if (Nvidium.IS_ENABLED) { var debugStrings = new ArrayList(); - renderer.addDebugInfo(debugStrings); + if (renderer != null) { + renderer.addDebugInfo(debugStrings); + } cir.setReturnValue(debugStrings); cir.cancel(); } @@ -131,51 +138,19 @@ private void redirectTerrainRenderList(Camera camera, Viewport viewport, int fra } } - @Redirect(method = "submitRebuildTasks", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/RenderSection;setPendingUpdate(Lme/jellysquid/mods/sodium/client/render/chunk/ChunkUpdateType;)V")) - private void injectEnqueueFalse(RenderSection instance, ChunkUpdateType type) { - instance.setPendingUpdate(type); - if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { - //We need to reset the fact that its been submitted to the rebuild queue from the build queue - ((IRenderSectionExtension) instance).isSubmittedRebuild(false); - } - } - @Unique private boolean isSectionVisibleBfs(RenderSection section) { - //The reason why this is done is that since the bfs search is async it could be updating the frame counter with the next frame - // while some sections that arnt updated/ticked yet still have the old frame id + if (renderer == null) return false; int delta = Math.abs(section.getLastVisibleFrame() - renderer.getAsyncFrameId()); return delta <= 1; } - @Inject(method = "isSectionVisible", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/RenderSection;getLastVisibleFrame()I", shift = At.Shift.BEFORE), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) - private void redirectIsSectionVisible(int x, int y, int z, CallbackInfoReturnable cir, RenderSection render) { - if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { - cir.setReturnValue(isSectionVisibleBfs(render)); - } - } - - @Inject(method = "tickVisibleRenders", at = @At("HEAD"), cancellable = true) - private void redirectAnimatedSpriteUpdates(CallbackInfo ci) { - if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs && SodiumClientMod.options().performance.animateOnlyVisibleTextures) { - ci.cancel(); - var sprites = renderer.getAnimatedSpriteSet(); - if (sprites == null) { - return; - } - for (var sprite : sprites) { - SpriteUtil.markSpriteActive(sprite); - } - } - } - - @Inject(method = "scheduleRebuild", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/RenderSection;setPendingUpdate(Lme/jellysquid/mods/sodium/client/render/chunk/ChunkUpdateType;)V", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) - private void instantReschedule(int x, int y, int z, boolean important, CallbackInfo ci, RenderSection section, ChunkUpdateType pendingUpdate) { - if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { - var queue = rebuildLists.get(pendingUpdate); - if (isSectionVisibleBfs(section) && queue.size() < pendingUpdate.getMaximumQueueSize()) { - ((IRenderSectionExtension)section).isSubmittedRebuild(true); - rebuildLists.get(pendingUpdate).add(section); + @Inject(method = "isSectionVisible", at = @At("RETURN"), cancellable = true) + private void redirectIsSectionVisible(int x, int y, int z, CallbackInfoReturnable cir) { + if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs && !cir.getReturnValueZ()) { + RenderSection render = sectionByPosition.get(SectionPos.asLong(x, y, z)); + if (render != null) { + cir.setReturnValue(isSectionVisibleBfs(render)); } } } @@ -183,7 +158,9 @@ private void instantReschedule(int x, int y, int z, boolean important, CallbackI @Inject(method = "getVisibleChunkCount", at = @At("HEAD"), cancellable = true) private void injectVisibilityCount(CallbackInfoReturnable cir) { if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { - cir.setReturnValue(this.renderer.getAsyncBfsVisibilityCount()); + if (renderer != null) { + cir.setReturnValue(renderer.getAsyncBfsVisibilityCount()); + } } } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumOptionsGUI.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumOptionsGUI.java index 8190333d..f6d0eccb 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumOptionsGUI.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumOptionsGUI.java @@ -1,15 +1,24 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; import me.cortex.nvidium.NvidiumWorldRenderer; import me.cortex.nvidium.config.ConfigGuiBuilder; import me.cortex.nvidium.sodiumCompat.INvidiumWorldRendererGetter; import me.cortex.nvidium.sodiumCompat.NvidiumOptionFlags; -import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI; -import me.jellysquid.mods.sodium.client.gui.options.*; -import me.jellysquid.mods.sodium.client.gui.options.storage.OptionStorage; -import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; +import net.caffeinemc.mods.sodium.client.gui.SodiumGameOptions; +import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI; +import net.caffeinemc.mods.sodium.client.gui.options.*; +import net.caffeinemc.mods.sodium.client.gui.options.storage.OptionStorage; +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -18,10 +27,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.*; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; @Mixin(value = SodiumOptionsGUI.class, remap = false) -public class MixinSodiumOptionsGUI { +public abstract class MixinSodiumOptionsGUI { @Shadow @Final private List pages; @Inject(method = "", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 3, shift = At.Shift.AFTER)) @@ -29,16 +40,34 @@ private void addNvidiumOptions(Screen prevScreen, CallbackInfo ci) { ConfigGuiBuilder.addNvidiumGui(pages); } - @Inject(method = "applyChanges", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILSOFT) - private void applyShaderReload(CallbackInfo ci, HashSet> dirtyStorages, EnumSet flags, MinecraftClient client) { - if (client.world != null) { - SodiumWorldRenderer swr = SodiumWorldRenderer.instanceNullable(); - if (swr != null) { - NvidiumWorldRenderer pipeline = ((INvidiumWorldRendererGetter)((SodiumWorldRendererAccessor)swr).getRenderSectionManager()).getRenderer(); - if (pipeline != null && flags.contains(NvidiumOptionFlags.REQUIRES_SHADER_RELOAD)) { - pipeline.reloadShaders(); + @Inject(method = "applyChanges", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getWindow()Lcom/mojang/blaze3d/platform/Window;"), locals = LocalCapture.CAPTURE_FAILHARD) + private void applyShaderReload(CallbackInfo ci, + HashSet> dirtyStorages, + EnumSet flags, + Minecraft client) { + if (client.level != null) { + if (flags.contains(NvidiumOptionFlags.REQUIRES_SHADER_RELOAD)) { + SodiumWorldRenderer swr = SodiumWorldRenderer.instanceNullable(); + if (swr != null) { + + try { + + java.lang.reflect.Field field = swr.getClass().getDeclaredField("renderSectionManager"); + field.setAccessible(true); + Object renderSectionManager = field.get(swr); + + if (renderSectionManager instanceof INvidiumWorldRendererGetter getter) { + NvidiumWorldRenderer pipeline = getter.getRenderer(); + if (pipeline != null) { + pipeline.reloadShaders(); + } + } + } catch (Exception e) { + + System.err.println("Failed to access renderSectionManager: " + e.getMessage()); + } } } } } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumWorldRenderer.java b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumWorldRenderer.java index d1210436..90c13505 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumWorldRenderer.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/MixinSodiumWorldRenderer.java @@ -1,21 +1,33 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; +import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import me.cortex.nvidium.Nvidium; import me.cortex.nvidium.NvidiumWorldRenderer; import me.cortex.nvidium.sodiumCompat.INvidiumWorldRendererGetter; -import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; -import me.jellysquid.mods.sodium.client.render.viewport.Viewport; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.render.BufferBuilderStorage; -import net.minecraft.client.render.Camera; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.BlockBreakingInfo; + +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderBuffers; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.server.level.BlockDestructionProgress; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -24,40 +36,85 @@ @Mixin(value = SodiumWorldRenderer.class, remap = false) public abstract class MixinSodiumWorldRenderer implements INvidiumWorldRendererGetter { - @Shadow private RenderSectionManager renderSectionManager; @Shadow - protected static void renderBlockEntity(MatrixStack matrices, BufferBuilderStorage bufferBuilders, Long2ObjectMap> blockBreakingProgressions, float tickDelta, VertexConsumerProvider.Immediate immediate, double x, double y, double z, BlockEntityRenderDispatcher dispatcher, BlockEntity entity) { - } + private RenderSectionManager renderSectionManager; + - @Inject(method = "setupTerrain", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/RenderSectionManager;needsUpdate()Z", shift = At.Shift.BEFORE)) - private void injectTerrainSetup(Camera camera, Viewport viewport, int frame, boolean spectator, boolean updateChunksImmediately, CallbackInfo ci) { + @Inject(method = "setupTerrain", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;needsUpdate()Z", shift = At.Shift.BEFORE)) + private void injectTerrainSetup(Camera camera, Viewport viewport, boolean spectator, boolean updateChunksImmediately, CallbackInfo ci) { if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { - ((INvidiumWorldRendererGetter)renderSectionManager).getRenderer().update(camera, viewport, frame, spectator); + ((INvidiumWorldRendererGetter)renderSectionManager).getRenderer().update(camera, viewport, spectator); } } - @Inject(method = "renderBlockEntities(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/BufferBuilderStorage;Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;FLnet/minecraft/client/render/VertexConsumerProvider$Immediate;DDDLnet/minecraft/client/render/block/entity/BlockEntityRenderDispatcher;)V", at = @At("HEAD"), cancellable = true, remap = true) - private void overrideEntityRenderer(MatrixStack matrices, BufferBuilderStorage bufferBuilders, Long2ObjectMap> blockBreakingProgressions, float tickDelta, VertexConsumerProvider.Immediate immediate, double x, double y, double z, BlockEntityRenderDispatcher blockEntityRenderer, CallbackInfo ci) { + @Inject(method = "renderBlockEntities", + at = @At("HEAD"), + cancellable = true) + private void overrideEntityRenderer(PoseStack poseStack, + RenderBuffers bufferBuilders, + Long2ObjectMap> blockBreakingProgressions, + float tickDelta, + MultiBufferSource.BufferSource immediate, + double x, double y, double z, + BlockEntityRenderDispatcher blockEntityRenderer, + CallbackInfo ci) { if (Nvidium.IS_ENABLED && Nvidium.config.async_bfs) { + NvidiumWorldRenderer renderer = ((INvidiumWorldRendererGetter) renderSectionManager).getRenderer(); + if (renderer == null) { + return; + } + ci.cancel(); - var sectionsWithEntities = ((INvidiumWorldRendererGetter)renderSectionManager).getRenderer().getSectionsWithEntities(); + + var sectionsWithEntities = renderer.getSectionsWithEntities(); + if (sectionsWithEntities == null) { + return; + } + for (var section : sectionsWithEntities) { - if (section.isDisposed() || section.getCulledBlockEntities() == null) + if (section.isDisposed()) { continue; - for (var entity : section.getCulledBlockEntities()) { - renderBlockEntity(matrices, bufferBuilders, blockBreakingProgressions, tickDelta, immediate, x, y, z, blockEntityRenderer, entity); + } + + var culledBlockEntities = section.getCulledBlockEntities(); + if (culledBlockEntities == null) { + continue; + } + + for (BlockEntity entity : culledBlockEntities) { + nvidium$renderBlockEntity(poseStack, bufferBuilders, blockBreakingProgressions, + tickDelta, immediate, x, y, z, blockEntityRenderer, entity); } } } } + @Unique + private static void nvidium$renderBlockEntity(PoseStack poseStack, + RenderBuffers bufferBuilders, + Long2ObjectMap> blockBreakingProgressions, + float tickDelta, + MultiBufferSource.BufferSource immediate, + double x, double y, double z, + BlockEntityRenderDispatcher dispatcher, + BlockEntity entity) { + var pos = entity.getBlockPos(); + + poseStack.pushPose(); + poseStack.translate(pos.getX() - x, pos.getY() - y, pos.getZ() - z); + + + dispatcher.render(entity, tickDelta, poseStack, immediate); + + poseStack.popPose(); + } + @Override public NvidiumWorldRenderer getRenderer() { - if (Nvidium.IS_ENABLED) { - return ((INvidiumWorldRendererGetter)renderSectionManager).getRenderer(); - } else { - return null; + if (Nvidium.IS_ENABLED && renderSectionManager != null) { + return ((INvidiumWorldRendererGetter) renderSectionManager).getRenderer(); } + return null; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/mixin/sodium/SodiumWorldRendererAccessor.java b/src/main/java/me/cortex/nvidium/mixin/sodium/SodiumWorldRendererAccessor.java index 86e8ae3f..047b1323 100644 --- a/src/main/java/me/cortex/nvidium/mixin/sodium/SodiumWorldRendererAccessor.java +++ b/src/main/java/me/cortex/nvidium/mixin/sodium/SodiumWorldRendererAccessor.java @@ -1,7 +1,16 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.mixin.sodium; -import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; -import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; + +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/main/java/me/cortex/nvidium/renderers/PrimaryTerrainRasterizer.java b/src/main/java/me/cortex/nvidium/renderers/PrimaryTerrainRasterizer.java index 3d948285..60f9235e 100644 --- a/src/main/java/me/cortex/nvidium/renderers/PrimaryTerrainRasterizer.java +++ b/src/main/java/me/cortex/nvidium/renderers/PrimaryTerrainRasterizer.java @@ -1,11 +1,19 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.renderers; import com.mojang.blaze3d.platform.GlStateManager; import me.cortex.nvidium.gl.shader.Shader; import me.cortex.nvidium.sodiumCompat.ShaderLoader; import me.cortex.nvidium.mixin.minecraft.LightMapAccessor; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; +import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceLocation; import org.lwjgl.opengl.GL12C; import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45C; @@ -21,12 +29,12 @@ public class PrimaryTerrainRasterizer extends Phase { private final int blockSampler = glGenSamplers(); private final int lightSampler = glGenSamplers(); private final Shader shader = Shader.make() - .addSource(TASK, ShaderLoader.parse(Identifier.of("nvidium", "terrain/task.glsl"))) - .addSource(MESH, ShaderLoader.parse(Identifier.of("nvidium", "terrain/mesh.glsl"))) - .addSource(FRAGMENT, ShaderLoader.parse(Identifier.of("nvidium", "terrain/frag.frag"))).compile(); + .addSource(TASK, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/task.glsl"))) + .addSource(MESH, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/mesh.glsl"))) + .addSource(FRAGMENT, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/frag.frag"))).compile(); public PrimaryTerrainRasterizer() { - GL45C.glSamplerParameteri(blockSampler, GL45C.GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + GL45C.glSamplerParameteri(blockSampler, GL45C.GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); GL45C.glSamplerParameteri(blockSampler, GL45C.GL_TEXTURE_MAG_FILTER, GL_NEAREST); GL45C.glSamplerParameteri(blockSampler, GL45C.GL_TEXTURE_MIN_LOD, 0); GL45C.glSamplerParameteri(blockSampler, GL45C.GL_TEXTURE_MAX_LOD, 4); @@ -44,16 +52,19 @@ private static void setTexture(int textureId, int bindingPoint) { public void raster(int regionCount, long commandAddr) { shader.bind(); - int blockId = MinecraftClient.getInstance().getTextureManager().getTexture(Identifier.of("minecraft", "textures/atlas/blocks.png")).getGlId(); - int lightId = ((LightMapAccessor)MinecraftClient.getInstance().gameRenderer.getLightmapTextureManager()).getTexture().getGlId(); + Minecraft minecraft = Minecraft.getInstance(); + + int blockId = minecraft.getTextureManager().getTexture(ResourceLocation.parse("textures/atlas/blocks.png")).getId(); + + int lightId = ((LightMapAccessor) minecraft.gameRenderer.lightTexture()).getTexture().getId(); GL45C.glBindSampler(0, blockSampler); GL45C.glBindSampler(1, lightSampler); setTexture(blockId, 0); setTexture(lightId, 1); - glBufferAddressRangeNV(GL_DRAW_INDIRECT_ADDRESS_NV, 0, commandAddr, regionCount*8L);//Bind the command buffer - glMultiDrawMeshTasksIndirectNV( 0, regionCount, 0); + glBufferAddressRangeNV(GL_DRAW_INDIRECT_ADDRESS_NV, 0, commandAddr, regionCount * 8L); + glMultiDrawMeshTasksIndirectNV(0, regionCount, 0); GL45C.glBindSampler(0, 0); GL45C.glBindSampler(1, 0); } @@ -63,4 +74,4 @@ public void delete() { GL45.glDeleteSamplers(lightSampler); shader.delete(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/renderers/RegionRasterizer.java b/src/main/java/me/cortex/nvidium/renderers/RegionRasterizer.java index eb617a5e..12ff0cb3 100644 --- a/src/main/java/me/cortex/nvidium/renderers/RegionRasterizer.java +++ b/src/main/java/me/cortex/nvidium/renderers/RegionRasterizer.java @@ -1,9 +1,16 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.renderers; import me.cortex.nvidium.gl.shader.Shader; import me.cortex.nvidium.sodiumCompat.ShaderLoader; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderParser; -import net.minecraft.util.Identifier; +import net.minecraft.resources.ResourceLocation; import static me.cortex.nvidium.gl.shader.ShaderType.FRAGMENT; import static me.cortex.nvidium.gl.shader.ShaderType.MESH; @@ -11,16 +18,16 @@ public class RegionRasterizer extends Phase { private final Shader shader = Shader.make() - .addSource(MESH, ShaderLoader.parse(Identifier.of("nvidium", "occlusion/region_raster/mesh.glsl"))) - .addSource(FRAGMENT, ShaderLoader.parse(Identifier.of("nvidium", "occlusion/region_raster/fragment.frag"))) - .compile(); + .addSource(MESH, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "occlusion/region_raster/mesh.glsl"))) + .addSource(FRAGMENT, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "occlusion/region_raster/fragment.frag"))) + .compile(); public void raster(int regionCount) { shader.bind(); - glDrawMeshTasksNV(0,regionCount); + glDrawMeshTasksNV(0, regionCount); } public void delete() { shader.delete(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/renderers/SectionRasterizer.java b/src/main/java/me/cortex/nvidium/renderers/SectionRasterizer.java index dfac4d8c..63494ddc 100644 --- a/src/main/java/me/cortex/nvidium/renderers/SectionRasterizer.java +++ b/src/main/java/me/cortex/nvidium/renderers/SectionRasterizer.java @@ -1,9 +1,16 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.renderers; import me.cortex.nvidium.gl.shader.Shader; import me.cortex.nvidium.sodiumCompat.ShaderLoader; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderParser; -import net.minecraft.util.Identifier; +import net.minecraft.resources.ResourceLocation; import static me.cortex.nvidium.gl.shader.ShaderType.*; import static org.lwjgl.opengl.NVMeshShader.glDrawMeshTasksNV; @@ -11,16 +18,17 @@ public class SectionRasterizer extends Phase { private final Shader shader = Shader.make() - .addSource(TASK, ShaderLoader.parse(Identifier.of("nvidium", "occlusion/section_raster/task.glsl"))) - .addSource(MESH, ShaderLoader.parse(Identifier.of("nvidium", "occlusion/section_raster/mesh.glsl"))) - .addSource(FRAGMENT, ShaderLoader.parse(Identifier.of("nvidium", "occlusion/section_raster/fragment.glsl"))).compile(); + .addSource(TASK, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "occlusion/section_raster/task.glsl"))) + .addSource(MESH, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "occlusion/section_raster/mesh.glsl"))) + .addSource(FRAGMENT, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "occlusion/section_raster/fragment.glsl"))) + .compile(); public void raster(int regionCount) { shader.bind(); - glDrawMeshTasksNV(0,regionCount); + glDrawMeshTasksNV(0, regionCount); } public void delete() { shader.delete(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/renderers/SortRegionSectionPhase.java b/src/main/java/me/cortex/nvidium/renderers/SortRegionSectionPhase.java index 3598ec45..8fc915c0 100644 --- a/src/main/java/me/cortex/nvidium/renderers/SortRegionSectionPhase.java +++ b/src/main/java/me/cortex/nvidium/renderers/SortRegionSectionPhase.java @@ -1,26 +1,15 @@ package me.cortex.nvidium.renderers; -import com.mojang.blaze3d.platform.GlStateManager; import me.cortex.nvidium.gl.shader.Shader; -import me.cortex.nvidium.mixin.minecraft.LightMapAccessor; import me.cortex.nvidium.sodiumCompat.ShaderLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; -import org.lwjgl.opengl.GL45; -import org.lwjgl.opengl.GL45C; +import net.minecraft.resources.ResourceLocation; -import static me.cortex.nvidium.RenderPipeline.GL_DRAW_INDIRECT_ADDRESS_NV; import static me.cortex.nvidium.gl.shader.ShaderType.*; -import static org.lwjgl.opengl.GL11C.GL_NEAREST; -import static org.lwjgl.opengl.GL11C.GL_NEAREST_MIPMAP_LINEAR; -import static org.lwjgl.opengl.GL33.glGenSamplers; import static org.lwjgl.opengl.GL43C.glDispatchCompute; -import static org.lwjgl.opengl.NVMeshShader.glMultiDrawMeshTasksIndirectNV; -import static org.lwjgl.opengl.NVVertexBufferUnifiedMemory.glBufferAddressRangeNV; public class SortRegionSectionPhase extends Phase { private final Shader shader = Shader.make() - .addSource(COMPUTE, ShaderLoader.parse(Identifier.of("nvidium", "sorting/region_section_sorter.comp"))) + .addSource(COMPUTE, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "sorting/region_section_sorter.comp"))) .compile(); public SortRegionSectionPhase() { @@ -34,4 +23,4 @@ public void dispatch(int sortingRegionCount) { public void delete() { shader.delete(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/renderers/TemporalTerrainRasterizer.java b/src/main/java/me/cortex/nvidium/renderers/TemporalTerrainRasterizer.java index e44630df..c93bbad0 100644 --- a/src/main/java/me/cortex/nvidium/renderers/TemporalTerrainRasterizer.java +++ b/src/main/java/me/cortex/nvidium/renderers/TemporalTerrainRasterizer.java @@ -1,10 +1,18 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.renderers; import me.cortex.nvidium.gl.shader.Shader; import me.cortex.nvidium.sodiumCompat.ShaderLoader; import me.cortex.nvidium.mixin.minecraft.LightMapAccessor; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; +import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceLocation; import org.lwjgl.opengl.GL12C; import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45C; @@ -12,7 +20,6 @@ import static me.cortex.nvidium.RenderPipeline.GL_DRAW_INDIRECT_ADDRESS_NV; import static me.cortex.nvidium.gl.shader.ShaderType.*; import static org.lwjgl.opengl.GL11C.*; -import static org.lwjgl.opengl.GL11C.GL_TEXTURE_WRAP_S; import static org.lwjgl.opengl.GL33.glGenSamplers; import static org.lwjgl.opengl.NVMeshShader.glMultiDrawMeshTasksIndirectNV; import static org.lwjgl.opengl.NVVertexBufferUnifiedMemory.glBufferAddressRangeNV; @@ -21,9 +28,9 @@ public class TemporalTerrainRasterizer extends Phase { private final int blockSampler = glGenSamplers(); private final int lightSampler = glGenSamplers(); private final Shader shader = Shader.make() - .addSource(TASK, ShaderLoader.parse(Identifier.of("nvidium", "terrain/temporal_task.glsl"))) - .addSource(MESH, ShaderLoader.parse(Identifier.of("nvidium", "terrain/mesh.glsl"))) - .addSource(FRAGMENT, ShaderLoader.parse(Identifier.of("nvidium", "terrain/frag.frag"))).compile(); + .addSource(TASK, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/temporal_task.glsl"))) + .addSource(MESH, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/mesh.glsl"))) + .addSource(FRAGMENT, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/frag.frag"))).compile(); public TemporalTerrainRasterizer() { GL45C.glSamplerParameteri(blockSampler, GL45C.GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); @@ -39,8 +46,11 @@ public TemporalTerrainRasterizer() { public void raster(int regionCount, long commandAddr) { shader.bind(); - int blockId = MinecraftClient.getInstance().getTextureManager().getTexture(Identifier.of("minecraft", "textures/atlas/blocks.png")).getGlId(); - int lightId = ((LightMapAccessor)MinecraftClient.getInstance().gameRenderer.getLightmapTextureManager()).getTexture().getGlId(); + Minecraft minecraft = Minecraft.getInstance(); + + int blockId = minecraft.getTextureManager().getTexture(ResourceLocation.parse("textures/atlas/blocks.png")).getId(); + + int lightId = ((LightMapAccessor) minecraft.gameRenderer.lightTexture()).getTexture().getId(); GL45C.glBindTextureUnit(0, blockId); GL45C.glBindSampler(0, blockSampler); @@ -48,11 +58,8 @@ public void raster(int regionCount, long commandAddr) { GL45C.glBindTextureUnit(1, lightId); GL45C.glBindSampler(1, lightSampler); - - - glBufferAddressRangeNV(GL_DRAW_INDIRECT_ADDRESS_NV, 0, commandAddr, regionCount*8L);//Bind the command buffer - glMultiDrawMeshTasksIndirectNV( 0, regionCount, 0); - + glBufferAddressRangeNV(GL_DRAW_INDIRECT_ADDRESS_NV, 0, commandAddr, regionCount * 8L); // Bind the command buffer + glMultiDrawMeshTasksIndirectNV(0, regionCount, 0); GL45C.glBindSampler(0, 0); GL45C.glBindSampler(1, 0); @@ -63,4 +70,4 @@ public void delete() { GL45.glDeleteSamplers(lightSampler); shader.delete(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/renderers/TranslucentTerrainRasterizer.java b/src/main/java/me/cortex/nvidium/renderers/TranslucentTerrainRasterizer.java index 5c70e227..4f5f4a3d 100644 --- a/src/main/java/me/cortex/nvidium/renderers/TranslucentTerrainRasterizer.java +++ b/src/main/java/me/cortex/nvidium/renderers/TranslucentTerrainRasterizer.java @@ -1,20 +1,26 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.renderers; import com.mojang.blaze3d.platform.GlStateManager; import me.cortex.nvidium.gl.shader.Shader; import me.cortex.nvidium.sodiumCompat.ShaderLoader; import me.cortex.nvidium.mixin.minecraft.LightMapAccessor; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; +import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceLocation; import org.lwjgl.opengl.GL12C; -import org.lwjgl.opengl.GL30C; import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45C; import static me.cortex.nvidium.RenderPipeline.GL_DRAW_INDIRECT_ADDRESS_NV; import static me.cortex.nvidium.gl.shader.ShaderType.*; import static org.lwjgl.opengl.GL11C.*; -import static org.lwjgl.opengl.GL11C.GL_TEXTURE_WRAP_S; import static org.lwjgl.opengl.GL33.glGenSamplers; import static org.lwjgl.opengl.NVMeshShader.glMultiDrawMeshTasksIndirectNV; import static org.lwjgl.opengl.NVVertexBufferUnifiedMemory.glBufferAddressRangeNV; @@ -24,9 +30,9 @@ public class TranslucentTerrainRasterizer extends Phase { private final int lightSampler = glGenSamplers(); private final Shader shader = Shader.make() - .addSource(TASK, ShaderLoader.parse(Identifier.of("nvidium", "terrain/translucent/task.glsl"))) - .addSource(MESH, ShaderLoader.parse(Identifier.of("nvidium", "terrain/translucent/mesh.glsl"))) - .addSource(FRAGMENT, ShaderLoader.parse(Identifier.of("nvidium", "terrain/frag.frag"), builder->{builder.add("TRANSLUCENT_PASS");})) + .addSource(TASK, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/translucent/task.glsl"))) + .addSource(MESH, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/translucent/mesh.glsl"))) + .addSource(FRAGMENT, ShaderLoader.parse(ResourceLocation.fromNamespaceAndPath("nvidium", "terrain/frag.frag"), builder -> { builder.add("TRANSLUCENT_PASS"); })) .compile(); public TranslucentTerrainRasterizer() { @@ -40,28 +46,30 @@ public TranslucentTerrainRasterizer() { GL45C.glSamplerParameteri(lightSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - private static void setTexture(int textureId, int bindingPoint) { GlStateManager._activeTexture(33984 + bindingPoint); GlStateManager._bindTexture(textureId); } - //Translucency is rendered in a very cursed and incorrect way + // Translucency is rendered in a very cursed and incorrect way // it hijacks the unassigned indirect command dispatch and uses that to dispatch the translucent chunks as well public void raster(int regionCount, long commandAddr) { shader.bind(); - int blockId = MinecraftClient.getInstance().getTextureManager().getTexture(Identifier.of("minecraft", "textures/atlas/blocks.png")).getGlId(); - int lightId = ((LightMapAccessor)MinecraftClient.getInstance().gameRenderer.getLightmapTextureManager()).getTexture().getGlId(); + Minecraft minecraft = Minecraft.getInstance(); + + int blockId = minecraft.getTextureManager().getTexture(ResourceLocation.parse("textures/atlas/blocks.png")).getId(); + + int lightId = ((LightMapAccessor) minecraft.gameRenderer.lightTexture()).getTexture().getId(); GL45C.glBindSampler(0, blockSampler); GL45C.glBindSampler(1, lightSampler); setTexture(blockId, 0); setTexture(lightId, 1); - //the +8*6 is to offset to the unassigned dispatch - glBufferAddressRangeNV(GL_DRAW_INDIRECT_ADDRESS_NV, 0, commandAddr, regionCount*8L);//Bind the command buffer - glMultiDrawMeshTasksIndirectNV( 0, regionCount, 0); + // the +8*6 is to offset to the unassigned dispatch + glBufferAddressRangeNV(GL_DRAW_INDIRECT_ADDRESS_NV, 0, commandAddr, regionCount * 8L); // Bind the command buffer + glMultiDrawMeshTasksIndirectNV(0, regionCount, 0); GL45C.glBindSampler(0, 0); GL45C.glBindSampler(1, 0); } @@ -71,4 +79,4 @@ public void delete() { GL45.glDeleteSamplers(lightSampler); shader.delete(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/sodiumCompat/IrisCheck.java b/src/main/java/me/cortex/nvidium/sodiumCompat/IrisCheck.java index 962ecfe5..40efa361 100644 --- a/src/main/java/me/cortex/nvidium/sodiumCompat/IrisCheck.java +++ b/src/main/java/me/cortex/nvidium/sodiumCompat/IrisCheck.java @@ -1,16 +1,20 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.sodiumCompat; -import net.fabricmc.loader.api.FabricLoader; -import net.irisshaders.iris.api.v0.IrisApi; +import net.neoforged.fml.ModList; public class IrisCheck { - public static final boolean IRIS_LOADED = FabricLoader.getInstance().isModLoaded("iris"); + public static final boolean IRIS_LOADED = ModList.get().isLoaded("iris"); - private static boolean checkIrisShaders() { - return IrisApi.getInstance().isShaderPackInUse(); - } public static boolean checkIrisShouldDisable() { - return !(IRIS_LOADED && checkIrisShaders()); + return IRIS_LOADED; } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumCompactChunkVertex.java b/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumCompactChunkVertex.java index 473a16c8..7af1dc41 100644 --- a/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumCompactChunkVertex.java +++ b/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumCompactChunkVertex.java @@ -1,19 +1,24 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.sodiumCompat; -import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexAttributeFormat; -import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexFormat; -import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.Material; -import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkMeshAttribute; -import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; -import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; import net.caffeinemc.mods.sodium.api.util.ColorABGR; import net.caffeinemc.mods.sodium.api.util.ColorU8; -import net.minecraft.util.math.MathHelper; +import net.caffeinemc.mods.sodium.client.gl.attribute.GlVertexFormat; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material; +import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; +import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; +import net.minecraft.util.Mth; import org.lwjgl.system.MemoryUtil; public class NvidiumCompactChunkVertex implements ChunkVertexType { - public static final GlVertexFormat VERTEX_FORMAT = new GlVertexFormat<>(ChunkMeshAttribute.class, null, 16); public static final int STRIDE = 16; public static final NvidiumCompactChunkVertex INSTANCE = new NvidiumCompactChunkVertex(); @@ -29,43 +34,34 @@ public class NvidiumCompactChunkVertex implements ChunkVertexType { @Override - public float getTextureScale() { - return TEXTURE_SCALE; - } - - @Override - public float getPositionScale() { - return MODEL_SCALE; - } - - @Override - public float getPositionOffset() { - return -MODEL_ORIGIN; - } - - @Override - public GlVertexFormat getVertexFormat() { - return VERTEX_FORMAT; + public GlVertexFormat getVertexFormat() { + return null; } @Override public ChunkVertexEncoder getEncoder() { - return (ptr, material, vertex, sectionIndex) -> { - int light = compactLight(vertex.light); - - MemoryUtil.memPutInt(ptr + 0, (encodePosition(vertex.x) << 0) | (encodePosition(vertex.y) << 16)); - MemoryUtil.memPutInt(ptr + 4, (encodePosition(vertex.z) << 0) | (encodeDrawParameters(material) << 16) | ((light&0xFF)<<24)); - MemoryUtil.memPutInt(ptr + 8, (encodeColor(vertex.color) << 0) | (((light>>8)&0xFF) << 24)); - MemoryUtil.memPutInt(ptr + 12, encodeTexture(vertex.u, vertex.v)); - - return ptr + STRIDE; + return new ChunkVertexEncoder() { + @Override + public long write(long l, int i, Vertex[] vertices, int i1) { + return 0; + } + + public long write(long ptr, Material material, ChunkVertexEncoder.Vertex vertex, int sectionIndex) { + int light = compactLight(vertex.light); + + MemoryUtil.memPutInt(ptr + 0, (encodePosition(vertex.x) << 0) | (encodePosition(vertex.y) << 16)); + MemoryUtil.memPutInt(ptr + 4, (encodePosition(vertex.z) << 0) | (encodeDrawParameters(material) << 16) | ((light & 0xFF) << 24)); + MemoryUtil.memPutInt(ptr + 8, (encodeColor(vertex.color) << 0) | (((light >> 8) & 0xFF) << 24)); + MemoryUtil.memPutInt(ptr + 12, encodeTexture(vertex.u, vertex.v)); + + return ptr + STRIDE; + } }; } - private static int compactLight(int light) { - int sky = MathHelper.clamp((light >>> 16) & 0xFF, 8, 248); - int block = MathHelper.clamp((light >>> 0) & 0xFF, 8, 248); + int sky = Mth.clamp((light >>> 16) & 0xFF, 8, 248); + int block = Mth.clamp((light >>> 0) & 0xFF, 8, 248); return (block << 0) | (sky << 8); } @@ -78,7 +74,6 @@ private static int encodeDrawParameters(Material material) { return ((material.bits() & 0xFF) << 0); } - private static int encodeColor(int color) { var brightness = ColorU8.byteToNormalizedFloat(ColorABGR.unpackAlpha(color)); @@ -89,9 +84,8 @@ private static int encodeColor(int color) { return ColorABGR.pack(r, g, b, 0x00); } - private static int encodeTexture(float u, float v) { return ((Math.round(u * TEXTURE_MAX_VALUE) & 0xFFFF) << 0) | ((Math.round(v * TEXTURE_MAX_VALUE) & 0xFFFF) << 16); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumOptionFlags.java b/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumOptionFlags.java index a5a1c2a5..9e598031 100644 --- a/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumOptionFlags.java +++ b/src/main/java/me/cortex/nvidium/sodiumCompat/NvidiumOptionFlags.java @@ -1,6 +1,15 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.sodiumCompat; -import me.jellysquid.mods.sodium.client.gui.options.OptionFlag; + +import net.caffeinemc.mods.sodium.client.gui.options.OptionFlag; public class NvidiumOptionFlags { public static OptionFlag REQUIRES_SHADER_RELOAD; diff --git a/src/main/java/me/cortex/nvidium/sodiumCompat/RepackagedSectionOutput.java b/src/main/java/me/cortex/nvidium/sodiumCompat/RepackagedSectionOutput.java index 2f065853..167c690f 100644 --- a/src/main/java/me/cortex/nvidium/sodiumCompat/RepackagedSectionOutput.java +++ b/src/main/java/me/cortex/nvidium/sodiumCompat/RepackagedSectionOutput.java @@ -1,6 +1,14 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.sodiumCompat; -import me.jellysquid.mods.sodium.client.util.NativeBuffer; +import net.caffeinemc.mods.sodium.client.util.NativeBuffer; import org.joml.Vector3i; //Computed on the build thread instead of the render thread saving alot of 1% lows diff --git a/src/main/java/me/cortex/nvidium/sodiumCompat/ShaderLoader.java b/src/main/java/me/cortex/nvidium/sodiumCompat/ShaderLoader.java index a6d2cb6c..cbcf9500 100644 --- a/src/main/java/me/cortex/nvidium/sodiumCompat/ShaderLoader.java +++ b/src/main/java/me/cortex/nvidium/sodiumCompat/ShaderLoader.java @@ -1,20 +1,33 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.sodiumCompat; import me.cortex.nvidium.Nvidium; import me.cortex.nvidium.config.StatisticsLoggingLevel; import me.cortex.nvidium.config.TranslucencySortingLevel; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderConstants; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderParser; -import net.minecraft.util.Identifier; +import net.caffeinemc.mods.sodium.client.gl.shader.ShaderConstants; +import net.caffeinemc.mods.sodium.client.gl.shader.ShaderParser; + + +import net.minecraft.resources.ResourceLocation; import java.util.function.Consumer; public class ShaderLoader { - public static String parse(Identifier path) { + + + public static String parse(ResourceLocation path) { return parse(path, shaderConstants -> {}); } - public static String parse(Identifier path, Consumer constantBuilder) { + + public static String parse(ResourceLocation path, Consumer constantBuilder) { var builder = ShaderConstants.builder(); if (Nvidium.IS_DEBUG) { builder.add("DEBUG"); @@ -38,4 +51,4 @@ public static String parse(Identifier path, Consumer co return ShaderParser.parseShader("#import <"+path.getNamespace()+":"+path.getPath()+">", builder.build()); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/nvidium/sodiumCompat/SodiumResultCompatibility.java b/src/main/java/me/cortex/nvidium/sodiumCompat/SodiumResultCompatibility.java index f9bd3d9e..569300e0 100644 --- a/src/main/java/me/cortex/nvidium/sodiumCompat/SodiumResultCompatibility.java +++ b/src/main/java/me/cortex/nvidium/sodiumCompat/SodiumResultCompatibility.java @@ -1,15 +1,19 @@ +/* + * Nvidium - High performance rendering engine for Minecraft + * Copyright (C) 2023 cortex + * + * Modified by 1Influence (2025) - Ported to NeoForge. + * Licensed under LGPL-3.0-only + */ + package me.cortex.nvidium.sodiumCompat; -import it.unimi.dsi.fastutil.ints.IntArrays; import it.unimi.dsi.fastutil.longs.LongArrays; -import me.cortex.nvidium.Nvidium; -import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; -import me.jellysquid.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; -import me.jellysquid.mods.sodium.client.util.NativeBuffer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.math.Vec3d; -import org.joml.Vector3f; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionMeshParts; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; +import net.caffeinemc.mods.sodium.client.util.NativeBuffer; +import net.minecraft.client.Minecraft; import org.joml.Vector3i; import org.lwjgl.system.MemoryUtil; @@ -17,7 +21,7 @@ public class SodiumResultCompatibility { public static RepackagedSectionOutput repackage(ChunkBuildOutput result) { int formatSize = 16; - int geometryBytes = result.meshes.values().stream().mapToInt(a->a.getVertexData().getLength()).sum(); + int geometryBytes = result.meshes.values().stream().mapToInt(a -> a.getVertexData().getLength()).sum(); var output = new NativeBuffer(geometryBytes); var offsets = new short[8]; var min = new Vector3i(2000); @@ -40,45 +44,50 @@ public static RepackagedSectionOutput repackage(ChunkBuildOutput result) { max.y = Math.max(max.y, 0); max.z = Math.max(max.z, 0); - size = new Vector3i(max.x - min.x - 1, max.y - min.y - 1, max.z - min.z - 1); + size = new Vector3i(max.x - min.x - 1, max.y - min.y - 1, max.z - min.z - 1); size.x = Math.min(15, Math.max(size.x, 0)); size.y = Math.min(15, Math.max(size.y, 0)); size.z = Math.min(15, Math.max(size.z, 0)); } - var repackagedGeometry = new RepackagedSectionOutput((geometryBytes/formatSize)/4, output, offsets, min, size); - //NvidiumGeometryReencoder.transpileGeometry(repackagedGeometry); + var repackagedGeometry = new RepackagedSectionOutput((geometryBytes / formatSize) / 4, output, offsets, min, size); return repackagedGeometry; } - private static void copyQuad(long from, long too) { - //Quads are 64 bytes big - for (long i = 0; i < 64; i+=8) { + // Quads are 64 bytes big + for (long i = 0; i < 64; i += 8) { MemoryUtil.memPutLong(too + i, MemoryUtil.memGetLong(from + i)); } } - //Everything is /6*4 cause its in indices and we want verticies + + private static int getVertexCount(BuiltSectionMeshParts mesh) { + return mesh.getVertexData().getLength() / 16; + } + + + private static long getVertexDataAddress(BuiltSectionMeshParts mesh) { + return MemoryUtil.memAddress(mesh.getVertexData().getDirectBuffer()); + } + private static void packageSectionGeometry(int formatSize, NativeBuffer output, short[] outOffsets, ChunkBuildOutput result, Vector3i min, Vector3i max) { int offset = 0; long outPtr = MemoryUtil.memAddress(output.getDirectBuffer()); - //NOTE: mutates the input translucent geometry - var cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); + var cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); - float cpx = (float) (cameraPos.x - (result.render.getChunkX()<<4)); - float cpy = (float) (cameraPos.y - (result.render.getChunkY()<<4)); - float cpz = (float) (cameraPos.z - (result.render.getChunkZ()<<4)); + float cpx = (float) (cameraPos.x - (result.render.getChunkX() << 4)); + float cpy = (float) (cameraPos.y - (result.render.getChunkY() << 4)); + float cpz = (float) (cameraPos.z - (result.render.getChunkZ() << 4)); - {//Project the camera pos onto the bounding outline of the chunk (-8 -> 24 for each axis) - float len = (float) Math.sqrt(cpx*cpx + cpy*cpy + cpz*cpz); - cpx *= 1/len; - cpy *= 1/len; - cpz *= 1/len; + { + float len = (float) Math.sqrt(cpx * cpx + cpy * cpy + cpz * cpz); + cpx *= 1 / len; + cpy *= 1 / len; + cpz *= 1 / len; - //The max range of the camera can be is like 32 blocks away so just use that len = Math.min(len, 32); cpx *= len; @@ -86,147 +95,131 @@ private static void packageSectionGeometry(int formatSize, NativeBuffer output, cpz *= len; } - //Do translucent first - var translucentData = result.meshes.get(DefaultTerrainRenderPasses.TRANSLUCENT); + // Do translucent first + var translucentData = result.meshes.get(DefaultTerrainRenderPasses.TRANSLUCENT); if (translucentData != null) { - int quadCount = 0; - for (int i = 0; i < 7; i++) { - var part = translucentData.getVertexRanges()[i]; - quadCount += part != null?part.vertexCount()/4:0; - } - int quadId = 0; - long[] sortingData = new long[quadCount]; - long[] srcs = new long[7]; - for (int i = 0; i < 7; i++) { - var part = translucentData.getVertexRanges()[i]; - if (part != null) { - long src = MemoryUtil.memAddress(translucentData.getVertexData().getDirectBuffer()) + (long) part.vertexStart() * formatSize; - srcs[i] = src; - - float cx = 0; - float cy = 0; - float cz = 0; - //Update the meta bits of the model format - for (int j = 0; j < part.vertexCount(); j++) { - long base = src + (long) j * formatSize; - byte flags = (byte) 0b100;//Mipping, No alpha cut - MemoryUtil.memPutByte(base + 6L, flags);//Note: the 6 here is the offset into the vertex format - - float x = decodePosition(MemoryUtil.memGetShort(base)); - float y = decodePosition(MemoryUtil.memGetShort(base + 2)); - float z = decodePosition(MemoryUtil.memGetShort(base + 4)); - updateSectionBounds(min, max, x, y, z); - - cx += x; - cy += y; - cz += z; - - if ((j&3) == 3) { - //Compute the center point of the vertex - cx *= 1 / 4f; - cy *= 1 / 4f; - cz *= 1 / 4f; - - //Distance to camera - float dx = cx-cpx; - float dy = cy-cpy; - float dz = cz-cpz; - - float dist = dx*dx + dy*dy + dz*dz; - - int sortDistance = (int) (dist*(1<<12)); - - //We pack the sorting data - long packedSortingData = (((long)sortDistance)<<32)|((((long) j>>2)<<3)|i); - sortingData[quadId++] = packedSortingData; - - cx = 0; - cy = 0; - cz = 0; - } + int vertexCount = getVertexCount(translucentData); + int quadCount = vertexCount / 4; + + if (quadCount > 0) { + long[] sortingData = new long[quadCount]; + long src = getVertexDataAddress(translucentData); + + float cx = 0; + float cy = 0; + float cz = 0; + int quadId = 0; + + for (int j = 0; j < vertexCount; j++) { + long base = src + (long) j * formatSize; + byte flags = (byte) 0b100; // Mipping, No alpha cut + MemoryUtil.memPutByte(base + 6L, flags); + + float x = decodePosition(MemoryUtil.memGetShort(base)); + float y = decodePosition(MemoryUtil.memGetShort(base + 2)); + float z = decodePosition(MemoryUtil.memGetShort(base + 4)); + updateSectionBounds(min, max, x, y, z); + + cx += x; + cy += y; + cz += z; + + if ((j & 3) == 3) { + cx *= 1 / 4f; + cy *= 1 / 4f; + cz *= 1 / 4f; + + float dx = cx - cpx; + float dy = cy - cpy; + float dz = cz - cpz; + + float dist = dx * dx + dy * dy + dz * dz; + + int sortDistance = (int) (dist * (1 << 12)); + + long packedSortingData = (((long) sortDistance) << 32) | (quadId); + sortingData[quadId++] = packedSortingData; + + cx = 0; + cy = 0; + cz = 0; } } - } - if (quadId != sortingData.length) { - throw new IllegalStateException(); - } + LongArrays.radixSort(sortingData); - LongArrays.radixSort(sortingData); + for (int i = 0; i < sortingData.length; i++) { + long data = sortingData[i]; + int srcQuadIndex = (int) (data & 0xFFFFFFFFL); + copyQuad(src + srcQuadIndex * 4L * formatSize, outPtr + ((sortingData.length - 1) - i) * 4L * formatSize); + } - for (int i = 0; i < sortingData.length; i++) { - long data = sortingData[i]; - copyQuad(srcs[(int) (data&7)] + ((data>>3)&((1L<<29)-1))*4*formatSize, outPtr + ((sortingData.length-1)-i) * 4L * formatSize); + offset += quadCount; } - - - offset += quadCount; } outOffsets[7] = (short) offset; - - var solid = result.meshes.get(DefaultTerrainRenderPasses.SOLID); + var solid = result.meshes.get(DefaultTerrainRenderPasses.SOLID); var cutout = result.meshes.get(DefaultTerrainRenderPasses.CUTOUT); - //Do all but translucent - for (int i = 0; i < 7; i++) { - int poff = offset; - if (solid != null) { - var part = solid.getVertexRanges()[i]; - if (part != null) { - long src = MemoryUtil.memAddress(solid.getVertexData().getDirectBuffer()) + (long) part.vertexStart() * formatSize; - long dst = outPtr + offset * 4L * formatSize; - MemoryUtil.memCopy(src, dst, (long) part.vertexCount() * formatSize); - - //Update the meta bits of the model format - for (int j = 0; j < part.vertexCount(); j++) { - long base = dst+ (long) j * formatSize; - byte flags = (byte) 0b100;//Mipping, No alpha cut - MemoryUtil.memPutByte(base + 6L, flags);//Note: the 6 here is the offset into the vertex format - - updateSectionBounds(min, max, base); - } + // Process solid geometry + if (solid != null) { + int vertexCount = getVertexCount(solid); + if (vertexCount > 0) { + long src = getVertexDataAddress(solid); + long dst = outPtr + offset * 4L * formatSize; + MemoryUtil.memCopy(src, dst, (long) vertexCount * formatSize); + + for (int j = 0; j < vertexCount; j++) { + long base = dst + (long) j * formatSize; + byte flags = (byte) 0b100; // Mipping, No alpha cut + MemoryUtil.memPutByte(base + 6L, flags); - offset += part.vertexCount()/4; + updateSectionBounds(min, max, base); } + + offset += vertexCount / 4; } - if (cutout != null) { - var part = cutout.getVertexRanges()[i]; - if (part != null) { - long src = MemoryUtil.memAddress(cutout.getVertexData().getDirectBuffer()) + (long) part.vertexStart() * formatSize; - long dst = outPtr + offset * 4L * formatSize; - MemoryUtil.memCopy(src, dst, (long) part.vertexCount() * formatSize); - - //Update the meta bits of the model format - for (int j = 0; j < part.vertexCount(); j++) { - long base = dst + (long) j * formatSize; - short sflags = MemoryUtil.memGetByte(base + 6L); - short mipbits = (short) ((sflags&(3<<1))>>1); - //mipping, remap 0.5 cut to 0.1 when iris is loaded - if (mipbits == 0b10 && IrisCheck.IRIS_LOADED) { - mipbits = 0b01; - } - byte flags = (byte) (((sflags&1)<<2) | mipbits); - MemoryUtil.memPutByte(base + 6L, flags);//Note: the 6 here is the offset into the vertex format - - updateSectionBounds(min, max, base); + } + + // Process cutout geometry + if (cutout != null) { + int vertexCount = getVertexCount(cutout); + if (vertexCount > 0) { + long src = getVertexDataAddress(cutout); + long dst = outPtr + offset * 4L * formatSize; + MemoryUtil.memCopy(src, dst, (long) vertexCount * formatSize); + + for (int j = 0; j < vertexCount; j++) { + long base = dst + (long) j * formatSize; + short sflags = MemoryUtil.memGetByte(base + 6L); + short mipbits = (short) ((sflags & (3 << 1)) >> 1); + if (mipbits == 0b10 && IrisCheck.IRIS_LOADED) { + mipbits = 0b01; } + byte flags = (byte) (((sflags & 1) << 2) | mipbits); + MemoryUtil.memPutByte(base + 6L, flags); - offset += part.vertexCount()/4; + updateSectionBounds(min, max, base); } + + offset += vertexCount / 4; } - outOffsets[i] = (short) (offset - poff); } - if (offset*4*formatSize != output.getLength()) { - throw new IllegalStateException(); + + for (int i = 0; i < 7; i++) { + outOffsets[i] = (short) (offset - outOffsets[7]); } - } + if (offset * 4 * formatSize != output.getLength()) { + throw new IllegalStateException("Vertex data size mismatch: expected " + output.getLength() + ", got " + (offset * 4 * formatSize)); + } + } private static float decodePosition(short v) { - return Short.toUnsignedInt(v)*(1f/2048.0f)-8.0f; + return Short.toUnsignedInt(v) * (1f / 2048.0f) - 8.0f; } private static void updateSectionBounds(Vector3i min, Vector3i max, long vertex) { @@ -245,4 +238,4 @@ private static void updateSectionBounds(Vector3i min, Vector3i max, float x, flo max.y = (int) Math.max(max.y, Math.ceil(y)); max.z = (int) Math.max(max.z, Math.ceil(z)); } -} +} \ No newline at end of file diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 00000000..e6d1785b --- /dev/null +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,34 @@ +modLoader = "javafml" +loaderVersion = "[4,)" +license = "LGPL-3.0-only" + + +[[mods]] +modId = "nvidium" +version = "${version}" +displayName = "Nvidium (NeoForge Port)" +authors = "Cortex (Original), 1Influence (Port)" +description = ''' +Unofficial NeoForge port of Nvidium. +''' + +[[dependencies.nvidium]] +modId = "neoforge" +type = "required" +versionRange = "[21.0.167,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.nvidium]] +modId = "minecraft" +type = "required" +versionRange = "[1.21,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.nvidium]] +modId = "sodium" +type = "required" +versionRange = "[0.6.0,)" +ordering = "AFTER" +side = "CLIENT" \ No newline at end of file diff --git a/src/main/resources/assets/nvidium/nvidium.png b/src/main/resources/assets/nvidium/nvidium.png index a17d47b9..ee2106f0 100644 Binary files a/src/main/resources/assets/nvidium/nvidium.png and b/src/main/resources/assets/nvidium/nvidium.png differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json deleted file mode 100644 index c0a9795f..00000000 --- a/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "schemaVersion": 1, - "id": "nvidium", - "version": "${version}", - "custom": { - "commit": "${commit}", - "buildtime": "${buildtime}" - }, - "name": "Nvidium", - "description": "Replacement rendering engine for sodium", - "authors": [ - "Cortex" - ], - "contact": {}, - "license": "LGPL-3.0", - "icon": "assets/nvidium/nvidium.png", - "environment": "client", - "entrypoints": {}, - "mixins": [ - "nvidium.mixins.json" - ], - "depends": { - "fabricloader": ">=0.15", - "minecraft": ">=1.21", - "sodium": ["=0.5.9", "=0.5.11"] - } -}