Finished GeometryManager and added AABB raster support

This commit is contained in:
mcrcortex
2024-01-29 12:35:09 +10:00
parent d499a19d4e
commit 787dc88c43
11 changed files with 69 additions and 77 deletions

View File

@@ -361,6 +361,6 @@ public class ModelManager {
}
public void addDebugInfo(List<String> info) {
info.add("BlockModels registered: " + this.modelTexture2id.size() + "/" + (1<<16));
}
}

View File

@@ -6,7 +6,6 @@ package me.cortex.zenith.client.core.rendering;
import me.cortex.zenith.client.core.gl.GlBuffer;
import me.cortex.zenith.client.core.model.ModelManager;
import me.cortex.zenith.client.core.rendering.building.BuiltSection;
import me.cortex.zenith.client.core.rendering.building.BuiltSectionGeometry;
import me.cortex.zenith.client.core.rendering.util.UploadStream;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;

View File

@@ -5,7 +5,6 @@ import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import me.cortex.zenith.client.core.gl.GlBuffer;
import me.cortex.zenith.client.core.rendering.building.BuiltSection;
import me.cortex.zenith.client.core.rendering.building.BuiltSectionGeometry;
import me.cortex.zenith.client.core.rendering.util.BufferArena;
import me.cortex.zenith.client.core.rendering.util.UploadStream;
import org.lwjgl.system.MemoryUtil;
@@ -33,7 +32,7 @@ public class GeometryManager {
void uploadResults() {
while (!this.buildResults.isEmpty()) {
var result = this.buildResults.pop();
boolean isDelete = result.opaque == null && result.translucent == null;
boolean isDelete = result.geometryBuffer == null;
if (isDelete) {
int id = -1;
if ((id = this.pos2id.remove(result.position)) != -1) {
@@ -142,36 +141,29 @@ public class GeometryManager {
//TODO: pack the offsets of each axis so that implicit face culling can work
//Note! the opaquePreDataCount and translucentPreDataCount are never writen to the meta buffer, as they are indexed in reverse relative to the base opaque and translucent geometry
private record SectionMeta(long position, int aabb, int opaqueGeometryPtr, int count, int translucentGeometryPtr) {
private record SectionMeta(long position, int aabb, int geometryPtr, int size, int[] offsets) {
public void writeMetadata(long ptr) {
//THIS IS DUE TO ENDIANNESS and that we are splitting a long into 2 ints
MemoryUtil.memPutInt(ptr, (int) (this.position>>32)); ptr += 4;
MemoryUtil.memPutInt(ptr, (int) this.position); ptr += 4;
MemoryUtil.memPutInt(ptr, (int) this.aabb); ptr += 4;
ptr += 4;
MemoryUtil.memPutInt(ptr, this.geometryPtr + this.offsets[0]); ptr += 4;
MemoryUtil.memPutInt(ptr, this.opaqueGeometryPtr); ptr += 4;
MemoryUtil.memPutInt(ptr, this.count); ptr += 4;
//MemoryUtil.memPutInt(ptr, (int) this.translucentGeometryPtr + this.translucentPreDataCount); ptr += 4;
//MemoryUtil.memPutInt(ptr, this.translucentQuadCount); ptr += 4;
MemoryUtil.memPutInt(ptr, (this.offsets[1]-this.offsets[0])|((this.offsets[2]-this.offsets[1])<<16)); ptr += 4;
MemoryUtil.memPutInt(ptr, (this.offsets[3]-this.offsets[2])|((this.offsets[4]-this.offsets[3])<<16)); ptr += 4;
MemoryUtil.memPutInt(ptr, (this.offsets[5]-this.offsets[4])|((this.offsets[6]-this.offsets[5])<<16)); ptr += 4;
MemoryUtil.memPutInt(ptr, (this.offsets[7]-this.offsets[6])|((this.size -this.offsets[7])<<16)); ptr += 4;
}
}
private SectionMeta createMeta(BuiltSection geometry) {
int geometryPtr = (int) this.geometryBuffer.upload(geometry.opaque.buffer());
//TODO: support translucent geometry
//return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), 0, -1,0, 0);
return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), -1);
int geometryPtr = (int) this.geometryBuffer.upload(geometry.geometryBuffer);
return new SectionMeta(geometry.position, geometry.aabb, geometryPtr, (int) (geometry.geometryBuffer.size/8), geometry.offsets);
}
private void freeMeta(SectionMeta meta) {
if (meta.opaqueGeometryPtr != -1) {
this.geometryBuffer.free(meta.opaqueGeometryPtr);
}
if (meta.translucentGeometryPtr != -1) {
this.geometryBuffer.free(meta.translucentGeometryPtr);
if (meta.geometryPtr != -1) {
this.geometryBuffer.free(meta.geometryPtr);
}
}

View File

@@ -1,7 +1,6 @@
package me.cortex.zenith.client.core.rendering;
import me.cortex.zenith.client.core.rendering.building.BuiltSection;
import me.cortex.zenith.client.core.rendering.building.BuiltSectionGeometry;
import me.cortex.zenith.client.core.rendering.building.RenderGenerationService;
import me.cortex.zenith.common.world.WorldEngine;
import me.cortex.zenith.common.world.WorldSection;
@@ -42,7 +41,7 @@ public class RenderTracker {
//Removes a lvl 0 section from the world renderer
public void remLvl0(int x, int y, int z) {
this.activeSections.remove(WorldEngine.getWorldSectionId(0, x, y, z));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(0, x, y, z), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(0, x, y, z)));
this.renderGen.removeTask(0, x, y, z);
}
@@ -64,14 +63,14 @@ public class RenderTracker {
this.renderGen.enqueueTask(lvl, x, y, z, this::shouldStillBuild, this::getBuildFlagsOrAbort);
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1), (z<<1)), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1), (z<<1)+1), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1)+1, (z<<1)), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1)+1, (z<<1)+1), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1), (z<<1)), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1), (z<<1)+1), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1)+1, (z<<1)), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1)+1, (z<<1)+1), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1), (z<<1))));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1), (z<<1)+1)));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1)+1, (z<<1))));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1), (y<<1)+1, (z<<1)+1)));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1), (z<<1))));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1), (z<<1)+1)));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1)+1, (z<<1))));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1)+1, (z<<1)+1)));
this.renderGen.removeTask(lvl-1, (x<<1), (y<<1), (z<<1));
@@ -96,7 +95,7 @@ public class RenderTracker {
this.activeSections.put(WorldEngine.getWorldSectionId(lvl-1, (x<<1)+1, (y<<1)+1, (z<<1)+1), O);
this.activeSections.remove(WorldEngine.getWorldSectionId(lvl, x, y, z));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl, x, y, z), null, null));
this.renderer.enqueueResult(new BuiltSection(WorldEngine.getWorldSectionId(lvl, x, y, z)));
this.renderGen.removeTask(lvl, x, y, z);
this.renderGen.enqueueTask(lvl - 1, (x<<1), (y<<1), (z<<1), this::shouldStillBuild, this::getBuildFlagsOrAbort);

View File

@@ -1,29 +1,43 @@
package me.cortex.zenith.client.core.rendering.building;
import me.cortex.zenith.common.util.MemoryBuffer;
import java.util.Arrays;
import java.util.Objects;
//TODO: also have an AABB size stored
public final class BuiltSection {
public final long position;
public final BuiltSectionGeometry opaque;
public final BuiltSectionGeometry translucent;
public final int aabb;
public final MemoryBuffer geometryBuffer;
public final int[] offsets;
public BuiltSection(long position, BuiltSectionGeometry opaque, BuiltSectionGeometry translucent) {
public BuiltSection(long position) {
this(position, -1, null, null);
}
public BuiltSection(long position, int aabb, MemoryBuffer geometryBuffer, int[] offsets) {
this.position = position;
this.opaque = opaque;
this.translucent = translucent;
this.aabb = aabb;
this.geometryBuffer = geometryBuffer;
this.offsets = offsets;
if (offsets != null) {
for (int i = 0; i < offsets.length-1; i++) {
int delta = offsets[i+1] - offsets[i];
if (delta<0||delta>=(1<<16)) {
throw new IllegalArgumentException("Offsets out of range");
}
}
}
}
public BuiltSection clone() {
return new BuiltSection(this.position, this.opaque != null ? this.opaque.clone() : null, this.translucent != null ? this.translucent.clone() : null);
return new BuiltSection(this.position, this.aabb, this.geometryBuffer!=null?this.geometryBuffer.copy():null, this.offsets!=null?Arrays.copyOf(this.offsets, this.offsets.length):null);
}
public void free() {
if (this.opaque != null) {
this.opaque.free();
}
if (this.translucent != null) {
this.translucent.free();
if (this.geometryBuffer != null) {
this.geometryBuffer.free();
}
}
}

View File

@@ -1,21 +0,0 @@
package me.cortex.zenith.client.core.rendering.building;
import me.cortex.zenith.common.util.MemoryBuffer;
import java.util.Arrays;
/**
* @param startOffsets Will be converted to ending offsets when doing data computation
*/
public record BuiltSectionGeometry(MemoryBuffer buffer, short[] startOffsets) {
public BuiltSectionGeometry clone() {
return new BuiltSectionGeometry(this.buffer != null ? this.buffer.copy() : null, Arrays.copyOf(this.startOffsets, this.startOffsets.length));
}
public void free() {
if (this.buffer != null) {
this.buffer.free();
}
}
}

View File

@@ -297,7 +297,7 @@ public class RenderDataFactory {
//MemoryUtil.memPutLong(buff.address+48, encodeRaw(2, 0,1,0,0,2,159,0, 0));//92 515
//MemoryUtil.memPutLong(buff.address+56, encodeRaw(3, 0,1,0,0,2,159,0, 0));//92 515
if (outData.isEmpty()) {
return new BuiltSection(section.getKey(), null, null);
return new BuiltSection(section.getKey());
}
//outData.clear();
@@ -317,7 +317,7 @@ public class RenderDataFactory {
MemoryUtil.memPutLong(ptr, data); ptr+=8;
}
return new BuiltSection(section.getKey(), new BuiltSectionGeometry(buff, new short[0]), null);
return new BuiltSection(section.getKey(), (31<<15)|(31<<20)|(31<<25), buff, new int[]{0, outData.size(), outData.size(), outData.size(), outData.size(), outData.size(), outData.size(), outData.size()});
}

View File

@@ -21,11 +21,11 @@ struct SectionMeta {
uint posA;
uint posB;
uint AABB;
uint _padA;
uint ptr;
uint cnt;
uint _padB;
uint _padC;
uint cntA;
uint cntB;
uint cntC;
uint cntD;
};
//TODO: see if making the stride 2*4*4 bytes or something cause you get that 16 byte write

View File

@@ -55,11 +55,13 @@ void main() {
}
if (shouldRender) {
uint basePtr = extractQuadStart(meta);
DrawCommand cmd;
cmd.count = extractQuadCount(meta) * 6;
cmd.count = (meta.cntA&0xFFFF) * 6;
cmd.instanceCount = 1;
cmd.firstIndex = 0;
cmd.baseVertex = int(extractQuadStart(meta))<<2;
cmd.baseVertex = int(basePtr)<<2;
cmd.baseInstance = encodeLocalLodPos(detail, ipos);
cmdBuffer[atomicAdd(opaqueDrawCount, 1)] = cmd;
}

View File

@@ -14,12 +14,15 @@ void main() {
uint detail = extractDetail(section);
ivec3 ipos = extractPosition(section);
ivec3 aabbOffset = extractAABBOffset(section);
ivec3 size = extractAABBSize(section);
//Transform ipos with respect to the vertex corner
ipos += ivec3(gl_VertexID&1, (gl_VertexID>>2)&1, (gl_VertexID>>1)&1);
ivec3 pos = (((ipos<<detail)-baseSectionPos)<<5);
pos += aabbOffset;
pos += (ivec3(gl_VertexID&1, (gl_VertexID>>2)&1, (gl_VertexID>>1)&1)*size)*(1<<detail);
vec3 cornerPos = vec3(((ipos<<detail)-baseSectionPos)<<5);
gl_Position = MVP * vec4(cornerPos,1);
gl_Position = MVP * vec4(vec3(pos),1);
//Write to this id
id = sid;

View File

@@ -16,6 +16,10 @@ uint extractQuadStart(SectionMeta meta) {
return meta.ptr;
}
uint extractQuadCount(SectionMeta meta) {
return meta.cnt;
ivec3 extractAABBOffset(SectionMeta meta) {
return (ivec3(meta.AABB)>>ivec3(0,5,10))&31;
}
ivec3 extractAABBSize(SectionMeta meta) {
return ((ivec3(meta.AABB)>>ivec3(15,20,25))&31)+1;//The size is + 1 cause its always at least 1x1x1
}