Finished GeometryManager and added AABB raster support
This commit is contained in:
@@ -361,6 +361,6 @@ public class ModelManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addDebugInfo(List<String> info) {
|
public void addDebugInfo(List<String> info) {
|
||||||
|
info.add("BlockModels registered: " + this.modelTexture2id.size() + "/" + (1<<16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.gl.GlBuffer;
|
||||||
import me.cortex.zenith.client.core.model.ModelManager;
|
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.BuiltSection;
|
||||||
import me.cortex.zenith.client.core.rendering.building.BuiltSectionGeometry;
|
|
||||||
import me.cortex.zenith.client.core.rendering.util.UploadStream;
|
import me.cortex.zenith.client.core.rendering.util.UploadStream;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.render.Camera;
|
import net.minecraft.client.render.Camera;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import me.cortex.zenith.client.core.gl.GlBuffer;
|
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.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.BufferArena;
|
||||||
import me.cortex.zenith.client.core.rendering.util.UploadStream;
|
import me.cortex.zenith.client.core.rendering.util.UploadStream;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
@@ -33,7 +32,7 @@ public class GeometryManager {
|
|||||||
void uploadResults() {
|
void uploadResults() {
|
||||||
while (!this.buildResults.isEmpty()) {
|
while (!this.buildResults.isEmpty()) {
|
||||||
var result = this.buildResults.pop();
|
var result = this.buildResults.pop();
|
||||||
boolean isDelete = result.opaque == null && result.translucent == null;
|
boolean isDelete = result.geometryBuffer == null;
|
||||||
if (isDelete) {
|
if (isDelete) {
|
||||||
int id = -1;
|
int id = -1;
|
||||||
if ((id = this.pos2id.remove(result.position)) != -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
|
//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
|
//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) {
|
public void writeMetadata(long ptr) {
|
||||||
//THIS IS DUE TO ENDIANNESS and that we are splitting a long into 2 ints
|
//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>>32)); ptr += 4;
|
||||||
MemoryUtil.memPutInt(ptr, (int) this.position); ptr += 4;
|
MemoryUtil.memPutInt(ptr, (int) this.position); ptr += 4;
|
||||||
MemoryUtil.memPutInt(ptr, (int) this.aabb); 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.offsets[1]-this.offsets[0])|((this.offsets[2]-this.offsets[1])<<16)); ptr += 4;
|
||||||
MemoryUtil.memPutInt(ptr, this.count); 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, (int) this.translucentGeometryPtr + this.translucentPreDataCount); ptr += 4;
|
MemoryUtil.memPutInt(ptr, (this.offsets[7]-this.offsets[6])|((this.size -this.offsets[7])<<16)); ptr += 4;
|
||||||
//MemoryUtil.memPutInt(ptr, this.translucentQuadCount); ptr += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SectionMeta createMeta(BuiltSection geometry) {
|
private SectionMeta createMeta(BuiltSection geometry) {
|
||||||
int geometryPtr = (int) this.geometryBuffer.upload(geometry.opaque.buffer());
|
int geometryPtr = (int) this.geometryBuffer.upload(geometry.geometryBuffer);
|
||||||
|
return new SectionMeta(geometry.position, geometry.aabb, geometryPtr, (int) (geometry.geometryBuffer.size/8), geometry.offsets);
|
||||||
//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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void freeMeta(SectionMeta meta) {
|
private void freeMeta(SectionMeta meta) {
|
||||||
if (meta.opaqueGeometryPtr != -1) {
|
if (meta.geometryPtr != -1) {
|
||||||
this.geometryBuffer.free(meta.opaqueGeometryPtr);
|
this.geometryBuffer.free(meta.geometryPtr);
|
||||||
}
|
|
||||||
if (meta.translucentGeometryPtr != -1) {
|
|
||||||
this.geometryBuffer.free(meta.translucentGeometryPtr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package me.cortex.zenith.client.core.rendering;
|
package me.cortex.zenith.client.core.rendering;
|
||||||
|
|
||||||
import me.cortex.zenith.client.core.rendering.building.BuiltSection;
|
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.client.core.rendering.building.RenderGenerationService;
|
||||||
import me.cortex.zenith.common.world.WorldEngine;
|
import me.cortex.zenith.common.world.WorldEngine;
|
||||||
import me.cortex.zenith.common.world.WorldSection;
|
import me.cortex.zenith.common.world.WorldSection;
|
||||||
@@ -42,7 +41,7 @@ public class RenderTracker {
|
|||||||
//Removes a lvl 0 section from the world renderer
|
//Removes a lvl 0 section from the world renderer
|
||||||
public void remLvl0(int x, int y, int z) {
|
public void remLvl0(int x, int y, int z) {
|
||||||
this.activeSections.remove(WorldEngine.getWorldSectionId(0, x, y, 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);
|
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.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))));
|
||||||
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), (z<<1)+1)));
|
||||||
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))));
|
||||||
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), (y<<1)+1, (z<<1)+1)));
|
||||||
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))));
|
||||||
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), (z<<1)+1)));
|
||||||
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))));
|
||||||
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)+1, (y<<1)+1, (z<<1)+1)));
|
||||||
|
|
||||||
|
|
||||||
this.renderGen.removeTask(lvl-1, (x<<1), (y<<1), (z<<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.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.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.removeTask(lvl, x, y, z);
|
||||||
|
|
||||||
this.renderGen.enqueueTask(lvl - 1, (x<<1), (y<<1), (z<<1), this::shouldStillBuild, this::getBuildFlagsOrAbort);
|
this.renderGen.enqueueTask(lvl - 1, (x<<1), (y<<1), (z<<1), this::shouldStillBuild, this::getBuildFlagsOrAbort);
|
||||||
|
|||||||
@@ -1,29 +1,43 @@
|
|||||||
package me.cortex.zenith.client.core.rendering.building;
|
package me.cortex.zenith.client.core.rendering.building;
|
||||||
|
|
||||||
|
import me.cortex.zenith.common.util.MemoryBuffer;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
//TODO: also have an AABB size stored
|
//TODO: also have an AABB size stored
|
||||||
public final class BuiltSection {
|
public final class BuiltSection {
|
||||||
public final long position;
|
public final long position;
|
||||||
public final BuiltSectionGeometry opaque;
|
public final int aabb;
|
||||||
public final BuiltSectionGeometry translucent;
|
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.position = position;
|
||||||
this.opaque = opaque;
|
this.aabb = aabb;
|
||||||
this.translucent = translucent;
|
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() {
|
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() {
|
public void free() {
|
||||||
if (this.opaque != null) {
|
if (this.geometryBuffer != null) {
|
||||||
this.opaque.free();
|
this.geometryBuffer.free();
|
||||||
}
|
|
||||||
if (this.translucent != null) {
|
|
||||||
this.translucent.free();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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+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
|
//MemoryUtil.memPutLong(buff.address+56, encodeRaw(3, 0,1,0,0,2,159,0, 0));//92 515
|
||||||
if (outData.isEmpty()) {
|
if (outData.isEmpty()) {
|
||||||
return new BuiltSection(section.getKey(), null, null);
|
return new BuiltSection(section.getKey());
|
||||||
}
|
}
|
||||||
//outData.clear();
|
//outData.clear();
|
||||||
|
|
||||||
@@ -317,7 +317,7 @@ public class RenderDataFactory {
|
|||||||
MemoryUtil.memPutLong(ptr, data); ptr+=8;
|
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()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ struct SectionMeta {
|
|||||||
uint posA;
|
uint posA;
|
||||||
uint posB;
|
uint posB;
|
||||||
uint AABB;
|
uint AABB;
|
||||||
uint _padA;
|
|
||||||
uint ptr;
|
uint ptr;
|
||||||
uint cnt;
|
uint cntA;
|
||||||
uint _padB;
|
uint cntB;
|
||||||
uint _padC;
|
uint cntC;
|
||||||
|
uint cntD;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: see if making the stride 2*4*4 bytes or something cause you get that 16 byte write
|
//TODO: see if making the stride 2*4*4 bytes or something cause you get that 16 byte write
|
||||||
|
|||||||
@@ -55,11 +55,13 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shouldRender) {
|
if (shouldRender) {
|
||||||
|
uint basePtr = extractQuadStart(meta);
|
||||||
|
|
||||||
DrawCommand cmd;
|
DrawCommand cmd;
|
||||||
cmd.count = extractQuadCount(meta) * 6;
|
cmd.count = (meta.cntA&0xFFFF) * 6;
|
||||||
cmd.instanceCount = 1;
|
cmd.instanceCount = 1;
|
||||||
cmd.firstIndex = 0;
|
cmd.firstIndex = 0;
|
||||||
cmd.baseVertex = int(extractQuadStart(meta))<<2;
|
cmd.baseVertex = int(basePtr)<<2;
|
||||||
cmd.baseInstance = encodeLocalLodPos(detail, ipos);
|
cmd.baseInstance = encodeLocalLodPos(detail, ipos);
|
||||||
cmdBuffer[atomicAdd(opaqueDrawCount, 1)] = cmd;
|
cmdBuffer[atomicAdd(opaqueDrawCount, 1)] = cmd;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,15 @@ void main() {
|
|||||||
|
|
||||||
uint detail = extractDetail(section);
|
uint detail = extractDetail(section);
|
||||||
ivec3 ipos = extractPosition(section);
|
ivec3 ipos = extractPosition(section);
|
||||||
|
ivec3 aabbOffset = extractAABBOffset(section);
|
||||||
|
ivec3 size = extractAABBSize(section);
|
||||||
|
|
||||||
//Transform ipos with respect to the vertex corner
|
//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(vec3(pos),1);
|
||||||
gl_Position = MVP * vec4(cornerPos,1);
|
|
||||||
|
|
||||||
//Write to this id
|
//Write to this id
|
||||||
id = sid;
|
id = sid;
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ uint extractQuadStart(SectionMeta meta) {
|
|||||||
return meta.ptr;
|
return meta.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint extractQuadCount(SectionMeta meta) {
|
ivec3 extractAABBOffset(SectionMeta meta) {
|
||||||
return meta.cnt;
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user