more changes

This commit is contained in:
mcrcortex
2025-08-14 22:19:01 +10:00
parent 634d187c11
commit d507429b9b
16 changed files with 89 additions and 282 deletions

View File

@@ -45,33 +45,11 @@ public class VoxyClientInstance extends VoxyInstance {
protected SectionStorage createStorage(WorldIdentifier identifier) { protected SectionStorage createStorage(WorldIdentifier identifier) {
var ctx = new ConfigBuildCtx(); var ctx = new ConfigBuildCtx();
ctx.setProperty(ConfigBuildCtx.BASE_SAVE_PATH, this.basePath.toString()); ctx.setProperty(ConfigBuildCtx.BASE_SAVE_PATH, this.basePath.toString());
ctx.setProperty(ConfigBuildCtx.WORLD_IDENTIFIER, getWorldId(identifier)); ctx.setProperty(ConfigBuildCtx.WORLD_IDENTIFIER, identifier.getWorldId());
ctx.pushPath(ConfigBuildCtx.DEFAULT_STORAGE_PATH); ctx.pushPath(ConfigBuildCtx.DEFAULT_STORAGE_PATH);
return this.storageConfig.build(ctx); return this.storageConfig.build(ctx);
} }
private static String bytesToHex(byte[] hash) {
StringBuilder hexString = new StringBuilder(2 * hash.length);
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
private static String getWorldId(WorldIdentifier identifier) {
String data = identifier.biomeSeed + identifier.key.toString();
try {
return bytesToHex(MessageDigest.getInstance("SHA-256").digest(data.getBytes())).substring(0, 32);
} catch (
NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
private static SectionStorageConfig getCreateStorageConfig(Path path) { private static SectionStorageConfig getCreateStorageConfig(Path path) {
var json = path.resolve("config.json"); var json = path.resolve("config.json");
Config config = null; Config config = null;

View File

@@ -10,7 +10,10 @@ import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.GlTexture;
import me.cortex.voxy.client.core.model.ModelBakerySubsystem; import me.cortex.voxy.client.core.model.ModelBakerySubsystem;
import me.cortex.voxy.client.core.model.ModelStore; import me.cortex.voxy.client.core.model.ModelStore;
import me.cortex.voxy.client.core.rendering.*; import me.cortex.voxy.client.core.rendering.ChunkBoundRenderer;
import me.cortex.voxy.client.core.rendering.RenderDistanceTracker;
import me.cortex.voxy.client.core.rendering.Viewport;
import me.cortex.voxy.client.core.rendering.ViewportSelector;
import me.cortex.voxy.client.core.rendering.building.RenderGenerationService; import me.cortex.voxy.client.core.rendering.building.RenderGenerationService;
import me.cortex.voxy.client.core.rendering.hierachical.AsyncNodeManager; import me.cortex.voxy.client.core.rendering.hierachical.AsyncNodeManager;
import me.cortex.voxy.client.core.rendering.hierachical.HierarchicalOcclusionTraverser; import me.cortex.voxy.client.core.rendering.hierachical.HierarchicalOcclusionTraverser;
@@ -28,15 +31,11 @@ import me.cortex.voxy.common.thread.ServiceThreadPool;
import me.cortex.voxy.common.world.WorldEngine; import me.cortex.voxy.common.world.WorldEngine;
import me.cortex.voxy.commonImpl.VoxyCommon; import me.cortex.voxy.commonImpl.VoxyCommon;
import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; 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.caffeinemc.mods.sodium.client.util.FogParameters;
import net.irisshaders.iris.Iris;
import net.irisshaders.iris.pipeline.programs.SodiumShader;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Matrix4fc; import org.joml.Matrix4fc;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -44,12 +43,10 @@ import java.util.List;
import static org.lwjgl.opengl.GL11.GL_VIEWPORT; import static org.lwjgl.opengl.GL11.GL_VIEWPORT;
import static org.lwjgl.opengl.GL11.glGetIntegerv; import static org.lwjgl.opengl.GL11.glGetIntegerv;
import static org.lwjgl.opengl.GL11C.*; import static org.lwjgl.opengl.GL11C.*;
import static org.lwjgl.opengl.GL30.glBindBufferRange;
import static org.lwjgl.opengl.GL30C.*; 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.GL33.glBindSampler;
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER; import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER;
import static org.lwjgl.opengl.GL43C.*; import static org.lwjgl.opengl.GL43C.GL_SHADER_STORAGE_BUFFER_BINDING;
public class VoxyRenderSystem { public class VoxyRenderSystem {
private final WorldEngine worldIn; private final WorldEngine worldIn;
@@ -154,6 +151,10 @@ public class VoxyRenderSystem {
public Viewport<?> setupViewport(ChunkRenderMatrices matrices, FogParameters fogParameters, double cameraX, double cameraY, double cameraZ) { public Viewport<?> setupViewport(ChunkRenderMatrices matrices, FogParameters fogParameters, double cameraX, double cameraY, double cameraZ) {
if (IrisUtil.irisShadowActive()) {
return null;
}
//Do some very cheeky stuff for MiB //Do some very cheeky stuff for MiB
if (VoxyCommon.IS_MINE_IN_ABYSS) { if (VoxyCommon.IS_MINE_IN_ABYSS) {
int sector = (((int)Math.floor(cameraX)>>4)+512)>>10; int sector = (((int)Math.floor(cameraX)>>4)+512)>>10;
@@ -161,7 +162,9 @@ public class VoxyRenderSystem {
cameraY += (16+(256-32-sector*30))*16; cameraY += (16+(256-32-sector*30))*16;
} }
//cameraY += 100;
var projection = computeProjectionMat(matrices.projection());//RenderSystem.getProjectionMatrix(); var projection = computeProjectionMat(matrices.projection());//RenderSystem.getProjectionMatrix();
//var projection = ShadowMatrices.createOrthoMatrix(160, -16*300, 16*300);
//var projection = new Matrix4f(matrices.projection()); //var projection = new Matrix4f(matrices.projection());
int[] dims = new int[4]; int[] dims = new int[4];
@@ -182,9 +185,10 @@ public class VoxyRenderSystem {
} }
public void renderOpaque(Viewport<?> viewport) { public void renderOpaque(Viewport<?> viewport) {
if (IrisUtil.irisShadowActive()) { if (viewport == null) {
return; return;
} }
TimingStatistics.resetSamplers(); TimingStatistics.resetSamplers();
long startTime = System.nanoTime(); long startTime = System.nanoTime();
@@ -211,7 +215,11 @@ public class VoxyRenderSystem {
TimingStatistics.E.start(); TimingStatistics.E.start();
if (!IrisUtil.irisShadowActive()) {
this.chunkBoundRenderer.render(viewport); this.chunkBoundRenderer.render(viewport);
} else {
viewport.depthBoundingBuffer.clear(0);
}
TimingStatistics.E.stop(); TimingStatistics.E.stop();

View File

@@ -4,9 +4,12 @@ import me.cortex.voxy.common.util.TrackedObject;
import java.util.Arrays; import java.util.Arrays;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import static org.lwjgl.opengl.GL45C.*; import static org.lwjgl.opengl.GL45C.*;
public class GlVertexArray extends TrackedObject { public class GlVertexArray extends TrackedObject {
public static final int STATIC_VAO = glGenVertexArrays();
public final int id; public final int id;
private int[] indices = new int[0]; private int[] indices = new int[0];
private int stride; private int stride;

View File

@@ -4,15 +4,19 @@ package me.cortex.voxy.client.core.model;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import me.cortex.voxy.common.world.other.Mapper; import me.cortex.voxy.common.world.other.Mapper;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.StampedLock; import java.util.concurrent.locks.StampedLock;
import static org.lwjgl.opengl.ARBDirectStateAccess.glTextureParameterf;
import static org.lwjgl.opengl.GL11.glGetInteger; import static org.lwjgl.opengl.GL11.glGetInteger;
import static org.lwjgl.opengl.GL12.GL_TEXTURE_MAX_LOD;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_BINDING; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_BINDING;
import static org.lwjgl.opengl.GL30C.glBindFramebuffer; import static org.lwjgl.opengl.GL30C.glBindFramebuffer;
@@ -101,15 +105,15 @@ public class ModelBakerySubsystem {
} }
//This is on this side only and done like this as only worker threads call this code //This is on this side only and done like this as only worker threads call this code
private final StampedLock seenIdsLock = new StampedLock(); private final ReentrantLock seenIdsLock = new ReentrantLock();
private final IntOpenHashSet seenIds = new IntOpenHashSet(6000); private final IntOpenHashSet seenIds = new IntOpenHashSet(6000);
public void requestBlockBake(int blockId) { public void requestBlockBake(int blockId) {
long stamp = this.seenIdsLock.writeLock(); this.seenIdsLock.lock();
if (!this.seenIds.add(blockId)) { if (!this.seenIds.add(blockId)) {
this.seenIdsLock.unlockWrite(stamp); this.seenIdsLock.unlock();
return; return;
} }
this.seenIdsLock.unlockWrite(stamp); this.seenIdsLock.unlock();
this.blockIdQueue.add(blockId); this.blockIdQueue.add(blockId);
this.blockIdCount.incrementAndGet(); this.blockIdCount.incrementAndGet();
} }

View File

@@ -2,7 +2,11 @@ package me.cortex.voxy.client.core.model;
import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.GlTexture;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.util.Identifier;
import static org.lwjgl.opengl.ARBDirectStateAccess.glTextureParameterf;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL11C.GL_NEAREST; import static org.lwjgl.opengl.GL11C.GL_NEAREST;
import static org.lwjgl.opengl.GL11C.GL_NEAREST_MIPMAP_LINEAR; import static org.lwjgl.opengl.GL11C.GL_NEAREST_MIPMAP_LINEAR;
@@ -27,11 +31,15 @@ public class ModelStore {
this.textures = new GlTexture().store(GL_RGBA8, Integer.numberOfTrailingZeros(ModelFactory.MODEL_TEXTURE_SIZE), ModelFactory.MODEL_TEXTURE_SIZE*3*256,ModelFactory.MODEL_TEXTURE_SIZE*2*256).name("ModelTextures"); this.textures = new GlTexture().store(GL_RGBA8, Integer.numberOfTrailingZeros(ModelFactory.MODEL_TEXTURE_SIZE), ModelFactory.MODEL_TEXTURE_SIZE*3*256,ModelFactory.MODEL_TEXTURE_SIZE*2*256).name("ModelTextures");
//Limit the mips of the texture to match that of the terrain atlas
int mipLvl = ((SpriteAtlasTexture) MinecraftClient.getInstance().getTextureManager()
.getTexture(Identifier.of("minecraft", "textures/atlas/blocks.png")))
.mipLevel;
glSamplerParameteri(this.blockSampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); glSamplerParameteri(this.blockSampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glSamplerParameteri(this.blockSampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glSamplerParameteri(this.blockSampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(this.blockSampler, GL_TEXTURE_MIN_LOD, 0); glSamplerParameteri(this.blockSampler, GL_TEXTURE_MIN_LOD, 0);
glSamplerParameteri(this.blockSampler, GL_TEXTURE_MAX_LOD, Integer.numberOfTrailingZeros(ModelFactory.MODEL_TEXTURE_SIZE)); glSamplerParameteri(this.blockSampler, GL_TEXTURE_MAX_LOD, mipLvl);//Integer.numberOfTrailingZeros(ModelFactory.MODEL_TEXTURE_SIZE)
} }

View File

@@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.GlFramebuffer; import me.cortex.voxy.client.core.gl.GlFramebuffer;
import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.GlTexture;
import me.cortex.voxy.client.core.gl.GlVertexArray;
import me.cortex.voxy.client.core.gl.shader.AutoBindingShader; import me.cortex.voxy.client.core.gl.shader.AutoBindingShader;
import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.gl.shader.ShaderType;
@@ -113,7 +114,7 @@ public class ChunkBoundRenderer {
glDepthFunc(GL_GREATER); glDepthFunc(GL_GREATER);
} }
glBindVertexArray(RenderService.STATIC_VAO); glBindVertexArray(GlVertexArray.STATIC_VAO);
viewport.depthBoundingBuffer.bind(); viewport.depthBoundingBuffer.bind();
this.rasterShader.bind(); this.rasterShader.bind();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE_BB_BYTE.id()); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE_BB_BYTE.id());

View File

@@ -1,229 +0,0 @@
package me.cortex.voxy.client.core.rendering;
import me.cortex.voxy.client.RenderStatistics;
import me.cortex.voxy.client.TimingStatistics;
import me.cortex.voxy.client.VoxyClient;
import me.cortex.voxy.client.core.gl.Capabilities;
import me.cortex.voxy.client.core.gl.GlTexture;
import me.cortex.voxy.client.core.model.ModelBakerySubsystem;
import me.cortex.voxy.client.core.rendering.building.RenderGenerationService;
import me.cortex.voxy.client.core.rendering.hierachical.AsyncNodeManager;
import me.cortex.voxy.client.core.rendering.hierachical.HierarchicalOcclusionTraverser;
import me.cortex.voxy.client.core.rendering.hierachical.NodeCleaner;
import me.cortex.voxy.client.core.rendering.section.AbstractSectionRenderer;
import me.cortex.voxy.client.core.rendering.section.IUsesMeshlets;
import me.cortex.voxy.client.core.rendering.section.MDICSectionRenderer;
import me.cortex.voxy.client.core.rendering.section.geometry.BasicSectionGeometryData;
import me.cortex.voxy.client.core.rendering.section.geometry.IGeometryData;
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.rendering.util.UploadStream;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.thread.ServiceThreadPool;
import me.cortex.voxy.common.world.WorldEngine;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static org.lwjgl.opengl.GL42.*;
public class RenderService<T extends AbstractSectionRenderer<J, Q>, J extends Viewport<J>, Q extends IGeometryData> {
public static final int STATIC_VAO = glGenVertexArrays();
private final ViewportSelector<?> viewportSelector;
private final Q geometryData;
private final AbstractSectionRenderer<J, Q> sectionRenderer;
private final AsyncNodeManager nodeManager;
private final NodeCleaner nodeCleaner;
private final HierarchicalOcclusionTraverser traversal;
private final ModelBakerySubsystem modelService;
private final RenderGenerationService renderGen;
private final WorldEngine world;
@SuppressWarnings("unchecked")
public RenderService(WorldEngine world, ServiceThreadPool serviceThreadPool) {
this.world = world;
this.modelService = new ModelBakerySubsystem(world.getMapper());
long geometryCapacity = 0;
this.geometryData = (Q) new BasicSectionGeometryData(1<<20, geometryCapacity);
//Max sections: ~500k
this.sectionRenderer = (T) new MDICSectionRenderer(null, this.modelService.getStore(), (BasicSectionGeometryData) this.geometryData);
//Logger.info("Using renderer: " + this.sectionRenderer.getClass().getSimpleName() + " with geometry buffer of: " + geometryCapacity + " bytes");
//Do something incredibly hacky, we dont need to keep the reference to this around, so just connect and discard
this.viewportSelector = new ViewportSelector<>(this.sectionRenderer::createViewport);
this.renderGen = new RenderGenerationService(world, this.modelService, serviceThreadPool,
this.sectionRenderer.getGeometryManager() instanceof IUsesMeshlets,
()->true);
this.nodeManager = new AsyncNodeManager(1<<21, this.geometryData, this.renderGen);
this.nodeCleaner = new NodeCleaner(this.nodeManager);
this.traversal = new HierarchicalOcclusionTraverser(this.nodeManager, this.nodeCleaner, this.renderGen);
world.setDirtyCallback(this.nodeManager::worldEvent);
Arrays.stream(world.getMapper().getBiomeEntries()).forEach(this.modelService::addBiome);
world.getMapper().setBiomeCallback(this.modelService::addBiome);
this.nodeManager.start();
}
public void addTopLevelNode(long pos) {
this.nodeManager.addTopLevel(pos);
}
public void removeTopLevelNode(long pos) {
this.nodeManager.removeTopLevel(pos);
}
public void tickModelService(long budget) {
this.modelService.tick(budget);
}
private boolean frexStillHasWork() {
if (!VoxyClient.isFrexActive()) {
return false;
}
//If frex is running we must tick everything to ensure correctness
UploadStream.INSTANCE.tick();
//Done here as is allows less gl state resetup
this.modelService.tick(100_000_000);
glFinish();
return this.nodeManager.hasWork() || this.renderGen.getTaskCount()!=0 || !this.modelService.areQueuesEmpty();
}
public void renderFarAwayOpaque(J viewport, GlTexture depthBoundTexture) {
//LightMapHelper.tickLightmap();
//Render previous geometry with the abstract renderer
//Execute the hieracial selector
// render delta sections
//Hieracial is not an abstract thing but
// the section renderer is as it might have different backends, but they all accept a buffer containing the section list
TimingStatistics.G.start();
this.sectionRenderer.renderOpaque(viewport);
TimingStatistics.G.stop();
{
int depthBuffer = glGetFramebufferAttachmentParameteri(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
//Compute the mip chain
viewport.hiZBuffer.buildMipChain(depthBuffer, viewport.width, viewport.height);
}
do {
//NOTE: need to do the upload and download tick here, after the section renderer renders the world, to ensure "stable"
// sections
{
TimingStatistics.main.stop();
TimingStatistics.dynamic.start();
/*
this.sectionUpdateQueue.consume(128);
//if (this.modelService.getProcessingCount() < 750)
{//Very bad hack to try control things
this.geometryUpdateQueue.consumeNano(Math.max(3_000_000 - (System.nanoTime() - frameStart), 50_000));
}
if (this.nodeManager.writeChanges(this.traversal.getNodeBuffer())) {//TODO: maybe move the node buffer out of the traversal class
UploadStream.INSTANCE.commit();
}*/
TimingStatistics.D.start();
//Tick download stream
DownloadStream.INSTANCE.tick();
TimingStatistics.D.stop();
this.nodeManager.tick(this.traversal.getNodeBuffer(), this.nodeCleaner);
//glFlush();
this.nodeCleaner.tick(this.traversal.getNodeBuffer());//Probably do this here??
TimingStatistics.dynamic.stop();
TimingStatistics.main.start();
}
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_PIXEL_BUFFER_BARRIER_BIT);
TimingStatistics.I.start();
this.traversal.doTraversal(viewport);
TimingStatistics.I.stop();
} while (this.frexStillHasWork());
TimingStatistics.H.start();
this.sectionRenderer.buildDrawCalls(viewport);
TimingStatistics.H.stop();
TimingStatistics.G.start();
this.sectionRenderer.renderTemporal(viewport);
TimingStatistics.G.stop();
}
public void renderFarAwayTranslucent(J viewport) {
this.sectionRenderer.renderTranslucent(viewport);
}
public void addDebugData(List<String> debug) {
this.modelService.addDebugData(debug);
this.renderGen.addDebugData(debug);
this.sectionRenderer.addDebug(debug);
this.nodeManager.addDebug(debug);
if (RenderStatistics.enabled) {
debug.add("HTC: [" + Arrays.stream(flipCopy(RenderStatistics.hierarchicalTraversalCounts)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
debug.add("HRS: [" + Arrays.stream(flipCopy(RenderStatistics.hierarchicalRenderSections)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
debug.add("VS: [" + Arrays.stream(flipCopy(RenderStatistics.visibleSections)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
debug.add("QC: [" + Arrays.stream(flipCopy(RenderStatistics.quadCount)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
}
}
private static int[] flipCopy(int[] array) {
int[] ret = new int[array.length];
int i = ret.length;
for (int j : array) {
ret[--i] = j;
}
return ret;
}
public void shutdown() {
//Cleanup callbacks
this.world.setDirtyCallback(null);
this.world.getMapper().setBiomeCallback(null);
this.world.getMapper().setStateCallback(null);
this.nodeManager.stop();
this.modelService.shutdown();
this.renderGen.shutdown();
this.viewportSelector.free();
this.sectionRenderer.free();
this.traversal.free();
this.nodeCleaner.free();
this.geometryData.free();
}
public Viewport<?> getViewport() {
return this.viewportSelector.getViewport();
}
public int getMeshQueueCount() {
return this.renderGen.getTaskCount();
}
}

View File

@@ -1,9 +1,9 @@
package me.cortex.voxy.client.core.rendering.hierachical; package me.cortex.voxy.client.core.rendering.hierachical;
import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.GlVertexArray;
import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.gl.shader.ShaderType;
import me.cortex.voxy.client.core.rendering.RenderService;
import me.cortex.voxy.client.core.rendering.Viewport; import me.cortex.voxy.client.core.rendering.Viewport;
import me.cortex.voxy.client.core.rendering.util.SharedIndexBuffer; import me.cortex.voxy.client.core.rendering.util.SharedIndexBuffer;
import me.cortex.voxy.client.core.rendering.util.UploadStream; import me.cortex.voxy.client.core.rendering.util.UploadStream;
@@ -67,7 +67,7 @@ public class DebugRenderer {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
this.debugShader.bind(); this.debugShader.bind();
glBindVertexArray(RenderService.STATIC_VAO); glBindVertexArray(GlVertexArray.STATIC_VAO);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, this.drawBuffer.id); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, this.drawBuffer.id);
GL15.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE_BYTE.id()); GL15.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE_BYTE.id());
glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id); glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id);

View File

@@ -326,7 +326,7 @@ public class HierarchicalOcclusionTraverser {
private void forwardDownloadResult(long ptr, long size) { private void forwardDownloadResult(long ptr, long size) {
int count = MemoryUtil.memGetInt(ptr);ptr += 8;//its 8 since we need to skip the second value (which is empty) int count = MemoryUtil.memGetInt(ptr);ptr += 8;//its 8 since we need to skip the second value (which is empty)
if (count < 0 || count > 50000) { if (count < 0 || count > 50000) {
Logger.error(new IllegalStateException("Count unexpected extreme value: " + count)); Logger.error(new IllegalStateException("Count unexpected extreme value: " + count + " things may get weird"));
return; return;
} }
if (count > (this.requestBuffer.size()>>3)-1) { if (count > (this.requestBuffer.size()>>3)-1) {

View File

@@ -5,12 +5,11 @@ import me.cortex.voxy.client.RenderStatistics;
import me.cortex.voxy.client.core.AbstractRenderPipeline; import me.cortex.voxy.client.core.AbstractRenderPipeline;
import me.cortex.voxy.client.core.gl.Capabilities; import me.cortex.voxy.client.core.gl.Capabilities;
import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.GlVertexArray;
import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderLoader; import me.cortex.voxy.client.core.gl.shader.ShaderLoader;
import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.gl.shader.ShaderType;
import me.cortex.voxy.client.core.model.ModelStore; import me.cortex.voxy.client.core.model.ModelStore;
import me.cortex.voxy.client.core.rendering.RenderService;
import me.cortex.voxy.client.core.rendering.section.geometry.BasicSectionGeometryData; import me.cortex.voxy.client.core.rendering.section.geometry.BasicSectionGeometryData;
import me.cortex.voxy.client.core.rendering.util.DownloadStream; import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.rendering.util.LightMapHelper; import me.cortex.voxy.client.core.rendering.util.LightMapHelper;
@@ -171,7 +170,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
this.terrainShader.bind(); this.terrainShader.bind();
glBindVertexArray(RenderService.STATIC_VAO);//Needs to be before binding glBindVertexArray(GlVertexArray.STATIC_VAO);//Needs to be before binding
this.pipeline.setupAndBindOpaque(viewport); this.pipeline.setupAndBindOpaque(viewport);
this.bindRenderingBuffers(viewport); this.bindRenderingBuffers(viewport);
@@ -208,7 +207,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
this.translucentTerrainShader.bind(); this.translucentTerrainShader.bind();
glBindVertexArray(RenderService.STATIC_VAO);//Needs to be before binding glBindVertexArray(GlVertexArray.STATIC_VAO);//Needs to be before binding
this.pipeline.setupAndBindTranslucent(viewport); this.pipeline.setupAndBindTranslucent(viewport);
this.bindRenderingBuffers(viewport); this.bindRenderingBuffers(viewport);
@@ -249,7 +248,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
if (Capabilities.INSTANCE.repFragTest) { if (Capabilities.INSTANCE.repFragTest) {
glEnable(GL_REPRESENTATIVE_FRAGMENT_TEST_NV); glEnable(GL_REPRESENTATIVE_FRAGMENT_TEST_NV);
} }
glBindVertexArray(RenderService.STATIC_VAO); glBindVertexArray(GlVertexArray.STATIC_VAO);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniform.id); glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniform.id);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.geometryManager.getMetadataBuffer().id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.geometryManager.getMetadataBuffer().id);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, viewport.visibilityBuffer.id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, viewport.visibilityBuffer.id);

View File

@@ -2,9 +2,9 @@ package me.cortex.voxy.client.core.rendering.util;
import me.cortex.voxy.client.core.gl.GlFramebuffer; import me.cortex.voxy.client.core.gl.GlFramebuffer;
import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.GlTexture;
import me.cortex.voxy.client.core.gl.GlVertexArray;
import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.gl.shader.ShaderType;
import me.cortex.voxy.client.core.rendering.RenderService;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import static org.lwjgl.opengl.ARBDirectStateAccess.*; import static org.lwjgl.opengl.ARBDirectStateAccess.*;
@@ -75,7 +75,7 @@ public class HiZBuffer {
} }
this.alloc(Integer.highestOneBit(width), Integer.highestOneBit(height)); this.alloc(Integer.highestOneBit(width), Integer.highestOneBit(height));
} }
glBindVertexArray(RenderService.STATIC_VAO); glBindVertexArray(GlVertexArray.STATIC_VAO);
int boundFB = GL11.glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING); int boundFB = GL11.glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING);
this.hiz.bind(); this.hiz.bind();
glBindFramebuffer(GL_FRAMEBUFFER, this.fb.id); glBindFramebuffer(GL_FRAMEBUFFER, this.fb.id);

View File

@@ -2,9 +2,9 @@ package me.cortex.voxy.client.core.rendering.util;
import me.cortex.voxy.client.core.gl.GlFramebuffer; import me.cortex.voxy.client.core.gl.GlFramebuffer;
import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.GlTexture;
import me.cortex.voxy.client.core.gl.GlVertexArray;
import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.gl.shader.ShaderType;
import me.cortex.voxy.client.core.rendering.RenderService;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import static org.lwjgl.opengl.ARBDirectStateAccess.*; import static org.lwjgl.opengl.ARBDirectStateAccess.*;
@@ -83,7 +83,7 @@ public class HiZBuffer2 {
{//Mip down to initial chain {//Mip down to initial chain
int boundFB = GL11.glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING); int boundFB = GL11.glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING);
glBindVertexArray(RenderService.STATIC_VAO); glBindVertexArray(GlVertexArray.STATIC_VAO);
this.hizInitial.bind(); this.hizInitial.bind();
glBindFramebuffer(GL_FRAMEBUFFER, this.fb.id); glBindFramebuffer(GL_FRAMEBUFFER, this.fb.id);

View File

@@ -254,6 +254,7 @@ public class Mapper {
//TODO: fixme: synchronize access to this.blockId2stateEntry //TODO: fixme: synchronize access to this.blockId2stateEntry
public StateEntry[] getStateEntries() { public StateEntry[] getStateEntries() {
this.blockLock.lock();
var set = new ArrayList<>(this.blockId2stateEntry); var set = new ArrayList<>(this.blockId2stateEntry);
StateEntry[] out = new StateEntry[set.size()]; StateEntry[] out = new StateEntry[set.size()];
int i = 0; int i = 0;
@@ -263,11 +264,13 @@ public class Mapper {
} }
out[i-1] = entry; out[i-1] = entry;
} }
this.blockLock.unlock();
return out; return out;
} }
//TODO: fixme: synchronize access to this.biomeId2biomeEntry //TODO: fixme: synchronize access to this.biomeId2biomeEntry
public BiomeEntry[] getBiomeEntries() { public BiomeEntry[] getBiomeEntries() {
this.biomeLock.lock();
var set = new ArrayList<>(this.biomeId2biomeEntry); var set = new ArrayList<>(this.biomeId2biomeEntry);
BiomeEntry[] out = new BiomeEntry[set.size()]; BiomeEntry[] out = new BiomeEntry[set.size()];
int i = 0; int i = 0;
@@ -277,6 +280,7 @@ public class Mapper {
} }
out[i-1] = entry; out[i-1] = entry;
} }
this.biomeLock.unlock();
return out; return out;
} }

View File

@@ -9,6 +9,8 @@ import net.minecraft.world.dimension.DimensionType;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class WorldIdentifier { public class WorldIdentifier {
private static final RegistryKey<DimensionType> NULL_DIM_KEY = RegistryKey.of(RegistryKeys.DIMENSION_TYPE, Identifier.of("voxy:null_dimension_id")); private static final RegistryKey<DimensionType> NULL_DIM_KEY = RegistryKey.of(RegistryKeys.DIMENSION_TYPE, Identifier.of("voxy:null_dimension_id"));
@@ -116,4 +118,31 @@ public class WorldIdentifier {
int b = B==null?0:B.hashCode(); int b = B==null?0:B.hashCode();
return (Integer.toUnsignedLong(a)<<32)|Integer.toUnsignedLong(b); return (Integer.toUnsignedLong(a)<<32)|Integer.toUnsignedLong(b);
} }
private static String bytesToHex(byte[] hash) {
StringBuilder hexString = new StringBuilder(2 * hash.length);
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
public String getWorldId() {
return getWorldId(this);
}
public static String getWorldId(WorldIdentifier identifier) {
String data = identifier.biomeSeed + identifier.key.toString();
try {
return bytesToHex(MessageDigest.getInstance("SHA-256").digest(data.getBytes())).substring(0, 32);
} catch (
NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
} }

View File

@@ -93,7 +93,7 @@ void voxy_emitFragment(VoxyFragmentParameters parameters);
vec4 computeColour(vec2 texturePos, vec4 colour) { vec4 computeColour(vec2 texturePos, vec4 colour) {
//Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha //Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha
if (useTinting()) { if (useTinting()) {
vec4 tintTest = texture(blockModelAtlas, texturePos, -2); vec4 tintTest = textureLod(blockModelAtlas, texturePos, 0);
if (abs(tintTest.r-tintTest.g) < 0.02f && abs(tintTest.g-tintTest.b) < 0.02f) { if (abs(tintTest.r-tintTest.g) < 0.02f && abs(tintTest.g-tintTest.b) < 0.02f) {
colour *= uint2vec4RGBA(interData.z).yzwx; colour *= uint2vec4RGBA(interData.z).yzwx;
} }

View File

@@ -32,3 +32,5 @@ accessible class net/minecraft/client/gl/GlDebug$DebugMessage
accessible class net/minecraft/client/world/ClientChunkManager$ClientChunkMap accessible class net/minecraft/client/world/ClientChunkManager$ClientChunkMap
accessible method net/minecraft/client/world/ClientChunkManager$ClientChunkMap getChunk (I)Lnet/minecraft/world/chunk/WorldChunk; accessible method net/minecraft/client/world/ClientChunkManager$ClientChunkMap getChunk (I)Lnet/minecraft/world/chunk/WorldChunk;
accessible method net/minecraft/client/world/ClientChunkManager$ClientChunkMap getIndex (II)I accessible method net/minecraft/client/world/ClientChunkManager$ClientChunkMap getIndex (II)I
accessible field net/minecraft/client/texture/SpriteAtlasTexture mipLevel I