Wip fix overdraw
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
package me.cortex.voxy.client.core.rendering;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||||
|
import me.cortex.voxy.client.core.gl.GlBuffer;
|
||||||
|
import me.cortex.voxy.client.core.rendering.util.UploadStream;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
|
||||||
|
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
|
||||||
|
import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;
|
||||||
|
import static org.lwjgl.opengl.GL15.glBindBuffer;
|
||||||
|
import static org.lwjgl.opengl.GL30.glBindBufferBase;
|
||||||
|
import static org.lwjgl.opengl.GL30.glBindVertexArray;
|
||||||
|
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;
|
||||||
|
import static org.lwjgl.opengl.GL31.glDrawElementsInstanced;
|
||||||
|
import static org.lwjgl.opengl.GL40C.GL_DRAW_INDIRECT_BUFFER;
|
||||||
|
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER;
|
||||||
|
|
||||||
|
//This is a render subsystem, its very simple in what it does
|
||||||
|
// it renders an AABB around loaded chunks, thats it
|
||||||
|
public class ChunkBoundRenderer {
|
||||||
|
public static final int MAX_CHUNK_COUNT = 10_000;
|
||||||
|
private final GlBuffer chunkPosBuffer = new GlBuffer(MAX_CHUNK_COUNT*8);//Stored as ivec2
|
||||||
|
private final GlBuffer uniformBuffer = new GlBuffer(128);
|
||||||
|
private final Long2IntOpenHashMap chunk2idx = new Long2IntOpenHashMap(MAX_CHUNK_COUNT);
|
||||||
|
private final long[] idx2chunk = new long[MAX_CHUNK_COUNT];
|
||||||
|
|
||||||
|
public ChunkBoundRenderer() {
|
||||||
|
this.chunk2idx.defaultReturnValue(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChunk(long pos) {
|
||||||
|
if (this.chunk2idx.containsKey(pos)) {
|
||||||
|
throw new IllegalArgumentException("Chunk already in map");
|
||||||
|
}
|
||||||
|
int idx = this.chunk2idx.size();
|
||||||
|
this.chunk2idx.put(pos, idx);
|
||||||
|
this.idx2chunk[idx] = pos;
|
||||||
|
|
||||||
|
long ptr = UploadStream.INSTANCE.upload(this.chunkPosBuffer, 8L*idx, 8);
|
||||||
|
//Need to do it in 2 parts because ivec2 is 2 parts
|
||||||
|
MemoryUtil.memPutInt(ptr, (int)(pos&0xFFFFFFFFL)); ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, (int)((pos>>>32)&0xFFFFFFFFL));
|
||||||
|
UploadStream.INSTANCE.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeChunk(long pos) {
|
||||||
|
int idx = this.chunk2idx.remove(pos);
|
||||||
|
if (idx == -1) {
|
||||||
|
throw new IllegalArgumentException("Chunk pos not in map");
|
||||||
|
}
|
||||||
|
if (idx == this.chunk2idx.size()-1) {
|
||||||
|
//Dont need to do anything as heap is already compact
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.idx2chunk[idx] != pos) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Move last entry on heap to this index
|
||||||
|
long ePos = this.idx2chunk[this.chunk2idx.size()];// since is already removed size is correct end idx
|
||||||
|
if (this.chunk2idx.put(ePos, idx) == -1) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
this.idx2chunk[idx] = ePos;
|
||||||
|
|
||||||
|
//Put the end pos into the new idx
|
||||||
|
long ptr = UploadStream.INSTANCE.upload(this.chunkPosBuffer, 8L*idx, 8);
|
||||||
|
//Need to do it in 2 parts because ivec2 is 2 parts
|
||||||
|
MemoryUtil.memPutInt(ptr, (int)(ePos&0xFFFFFFFFL)); ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, (int)((ePos>>>32)&0xFFFFFFFFL));
|
||||||
|
UploadStream.INSTANCE.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bind and render, changing as little gl state as possible so that the caller may configure how it wants to render
|
||||||
|
public void render(Viewport<?> viewport) {
|
||||||
|
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, 128);
|
||||||
|
viewport.MVP.getToAddress(ptr); ptr += 4*4*4;
|
||||||
|
viewport.section.getToAddress(ptr); ptr += 4*4;
|
||||||
|
viewport.innerTranslation.getToAddress(ptr); ptr += 4*4;
|
||||||
|
UploadStream.INSTANCE.commit();
|
||||||
|
|
||||||
|
//TODO: NOTE: need to reverse the winding order since we want the back faces of the AABB, not the front
|
||||||
|
//this.cullShader.bind();
|
||||||
|
glBindVertexArray(RenderService.STATIC_VAO);
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.chunkPosBuffer.id);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE.id());
|
||||||
|
glDrawElementsInstanced(GL_TRIANGLES, 6*2*3, GL_UNSIGNED_BYTE, SharedIndexBuffer.CUBE_INDEX_OFFSET, this.chunk2idx.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void free() {
|
||||||
|
this.uniformBuffer.free();
|
||||||
|
this.chunkPosBuffer.free();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||||||
|
|
||||||
//Has a base index buffer of 16380 quads, and also a 1 cube byte index buffer at the end
|
//Has a base index buffer of 16380 quads, and also a 1 cube byte index buffer at the end
|
||||||
public class SharedIndexBuffer {
|
public class SharedIndexBuffer {
|
||||||
|
public static final int CUBE_INDEX_OFFSET = (1<<16)*6*2;
|
||||||
public static final SharedIndexBuffer INSTANCE = new SharedIndexBuffer();
|
public static final SharedIndexBuffer INSTANCE = new SharedIndexBuffer();
|
||||||
public static final SharedIndexBuffer INSTANCE_BYTE = new SharedIndexBuffer(true);
|
public static final SharedIndexBuffer INSTANCE_BYTE = new SharedIndexBuffer(true);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package me.cortex.voxy.client.core.rendering;
|
package me.cortex.voxy.client.core.rendering;
|
||||||
|
|
||||||
import org.joml.FrustumIntersection;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.*;
|
||||||
import org.joml.Vector4f;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
@@ -28,6 +27,10 @@ public abstract class Viewport <A extends Viewport<A>> {
|
|||||||
public double cameraY;
|
public double cameraY;
|
||||||
public double cameraZ;
|
public double cameraZ;
|
||||||
|
|
||||||
|
public final Matrix4f MVP = new Matrix4f();
|
||||||
|
public final Vector3i section = new Vector3i();
|
||||||
|
public final Vector3f innerTranslation = new Vector3f();
|
||||||
|
|
||||||
protected Viewport() {
|
protected Viewport() {
|
||||||
Vector4f[] planes = null;
|
Vector4f[] planes = null;
|
||||||
try {
|
try {
|
||||||
@@ -67,8 +70,24 @@ public abstract class Viewport <A extends Viewport<A>> {
|
|||||||
return (A) this;
|
return (A) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public A updateFrustum() {
|
public A update() {
|
||||||
this.frustum.set(new Matrix4f(this.projection).mul(this.modelView), false);
|
//MVP
|
||||||
|
this.projection.mul(this.modelView, this.MVP);
|
||||||
|
|
||||||
|
//Update the frustum
|
||||||
|
this.frustum.set(this.MVP, false);
|
||||||
|
|
||||||
|
//Translation vectors
|
||||||
|
int sx = MathHelper.floor(this.cameraX)>>5;
|
||||||
|
int sy = MathHelper.floor(this.cameraY)>>5;
|
||||||
|
int sz = MathHelper.floor(this.cameraZ)>>5;
|
||||||
|
this.section.set(sx, sy, sz);
|
||||||
|
|
||||||
|
this.innerTranslation.set(
|
||||||
|
(float) (this.cameraX-(sx<<5)),
|
||||||
|
(float) (this.cameraY-(sy<<5)),
|
||||||
|
(float) (this.cameraZ-(sz<<5)));
|
||||||
|
|
||||||
return (A) this;
|
return (A) this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,11 @@ import me.cortex.voxy.client.TimingStatistics;
|
|||||||
import me.cortex.voxy.client.config.VoxyConfig;
|
import me.cortex.voxy.client.config.VoxyConfig;
|
||||||
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.model.ColourDepthTextureData;
|
|
||||||
import me.cortex.voxy.client.core.model.ModelBakerySubsystem;
|
import me.cortex.voxy.client.core.model.ModelBakerySubsystem;
|
||||||
import me.cortex.voxy.client.core.model.bakery.ModelTextureBakery;
|
|
||||||
import me.cortex.voxy.client.core.rendering.building.RenderDataFactory45;
|
import me.cortex.voxy.client.core.rendering.building.RenderDataFactory45;
|
||||||
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.post.PostProcessing;
|
import me.cortex.voxy.client.core.rendering.post.PostProcessing;
|
||||||
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.RawDownloadStream;
|
|
||||||
import me.cortex.voxy.client.core.util.IrisUtil;
|
import me.cortex.voxy.client.core.util.IrisUtil;
|
||||||
import me.cortex.voxy.common.Logger;
|
import me.cortex.voxy.common.Logger;
|
||||||
import me.cortex.voxy.common.thread.ServiceThreadPool;
|
import me.cortex.voxy.common.thread.ServiceThreadPool;
|
||||||
@@ -22,7 +19,6 @@ import me.cortex.voxy.common.world.WorldSection;
|
|||||||
import me.cortex.voxy.common.world.other.Mapper;
|
import me.cortex.voxy.common.world.other.Mapper;
|
||||||
import me.cortex.voxy.commonImpl.VoxyCommon;
|
import me.cortex.voxy.commonImpl.VoxyCommon;
|
||||||
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses;
|
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses;
|
||||||
import net.minecraft.block.Blocks;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gl.GlBackend;
|
import net.minecraft.client.gl.GlBackend;
|
||||||
import net.minecraft.client.render.Camera;
|
import net.minecraft.client.render.Camera;
|
||||||
@@ -30,9 +26,7 @@ import net.minecraft.client.render.Frustum;
|
|||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import java.lang.invoke.VarHandle;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -180,7 +174,7 @@ public class VoxyRenderSystem {
|
|||||||
.setModelView(matrices.peek().getPositionMatrix())
|
.setModelView(matrices.peek().getPositionMatrix())
|
||||||
.setCamera(cameraX, cameraY, cameraZ)
|
.setCamera(cameraX, cameraY, cameraZ)
|
||||||
.setScreenSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight)
|
.setScreenSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight)
|
||||||
.updateFrustum();
|
.update();
|
||||||
viewport.frameId++;
|
viewport.frameId++;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -174,20 +174,14 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
|
|
||||||
private void uploadUniform(Viewport<?> viewport) {
|
private void uploadUniform(Viewport<?> viewport) {
|
||||||
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, 1024);
|
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, 1024);
|
||||||
int sx = MathHelper.floor(viewport.cameraX)>>5;
|
|
||||||
int sy = MathHelper.floor(viewport.cameraY)>>5;
|
|
||||||
int sz = MathHelper.floor(viewport.cameraZ)>>5;
|
|
||||||
|
|
||||||
new Matrix4f(viewport.projection).mul(viewport.modelView).getToAddress(ptr); ptr += 4*4*4;
|
viewport.MVP.getToAddress(ptr); ptr += 4*4*4;
|
||||||
|
|
||||||
MemoryUtil.memPutInt(ptr, sx); ptr += 4;
|
viewport.section.getToAddress(ptr); ptr += 4*3;
|
||||||
MemoryUtil.memPutInt(ptr, sy); ptr += 4;
|
|
||||||
MemoryUtil.memPutInt(ptr, sz); ptr += 4;
|
|
||||||
|
|
||||||
MemoryUtil.memPutFloat(ptr, viewport.width); ptr += 4;
|
MemoryUtil.memPutFloat(ptr, viewport.width); ptr += 4;
|
||||||
|
|
||||||
var innerTranslation = new Vector3f((float) (viewport.cameraX-(sx<<5)), (float) (viewport.cameraY-(sy<<5)), (float) (viewport.cameraZ-(sz<<5)));
|
viewport.innerTranslation.getToAddress(ptr); ptr += 4*3;
|
||||||
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
|
||||||
|
|
||||||
MemoryUtil.memPutFloat(ptr, viewport.height); ptr += 4;
|
MemoryUtil.memPutFloat(ptr, viewport.height); ptr += 4;
|
||||||
|
|
||||||
|
|||||||
@@ -84,24 +84,19 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
|
|
||||||
private void uploadUniformBuffer(MDICViewport viewport) {
|
private void uploadUniformBuffer(MDICViewport viewport) {
|
||||||
long ptr = UploadStream.INSTANCE.upload(this.uniform, 0, 1024);
|
long ptr = UploadStream.INSTANCE.upload(this.uniform, 0, 1024);
|
||||||
|
|
||||||
int sx = MathHelper.floor(viewport.cameraX)>>5;
|
|
||||||
int sy = MathHelper.floor(viewport.cameraY)>>5;
|
|
||||||
int sz = MathHelper.floor(viewport.cameraZ)>>5;
|
|
||||||
|
|
||||||
var mat = new Matrix4f(viewport.projection).mul(viewport.modelView);
|
var mat = new Matrix4f(viewport.MVP);
|
||||||
var innerTranslation = new Vector3f((float) (viewport.cameraX-(sx<<5)), (float) (viewport.cameraY-(sy<<5)), (float) (viewport.cameraZ-(sz<<5)));
|
mat.translate(-viewport.innerTranslation.x, -viewport.innerTranslation.y, -viewport.innerTranslation.z);
|
||||||
mat.translate(-innerTranslation.x, -innerTranslation.y, -innerTranslation.z);
|
|
||||||
mat.getToAddress(ptr); ptr += 4*4*4;
|
mat.getToAddress(ptr); ptr += 4*4*4;
|
||||||
MemoryUtil.memPutInt(ptr, sx); ptr += 4;
|
|
||||||
MemoryUtil.memPutInt(ptr, sy); ptr += 4;
|
viewport.section.getToAddress(ptr); ptr += 4*3;
|
||||||
MemoryUtil.memPutInt(ptr, sz); ptr += 4;
|
|
||||||
if (viewport.frameId<0) {
|
if (viewport.frameId<0) {
|
||||||
Logger.error("Frame ID negative, this will cause things to break, wrapping around");
|
Logger.error("Frame ID negative, this will cause things to break, wrapping around");
|
||||||
viewport.frameId &= 0x7fffffff;
|
viewport.frameId &= 0x7fffffff;
|
||||||
}
|
}
|
||||||
MemoryUtil.memPutInt(ptr, viewport.frameId&0x7fffffff); ptr += 4;
|
MemoryUtil.memPutInt(ptr, viewport.frameId&0x7fffffff); ptr += 4;
|
||||||
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
viewport.innerTranslation.getToAddress(ptr); ptr += 4*3;
|
||||||
|
|
||||||
UploadStream.INSTANCE.commit();
|
UploadStream.INSTANCE.commit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
public class MixinRenderSectionManager {
|
public class MixinRenderSectionManager {
|
||||||
@Shadow @Final private ClientWorld level;
|
@Shadow @Final private ClientWorld level;
|
||||||
|
|
||||||
|
@Inject(method = "onChunkAdded", at = @At("HEAD"))
|
||||||
|
private void voxy$trackChunkAdd(int x, int z, CallbackInfo ci) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "onChunkRemoved", at = @At("HEAD"))
|
||||||
|
private void voxy$trackChunkRemove(int x, int z, CallbackInfo ci) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "onChunkRemoved", at = @At("HEAD"))
|
@Inject(method = "onChunkRemoved", at = @At("HEAD"))
|
||||||
private void injectIngest(int x, int z, CallbackInfo ci) {
|
private void injectIngest(int x, int z, CallbackInfo ci) {
|
||||||
//TODO: Am not quite sure if this is right
|
//TODO: Am not quite sure if this is right
|
||||||
|
|||||||
Reference in New Issue
Block a user