diff --git a/src/main/java/me/cortex/voxy/client/VoxyClient.java b/src/main/java/me/cortex/voxy/client/VoxyClient.java index 9525315d..024ff8c4 100644 --- a/src/main/java/me/cortex/voxy/client/VoxyClient.java +++ b/src/main/java/me/cortex/voxy/client/VoxyClient.java @@ -17,29 +17,29 @@ import java.util.function.Function; public class VoxyClient implements ClientModInitializer { private static final HashSet FREX = new HashSet<>(); + + public static void initVoxyClient() { + Capabilities.init();//Ensure clinit is called + + boolean systemSupported = Capabilities.INSTANCE.compute && Capabilities.INSTANCE.indirectParameters; + if (systemSupported) { + + SharedIndexBuffer.INSTANCE.id(); + BudgetBufferRenderer.init(); + + VoxyCommon.setInstanceFactory(VoxyClientInstance::new); + + if (!Capabilities.INSTANCE.subgroup) { + Logger.warn("GPU does not support subgroup operations, expect some performance degradation"); + } + + } else { + Logger.error("Voxy is unsupported on your system."); + } + } + @Override public void onInitializeClient() { - ClientLifecycleEvents.CLIENT_STARTED.register(client->{ - Capabilities.init();//Ensure clinit is called - - boolean systemSupported = Capabilities.INSTANCE.compute && Capabilities.INSTANCE.indirectParameters; - if (systemSupported) { - - SharedIndexBuffer.INSTANCE.id(); - BudgetBufferRenderer.init(); - - VoxyCommon.setInstanceFactory(VoxyClientInstance::new); - - if (!Capabilities.INSTANCE.subgroup) { - Logger.warn("GPU does not support subgroup operations, expect some performance degradation"); - } - - } else { - Logger.error("Voxy is unsupported on your system."); - } - }); - - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { if (VoxyCommon.isAvailable()) { dispatcher.register(VoxyCommands.register()); diff --git a/src/main/java/me/cortex/voxy/client/core/AbstractRenderPipeline.java b/src/main/java/me/cortex/voxy/client/core/AbstractRenderPipeline.java index 7d766e3c..0ef1ccb6 100644 --- a/src/main/java/me/cortex/voxy/client/core/AbstractRenderPipeline.java +++ b/src/main/java/me/cortex/voxy/client/core/AbstractRenderPipeline.java @@ -2,6 +2,7 @@ package me.cortex.voxy.client.core; import me.cortex.voxy.client.RenderStatistics; import me.cortex.voxy.client.TimingStatistics; +import me.cortex.voxy.client.core.model.ModelBakerySubsystem; import me.cortex.voxy.client.core.rendering.Viewport; import me.cortex.voxy.client.core.rendering.hierachical.AsyncNodeManager; import me.cortex.voxy.client.core.rendering.hierachical.HierarchicalOcclusionTraverser; @@ -60,6 +61,9 @@ public abstract class AbstractRenderPipeline extends TrackedObject { this.traversal = traversal; } + //Allows pipelines to configure model baking system + public void setupExtraModelBakeryData(ModelBakerySubsystem modelService) {} + public final void setSectionRenderer(AbstractSectionRenderer sectionRenderer) {//Stupid java ordering not allowing something pre super if (this.sectionRenderer != null) throw new IllegalStateException(); this.sectionRenderer = sectionRenderer; @@ -67,12 +71,12 @@ public abstract class AbstractRenderPipeline extends TrackedObject { protected abstract int setup(Viewport viewport, int sourceFramebuffer); protected abstract void postOpaquePreTranslucent(Viewport viewport); - protected void finish(Viewport viewport, Matrix4fc mcProjection, int sourceFrameBuffer) { + protected void finish(Viewport viewport, int sourceFrameBuffer) { glDisable(GL_STENCIL_TEST); glBindFramebuffer(GL_FRAMEBUFFER, sourceFrameBuffer); } - public void runPipeline(Viewport viewport, Matrix4fc mcProjection, int sourceFrameBuffer) { + public void runPipeline(Viewport viewport, int sourceFrameBuffer) { int depthTexture = this.setup(viewport, sourceFrameBuffer); var rs = ((AbstractSectionRenderer)this.sectionRenderer); @@ -85,7 +89,7 @@ public abstract class AbstractRenderPipeline extends TrackedObject { rs.renderTranslucent(viewport); - this.finish(viewport, mcProjection, sourceFrameBuffer); + this.finish(viewport, sourceFrameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, sourceFrameBuffer); } @@ -186,8 +190,9 @@ public abstract class AbstractRenderPipeline extends TrackedObject { RenderStatistics.addDebug(debug); } - public abstract void bindOpaqueFramebuffer(); - public abstract void bindTranslucentFramebuffer(); + //Binds the framebuffer and any other bindings needed for rendering + public abstract void setupAndBindOpaque(Viewport viewport); + public abstract void setupAndBindTranslucent(Viewport viewport); //null means dont transform the shader @@ -199,4 +204,5 @@ public abstract class AbstractRenderPipeline extends TrackedObject { public String patchTranslucentShader(AbstractSectionRenderer renderer, String input) { return null; } + } diff --git a/src/main/java/me/cortex/voxy/client/core/NormalRenderPipeline.java b/src/main/java/me/cortex/voxy/client/core/NormalRenderPipeline.java index bc6ec93f..aa023787 100644 --- a/src/main/java/me/cortex/voxy/client/core/NormalRenderPipeline.java +++ b/src/main/java/me/cortex/voxy/client/core/NormalRenderPipeline.java @@ -102,7 +102,7 @@ public class NormalRenderPipeline extends AbstractRenderPipeline { } @Override - protected void finish(Viewport viewport, Matrix4fc mcProjection, int sourceFrameBuffer) { + protected void finish(Viewport viewport, int sourceFrameBuffer) { this.finalBlit.bind(); if (this.useEnvFog) { float start = viewport.fogParameters.environmentalStart(); @@ -113,18 +113,18 @@ public class NormalRenderPipeline extends AbstractRenderPipeline { } glBindTextureUnit(3, this.colourSSAOTex.id); - AbstractRenderPipeline.transformBlitDepth(this.finalBlit, this.fb.getDepthTex().id, sourceFrameBuffer, viewport, new Matrix4f(mcProjection).mul(viewport.modelView)); + AbstractRenderPipeline.transformBlitDepth(this.finalBlit, this.fb.getDepthTex().id, sourceFrameBuffer, viewport, new Matrix4f(viewport.vanillaProjection).mul(viewport.modelView)); //glBlitNamedFramebuffer(this.fbSSAO.id, sourceFrameBuffer, 0,0, viewport.width, viewport.height, 0,0, viewport.width, viewport.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); } @Override - public void bindOpaqueFramebuffer() { + public void setupAndBindOpaque(Viewport viewport) { this.fb.bind(); } @Override - public void bindTranslucentFramebuffer() { + public void setupAndBindTranslucent(Viewport viewport) { glBindFramebuffer(GL_FRAMEBUFFER, this.fbSSAO.id); } diff --git a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java index d46c91cd..39d890a3 100644 --- a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java +++ b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java @@ -26,12 +26,17 @@ import me.cortex.voxy.client.core.util.IrisUtil; import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.thread.ServiceThreadPool; import me.cortex.voxy.common.world.WorldEngine; +import me.cortex.voxy.commonImpl.VoxyCommon; import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; import net.caffeinemc.mods.sodium.client.util.FogParameters; +import net.irisshaders.iris.Iris; +import net.irisshaders.iris.pipeline.programs.SodiumShader; import net.minecraft.client.MinecraftClient; import org.joml.Matrix4f; import org.joml.Matrix4fc; import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL30; import java.util.Arrays; import java.util.List; @@ -39,9 +44,12 @@ import java.util.List; import static org.lwjgl.opengl.GL11.GL_VIEWPORT; import static org.lwjgl.opengl.GL11.glGetIntegerv; import static org.lwjgl.opengl.GL11C.*; -import static org.lwjgl.opengl.GL30C.GL_DRAW_FRAMEBUFFER_BINDING; -import static org.lwjgl.opengl.GL30C.glBindFramebuffer; +import static org.lwjgl.opengl.GL30.glBindBufferRange; +import static org.lwjgl.opengl.GL30C.*; +import static org.lwjgl.opengl.GL32.glGetInteger64i; import static org.lwjgl.opengl.GL33.glBindSampler; +import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER; +import static org.lwjgl.opengl.GL43C.*; public class VoxyRenderSystem { private final WorldEngine worldIn; @@ -71,6 +79,13 @@ public class VoxyRenderSystem { //Keep the world loaded, NOTE: this is done FIRST, to keep and ensure that even if the rest of loading takes more // than timeout, we keep the world acquired world.acquireRef(); + + //Fking HATE EVERYTHING AAAAAAAAAAAAAAAA + int[] oldBufferBindings = new int[10]; + for (int i = 0; i < oldBufferBindings.length; i++) { + oldBufferBindings[i] = glGetIntegeri(GL_SHADER_STORAGE_BUFFER_BINDING, i); + } + try { //wait for opengl to be finished, this should hopefully ensure all memory allocations are free glFinish(); @@ -100,6 +115,7 @@ public class VoxyRenderSystem { } this.pipeline = RenderPipelineFactory.createPipeline(this.nodeManager, this.nodeCleaner, this.traversal, this::frexStillHasWork); + this.pipeline.setupExtraModelBakeryData(this.modelService);//Configure the model service var sectionRenderer = createSectionRenderer(this.pipeline, this.modelService.getStore(), this.geometryData); this.pipeline.setSectionRenderer(sectionRenderer); this.viewportSelector = new ViewportSelector<>(sectionRenderer::createViewport); @@ -109,7 +125,7 @@ public class VoxyRenderSystem { int maxSec = (MinecraftClient.getInstance().world.getTopSectionCoord() - 1) >> 5; //Do some very cheeky stuff for MiB - if (false) { + if (VoxyCommon.IS_MINE_IN_ABYSS) {//TODO: make this somehow configurable minSec = -8; maxSec = 7; } @@ -125,32 +141,63 @@ public class VoxyRenderSystem { this.chunkBoundRenderer = new ChunkBoundRenderer(); - Logger.info("Voxy render system created with " + geometryCapacity + " geometry capacity, using pipeline '" + this.pipeline.getClass().getSimpleName() + "' with renderer '" + sectionRenderer.getClass().getSimpleName() + "'"); } catch (RuntimeException e) { world.releaseRef();//If something goes wrong, we must release the world first throw e; } + + for (int i = 0; i < oldBufferBindings.length; i++) { + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, oldBufferBindings[i]); + } } - public void renderOpaque(ChunkRenderMatrices matrices, FogParameters fogParameters, double cameraX, double cameraY, double cameraZ) { - if (IrisUtil.irisShadowActive()) { - return; - } - TimingStatistics.resetSamplers(); - + public Viewport setupViewport(ChunkRenderMatrices matrices, FogParameters fogParameters, double cameraX, double cameraY, double cameraZ) { //Do some very cheeky stuff for MiB - if (false) { + if (VoxyCommon.IS_MINE_IN_ABYSS) { int sector = (((int)Math.floor(cameraX)>>4)+512)>>10; cameraX -= sector<<14;//10+4 cameraY += (16+(256-32-sector*30))*16; } + var projection = computeProjectionMat(matrices.projection());//RenderSystem.getProjectionMatrix(); + //var projection = new Matrix4f(matrices.projection()); + + int[] dims = new int[4]; + glGetIntegerv(GL_VIEWPORT, dims); + + var viewport = this.getViewport(); + viewport + .setVanillaProjection(matrices.projection()) + .setProjection(projection) + .setModelView(new Matrix4f(matrices.modelView())) + .setCamera(cameraX, cameraY, cameraZ) + .setScreenSize(dims[2], dims[3]) + .setFogParameters(fogParameters) + .update(); + viewport.frameId++; + + return viewport; + } + + public void renderOpaque(Viewport viewport) { + if (IrisUtil.irisShadowActive()) { + return; + } + TimingStatistics.resetSamplers(); + long startTime = System.nanoTime(); TimingStatistics.all.start(); TimingStatistics.main.start(); + //TODO: optimize + int[] oldBufferBindings = new int[10]; + for (int i = 0; i < oldBufferBindings.length; i++) { + oldBufferBindings[i] = glGetIntegeri(GL_SHADER_STORAGE_BUFFER_BINDING, i); + } + + int oldFB = GL11.glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING); int boundFB = oldFB; @@ -162,21 +209,6 @@ public class VoxyRenderSystem { //this.autoBalanceSubDivSize(); - var projection = computeProjectionMat(matrices.projection());//RenderSystem.getProjectionMatrix(); - //var projection = new Matrix4f(matrices.projection()); - - int[] dims = new int[4]; - glGetIntegerv(GL_VIEWPORT, dims); - - var viewport = this.getViewport(); - viewport - .setProjection(projection) - .setModelView(new Matrix4f(matrices.modelView())) - .setCamera(cameraX, cameraY, cameraZ) - .setScreenSize(dims[2], dims[3]) - .setFogParameters(fogParameters) - .update(); - viewport.frameId++; TimingStatistics.E.start(); this.chunkBoundRenderer.render(viewport); @@ -184,7 +216,7 @@ public class VoxyRenderSystem { //The entire rendering pipeline (excluding the chunkbound thing) - this.pipeline.runPipeline(viewport, matrices.projection(), boundFB); + this.pipeline.runPipeline(viewport, boundFB); TimingStatistics.main.stop(); @@ -197,7 +229,7 @@ public class VoxyRenderSystem { //Tick upload stream (this is ok to do here as upload ticking is just memory management) UploadStream.INSTANCE.tick(); - while (this.renderDistanceTracker.setCenterAndProcess(cameraX, cameraZ) && VoxyClient.isFrexActive());//While FF is active, run until everything is processed + while (this.renderDistanceTracker.setCenterAndProcess(viewport.cameraX, viewport.cameraZ) && VoxyClient.isFrexActive());//While FF is active, run until everything is processed //Done here as is allows less gl state resetup this.modelService.tick(Math.max(3_000_000-(System.nanoTime()-startTime), 500_000)); @@ -207,22 +239,29 @@ public class VoxyRenderSystem { glBindFramebuffer(GlConst.GL_FRAMEBUFFER, oldFB); {//Reset state manager stuffs + glUseProgram(0); glEnable(GL_DEPTH_TEST); GlStateManager._glBindVertexArray(0);//Clear binding - GlStateManager._activeTexture(GlConst.GL_TEXTURE0); - GlStateManager._bindTexture(0); - glBindSampler(0, 0); - GlStateManager._activeTexture(GlConst.GL_TEXTURE1); - GlStateManager._bindTexture(0); - glBindSampler(1, 0); + for (int i = 0; i < 16; i++) { + GlStateManager._activeTexture(GlConst.GL_TEXTURE0+i); + GlStateManager._bindTexture(0); + glBindSampler(i, 0); + } - GlStateManager._activeTexture(GlConst.GL_TEXTURE2); - GlStateManager._bindTexture(0); - glBindSampler(2, 0); + IrisUtil.clearIrisSamplers();//Thanks iris (sigh) + + //TODO: should/needto actually restore all of these, not just clear them + //Clear all the bindings + for (int i = 0; i < oldBufferBindings.length; i++) { + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, oldBufferBindings[i]); + } + + //((SodiumShader) Iris.getPipelineManager().getPipelineNullable().getSodiumPrograms().getProgram(DefaultTerrainRenderPasses.CUTOUT).getInterface()).setupState(DefaultTerrainRenderPasses.CUTOUT, fogParameters); } + TimingStatistics.all.stop(); /* @@ -375,7 +414,7 @@ public class VoxyRenderSystem { //Limit to available dedicated memory if possible if (Capabilities.INSTANCE.canQueryGpuMemory) { //512mb less than avalible, - long limit = Capabilities.INSTANCE.getFreeDedicatedGpuMemory() - 1024*1024*1024; + long limit = Capabilities.INSTANCE.getFreeDedicatedGpuMemory() - (long)(1.5*1024*1024*1024);//1.5gb vram buffer // Give a minimum of 512 mb requirement limit = Math.max(512*1024*1024, limit); diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java index 9824e63e..6048f2a5 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java @@ -1,6 +1,7 @@ package me.cortex.voxy.client.core.model; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectSet; @@ -118,6 +119,7 @@ public class ModelFactory { public final Deque resultJobs = new ArrayDeque<>(); + private Object2IntMap customBlockStateIdMapping; //TODO: NOTE!!! is it worth even uploading as a 16x16 texture, since automatic lod selection... doing 8x8 textures might be perfectly ok!!! // this _quarters_ the memory requirements for the texture atlas!!! WHICH IS HUGE saving @@ -141,6 +143,10 @@ public class ModelFactory { this.downstream.tick(); } + public void setCustomBlockStateMapping(Object2IntMap mapping) { + this.customBlockStateIdMapping = mapping; + } + public boolean addEntry(int blockId) { if (this.idMappings[blockId] != -1) { return false; @@ -456,6 +462,16 @@ public class ModelFactory { MemoryUtil.memPutInt(clrUploadPtr, captureColourConstant(colourProvider, blockState, biome)|0xFF000000); clrUploadPtr += 4; } } + uploadPtr += 4; + + //have 32 bytes of free space after here + + //install the custom mapping id if it exists + if (this.customBlockStateIdMapping != null && this.customBlockStateIdMapping.containsKey(blockState)) { + MemoryUtil.memPutInt(uploadPtr, this.customBlockStateIdMapping.getInt(blockState)); + } else { + MemoryUtil.memPutInt(uploadPtr, 0); + } uploadPtr += 4; //Note: if the layer isSolid then need to fill all the points in the texture where alpha == 0 with the average colour diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/Viewport.java b/src/main/java/me/cortex/voxy/client/core/rendering/Viewport.java index b952c60c..1ef4c970 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/Viewport.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/Viewport.java @@ -27,6 +27,7 @@ public abstract class Viewport > { public int width; public int height; public int frameId; + public Matrix4f vanillaProjection = new Matrix4f(); public Matrix4f projection; public Matrix4f modelView; public final FrustumIntersection frustum = new FrustumIntersection(); @@ -59,6 +60,11 @@ public abstract class Viewport > { this.depthBoundingBuffer.free(); } + public A setVanillaProjection(Matrix4fc projection) { + this.vanillaProjection.set(projection); + return (A) this; + } + public A setProjection(Matrix4f projection) { this.projection = projection; return (A) this; diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java index 2cd08f83..74a8de2f 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java @@ -102,20 +102,34 @@ public class MDICSectionRenderer extends AbstractSectionRenderer builder, String shader, String original) { + boolean patched = shader != original;//This is the correct comparison type (reference) + try { + return builder.clone() + .defineIf("PATCHED_SHADER", patched) + .addSource(ShaderType.FRAGMENT, shader) + .compile(); + } catch (RuntimeException e) { + if (patched) { + Logger.error("Failed to compile shader patch, using normal pipeline to prevent errors", e); + return tryCompilePatchedOrNormal(builder, original, original); + } else { + throw e; + } + } + } + private void uploadUniformBuffer(MDICViewport viewport) { long ptr = UploadStream.INSTANCE.upload(this.uniform, 0, 1024); @@ -153,12 +167,12 @@ public class MDICSectionRenderer extends AbstractSectionRenderer shaderSourceGetter, boolean renderDebugLabels, CallbackInfo ci) { + VoxyClient.initVoxyClient(); + } +} diff --git a/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java b/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java index 6637eadf..50651885 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java +++ b/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java @@ -18,7 +18,7 @@ public class MixinRenderPipeline { private void voxy$injectRender(TerrainRenderPass pass, Viewport frustum, FogParameters fogParameters, ChunkRenderMatrices crm, double px, double py, double pz, CallbackInfo ci) { var renderer = ((IGetVoxyRenderSystem) MinecraftClient.getInstance().worldRenderer).getVoxyRenderSystem(); if (renderer != null) { - renderer.renderOpaque(crm, fogParameters, px, py, pz); + renderer.renderOpaque(renderer.setupViewport(crm, fogParameters, px, py, pz)); } } } diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java index b7a36ca3..9f9bc61c 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java @@ -23,7 +23,7 @@ public class MixinDefaultChunkRenderer { if (renderPass == DefaultTerrainRenderPasses.CUTOUT) { var renderer = ((IGetVoxyRenderSystem) MinecraftClient.getInstance().worldRenderer).getVoxyRenderSystem(); if (renderer != null) { - renderer.renderOpaque(matrices, fogParameters, camera.x, camera.y, camera.z); + renderer.renderOpaque(renderer.setupViewport(matrices, fogParameters, camera.x, camera.y, camera.z)); } } } diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java index cdf82a66..0aacc88e 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java @@ -5,6 +5,7 @@ import me.cortex.voxy.client.config.VoxyConfig; import me.cortex.voxy.client.core.IGetVoxyRenderSystem; import me.cortex.voxy.client.core.VoxyRenderSystem; import me.cortex.voxy.common.world.service.VoxelIngestService; +import me.cortex.voxy.commonImpl.VoxyCommon; import net.caffeinemc.mods.sodium.client.gl.device.CommandList; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; @@ -94,7 +95,7 @@ public class MixinRenderSectionManager { } int x = instance.getChunkX(), y = instance.getChunkY(), z = instance.getChunkZ(); //Do some very cheeky stuff for MiB - if (false) { + if (VoxyCommon.IS_MINE_IN_ABYSS) { int sector = (x+512)>>10; x-=sector<<10; y+=16+(256-32-sector*30); diff --git a/src/main/java/me/cortex/voxy/common/world/WorldUpdater.java b/src/main/java/me/cortex/voxy/common/world/WorldUpdater.java index c335f931..c078999d 100644 --- a/src/main/java/me/cortex/voxy/common/world/WorldUpdater.java +++ b/src/main/java/me/cortex/voxy/common/world/WorldUpdater.java @@ -2,6 +2,7 @@ package me.cortex.voxy.common.world; import me.cortex.voxy.common.voxelization.VoxelizedSection; import me.cortex.voxy.common.world.other.Mapper; +import me.cortex.voxy.commonImpl.VoxyCommon; import static me.cortex.voxy.common.world.WorldEngine.*; @@ -12,7 +13,7 @@ public class WorldUpdater { public static void insertUpdate(WorldEngine into, VoxelizedSection section) {//TODO: add a bitset of levels to update and if it should force update //Do some very cheeky stuff for MiB - if (false) { + if (VoxyCommon.IS_MINE_IN_ABYSS) { int sector = (section.x+512)>>10; section.setPosition(section.x-(sector<<10), section.y+16+(256-32-sector*30), section.z);//Note sector size mult is 30 because the top chunk is replicated (and so is bottom chunk) } diff --git a/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java b/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java index f4430246..bf8c9509 100644 --- a/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java +++ b/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java @@ -85,4 +85,7 @@ public class VoxyCommon implements ModInitializer { public static boolean isAvailable() { return FACTORY != null; } + + + public static final boolean IS_MINE_IN_ABYSS = false; } diff --git a/src/main/resources/assets/voxy/shaders/lod/block_model.glsl b/src/main/resources/assets/voxy/shaders/lod/block_model.glsl index c4013b8d..b4971bb9 100644 --- a/src/main/resources/assets/voxy/shaders/lod/block_model.glsl +++ b/src/main/resources/assets/voxy/shaders/lod/block_model.glsl @@ -2,7 +2,8 @@ struct BlockModel { uint faceData[6]; uint flagsA; uint colourTint; - uint _pad[8]; + uint customId; + uint _pad[7]; }; //TODO: FIXME: this isnt actually correct cause depending on the face (i think) it could be 1/64 th of a position off diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag index 26656465..b460c97c 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag +++ b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag @@ -17,9 +17,18 @@ layout(location = 1) in flat uvec4 interData; #ifdef DEBUG_RENDER layout(location = 7) in flat uint quadDebug; #endif -layout(location = 0) out vec4 outColour; +#ifndef PATCHED_SHADER +layout(location = 0) out vec4 outColour; +#else + +//Bind the model buffer and import the model system as we need it +#define MODEL_BUFFER_BINDING 3 +#import + +#endif + #import vec4 uint2vec4RGBA(uint colour) { @@ -38,17 +47,23 @@ bool useCutout() { return (interData.x&1u)==1u; } -vec4 computeColour(vec4 colour) { - //Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha - if (useTinting() && abs(colour.r-colour.g) < 0.02f && abs(colour.g-colour.b) < 0.02f) { - colour *= uint2vec4RGBA(interData.z).yzwx; - } - return (colour * uint2vec4RGBA(interData.y)) + vec4(0,0,0,float(interData.w&0xFFu)/255); +uint getFace() { + #ifndef PATCHED_SHADER + return (interData.w>>8)&7u; + #else + return (interData.y>>8)&7u; + #endif } +#ifdef PATCHED_SHADER +vec2 getLightmap() { + //return clamp(vec2(interData.y&0xFu, (interData.y>>4)&0xFu)/16, vec2(4.0f/255), vec2(252.0f/255)); + return vec2(interData.y&0xFu, (interData.y>>4)&0xFu)/15; +} +#endif -uint getFace() { - return (interData.w>>8)&7u; +uint getModelId() { + return interData.x>>16; } vec2 getBaseUV() { @@ -58,6 +73,37 @@ vec2 getBaseUV() { return modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0))); } + +#ifdef PATCHED_SHADER +struct VoxyFragmentParameters { + //TODO: pass in derivative data + vec4 sampledColour; + vec2 tile; + vec2 uv; + uint face; + uint modelId; + vec2 lightMap; + vec4 tinting; + uint customId;//Same as iris's modelId +}; + +void voxy_emitFragment(VoxyFragmentParameters parameters); +#else + +vec4 computeColour(vec2 texturePos, vec4 colour) { + //Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha + if (useTinting()) { + vec4 tintTest = texture(blockModelAtlas, texturePos, -2); + if (abs(tintTest.r-tintTest.g) < 0.02f && abs(tintTest.g-tintTest.b) < 0.02f) { + colour *= uint2vec4RGBA(interData.z).yzwx; + } + } + return (colour * uint2vec4RGBA(interData.y)) + vec4(0,0,0,float(interData.w&0xFFu)/255); +} + +#endif + + void main() { //Tile is the tile we are in vec2 tile; @@ -92,11 +138,10 @@ void main() { #endif } - colour = computeColour(colour); - + #ifndef PATCHED_SHADER + colour = computeColour(texPos, colour); outColour = colour; - #ifdef DEBUG_RENDER uint hash = quadDebug*1231421+123141; hash ^= hash>>16; @@ -105,6 +150,21 @@ void main() { hash = hash * 1827364925 + 123325621; outColour = vec4(float(hash&15u)/15, float((hash>>4)&15u)/15, float((hash>>8)&15u)/15, 1); #endif + + #else + uint modelId = getModelId(); + BlockModel model = modelData[modelId]; + vec4 tint = vec4(1); + if (useTinting()) { + vec4 tintTest = texture(blockModelAtlas, texPos, -2); + if (abs(tintTest.r-tintTest.g) < 0.02f && abs(tintTest.g-tintTest.b) < 0.02f) { + tint = uint2vec4RGBA(interData.z).yzwx; + } + } + + voxy_emitFragment(VoxyFragmentParameters(colour, tile, texPos, getFace(), modelId, getLightmap().yx, tint, model.customId)); + + #endif } @@ -131,4 +191,5 @@ colour = textureGrad(blockModelAtlas, texPos, dx, dy); */ //#else //colour = texture(blockModelAtlas, texPos); -//#endif \ No newline at end of file +//#endif + diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert b/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert index 9f6a4db7..5c51a1e0 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert +++ b/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert @@ -129,6 +129,7 @@ void main() { flags |= uint(!modelHasMipmaps(model))<<1; //Compute lighting + uint lighting = extractLightId(quad); vec4 tinting = getLighting(extractLightId(quad)); //Apply model colour tinting @@ -143,6 +144,9 @@ void main() { conditionalTinting = tintColour; } + setSizeAndFlags(modelId, flags, quadSize); + + #ifndef PATCHED_SHADER uint addin = 0; if (!isTranslucent) { tinting.w = 0.0; @@ -167,8 +171,11 @@ void main() { } } - setSizeAndFlags(modelId, flags, quadSize); setTintingAndExtra(tinting, conditionalTinting, addin|(face<<8)); + #else + interData.y = lighting|(face<<8); + interData.z = tintColour; + #endif } diff --git a/src/main/resources/client.voxy.mixins.json b/src/main/resources/client.voxy.mixins.json index a4e9c449..6b649050 100644 --- a/src/main/resources/client.voxy.mixins.json +++ b/src/main/resources/client.voxy.mixins.json @@ -3,6 +3,14 @@ "package": "me.cortex.voxy.client.mixin", "compatibilityLevel": "JAVA_17", "client": [ + "iris.CustomUniformsAccessor", + "iris.IrisRenderingPipelineAccessor", + "iris.MixinIrisRenderingPipeline", + "iris.MixinIrisSamplers", + "iris.MixinMatrixUniforms", + "iris.MixinProgramSet", + "iris.MixinShaderPackSourceNames", + "iris.MixinStandardMacros", "minecraft.MixinClientChunkManager", "minecraft.MixinClientCommonNetworkHandler", "minecraft.MixinClientLoginNetworkHandler", @@ -10,6 +18,7 @@ "minecraft.MixinFogRenderer", "minecraft.MixinGlDebug", "minecraft.MixinMinecraftClient", + "minecraft.MixinRenderSystem", "minecraft.MixinThreadExecutor", "minecraft.MixinWindow", "minecraft.MixinWorldRenderer", @@ -20,7 +29,5 @@ ], "injectors": { "defaultRequire": 1 - }, - "mixins": [ - ] + } }