painn
This commit is contained in:
@@ -17,29 +17,29 @@ import java.util.function.Function;
|
||||
public class VoxyClient implements ClientModInitializer {
|
||||
private static final HashSet<String> 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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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<Runnable> resultJobs = new ArrayDeque<>();
|
||||
|
||||
private Object2IntMap<BlockState> 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<BlockState> 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
|
||||
|
||||
@@ -27,6 +27,7 @@ public abstract class Viewport <A extends Viewport<A>> {
|
||||
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 <A extends Viewport<A>> {
|
||||
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;
|
||||
|
||||
@@ -102,20 +102,34 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
||||
String opaqueFrag = pipeline.patchOpaqueShader(this, frag);
|
||||
opaqueFrag = opaqueFrag==null?frag:opaqueFrag;
|
||||
|
||||
this.terrainShader = builder.clone()
|
||||
.addSource(ShaderType.FRAGMENT, opaqueFrag)
|
||||
.compile();
|
||||
//TODO: find a more robust/nicer way todo this
|
||||
this.terrainShader = tryCompilePatchedOrNormal(builder, opaqueFrag, frag);
|
||||
|
||||
String translucentFrag = pipeline.patchTranslucentShader(this, frag);
|
||||
if (translucentFrag == null) {
|
||||
this.translucentTerrainShader = builder.clone()
|
||||
.addSource(ShaderType.FRAGMENT, opaqueFrag)
|
||||
.compile();
|
||||
if (translucentFrag != null) {
|
||||
this.translucentTerrainShader = tryCompilePatchedOrNormal(builder, translucentFrag, frag);
|
||||
} else {
|
||||
this.translucentTerrainShader = this.terrainShader;
|
||||
}
|
||||
}
|
||||
|
||||
private static Shader tryCompilePatchedOrNormal(Shader.Builder<?> 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<MDICViewport, B
|
||||
private void renderTerrain(MDICViewport viewport, long indirectOffset, long drawCountOffset, int maxDrawCount) {
|
||||
//RenderLayer.getCutoutMipped().startDrawing();
|
||||
|
||||
this.pipeline.bindOpaqueFramebuffer();
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
this.terrainShader.bind();
|
||||
glBindVertexArray(RenderService.STATIC_VAO);//Needs to be before binding
|
||||
this.pipeline.setupAndBindOpaque(viewport);
|
||||
this.bindRenderingBuffers(viewport);
|
||||
|
||||
glMemoryBarrier(GL_COMMAND_BARRIER_BIT|GL_SHADER_STORAGE_BARRIER_BIT);//Barrier everything is needed
|
||||
@@ -187,7 +201,6 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
||||
@Override
|
||||
public void renderTranslucent(MDICViewport viewport) {
|
||||
if (this.geometryManager.getSectionCount() == 0) return;
|
||||
this.pipeline.bindTranslucentFramebuffer();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
@@ -196,6 +209,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
this.translucentTerrainShader.bind();
|
||||
glBindVertexArray(RenderService.STATIC_VAO);//Needs to be before binding
|
||||
this.pipeline.setupAndBindTranslucent(viewport);
|
||||
this.bindRenderingBuffers(viewport);
|
||||
|
||||
glMemoryBarrier(GL_COMMAND_BARRIER_BIT|GL_SHADER_STORAGE_BARRIER_BIT);//Barrier everything is needed
|
||||
|
||||
@@ -41,6 +41,10 @@ public class UploadStream {
|
||||
data.cpyTo(this.upload(buffer, destOffset, data.size));
|
||||
}
|
||||
|
||||
public long uploadTo(GlBuffer buffer) {
|
||||
return this.upload(buffer, 0, buffer.size());
|
||||
}
|
||||
|
||||
public long upload(GlBuffer buffer, long destOffset, long size) {
|
||||
long addr = this.rawUploadAddress((int) size);
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package me.cortex.voxy.client.core.util;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.irisshaders.iris.gl.IrisRenderSystem;
|
||||
import net.irisshaders.iris.shadows.ShadowRenderer;
|
||||
|
||||
public class IrisUtil {
|
||||
private static final boolean IRIS_INSTALLED = FabricLoader.getInstance().isModLoaded("iris");
|
||||
public static final boolean IRIS_INSTALLED = FabricLoader.getInstance().isModLoaded("iris");
|
||||
|
||||
|
||||
private static boolean irisShadowActive0() {
|
||||
@@ -14,4 +15,14 @@ public class IrisUtil {
|
||||
public static boolean irisShadowActive() {
|
||||
return IRIS_INSTALLED && irisShadowActive0();
|
||||
}
|
||||
|
||||
public static void clearIrisSamplers() {
|
||||
if (IRIS_INSTALLED) clearIrisSamplers0();
|
||||
}
|
||||
|
||||
private static void clearIrisSamplers0() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
IrisRenderSystem.bindSamplerToUnit(i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package me.cortex.voxy.client.mixin.minecraft;
|
||||
|
||||
|
||||
import com.mojang.blaze3d.shaders.ShaderType;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import me.cortex.voxy.client.VoxyClient;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
//Thanks iris for making me need todo this ;-; _irritater_
|
||||
@Mixin(RenderSystem.class)
|
||||
public class MixinRenderSystem {
|
||||
//We need to inject before iris to initalize our systems
|
||||
@Inject(method = "initRenderer", order = 900, remap = false, at = @At("RETURN"))
|
||||
private static void voxy$injectInit(long windowHandle, int debugVerbosity, boolean sync, BiFunction<Identifier, ShaderType, String> shaderSourceGetter, boolean renderDebugLabels, CallbackInfo ci) {
|
||||
VoxyClient.initVoxyClient();
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <voxy:lod/block_model.glsl>
|
||||
|
||||
#endif
|
||||
|
||||
#import <voxy:lod/gl46/bindings.glsl>
|
||||
|
||||
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
|
||||
//#endif
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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": [
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user