It works EVEN BETTER
This commit is contained in:
@@ -77,16 +77,16 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
|||||||
world.getMapper().setBiomeCallback(this.modelService::addBiome);
|
world.getMapper().setBiomeCallback(this.modelService::addBiome);
|
||||||
|
|
||||||
//this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(0, 0,0,0));
|
//this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(0, 0,0,0));
|
||||||
this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, 0,0,0));
|
//this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, 0,0,0));
|
||||||
/*
|
|
||||||
final int H_WIDTH = 1;
|
final int H_WIDTH = 10;
|
||||||
for (int x = -H_WIDTH; x <= H_WIDTH; x++) {
|
for (int x = -H_WIDTH; x <= H_WIDTH; x++) {
|
||||||
for (int y = -1; y <= 0; y++) {
|
for (int y = 0; y <= 0; y++) {
|
||||||
for (int z = -H_WIDTH; z <= H_WIDTH; z++) {
|
for (int z = -H_WIDTH; z <= H_WIDTH; z++) {
|
||||||
this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, x, y, z));
|
this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, x, y, z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setup(Camera camera) {
|
public void setup(Camera camera) {
|
||||||
@@ -123,6 +123,8 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
|||||||
if (this.nodeManager.writeChanges(this.traversal.getNodeBuffer())) {//TODO: maybe move the node buffer out of the traversal class
|
if (this.nodeManager.writeChanges(this.traversal.getNodeBuffer())) {//TODO: maybe move the node buffer out of the traversal class
|
||||||
UploadStream.INSTANCE.commit();
|
UploadStream.INSTANCE.commit();
|
||||||
}
|
}
|
||||||
|
//this needs to go after, due to geometry updates committed by the nodeManager
|
||||||
|
this.sectionRenderer.getGeometryManager().tick();
|
||||||
}
|
}
|
||||||
UploadStream.INSTANCE.tick();
|
UploadStream.INSTANCE.tick();
|
||||||
|
|
||||||
@@ -142,6 +144,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
|||||||
this.modelService.addDebugData(debug);
|
this.modelService.addDebugData(debug);
|
||||||
this.renderGen.addDebugData(debug);
|
this.renderGen.addDebugData(debug);
|
||||||
this.sectionRenderer.addDebug(debug);
|
this.sectionRenderer.addDebug(debug);
|
||||||
|
this.nodeManager.addDebug(debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
MemoryUtil.memPutInt(ptr, (int) (this.renderList.size()/4-1)); ptr += 4;//TODO maybe move this to a #define
|
MemoryUtil.memPutInt(ptr, (int) (this.renderList.size()/4-1)); ptr += 4;//TODO maybe move this to a #define
|
||||||
|
|
||||||
//Screen space size for descending
|
//Screen space size for descending
|
||||||
MemoryUtil.memPutFloat(ptr, 64*64); ptr += 4;
|
MemoryUtil.memPutFloat(ptr, 128*128); ptr += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindings() {
|
private void bindings() {
|
||||||
@@ -143,7 +143,7 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
PrintfDebugUtil.bind();
|
PrintfDebugUtil.bind();
|
||||||
|
|
||||||
|
|
||||||
this.traverseInternal(1);
|
this.traverseInternal(this.nodeManager.getTopLevelNodeIds().size());
|
||||||
|
|
||||||
|
|
||||||
this.downloadResetRequestQueue();
|
this.downloadResetRequestQueue();
|
||||||
@@ -192,7 +192,7 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
|
|
||||||
ptr = UploadStream.INSTANCE.upload(this.scratchQueueA, 0, 4L*initialQueueSize);
|
ptr = UploadStream.INSTANCE.upload(this.scratchQueueA, 0, 4L*initialQueueSize);
|
||||||
for (int i = 0; i < initialQueueSize; i++) {
|
for (int i = 0; i < initialQueueSize; i++) {
|
||||||
MemoryUtil.memPutInt(ptr + 4L*i, 0);
|
MemoryUtil.memPutInt(ptr + 4L*i, this.nodeManager.getTopLevelNodeIds().getInt(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadStream.INSTANCE.commit();
|
UploadStream.INSTANCE.commit();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package me.cortex.voxy.client.core.rendering.hierachical2;
|
package me.cortex.voxy.client.core.rendering.hierachical2;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||||
import me.cortex.voxy.client.core.gl.GlBuffer;
|
import me.cortex.voxy.client.core.gl.GlBuffer;
|
||||||
@@ -12,6 +13,10 @@ import me.cortex.voxy.common.Logger;
|
|||||||
import me.cortex.voxy.common.world.WorldEngine;
|
import me.cortex.voxy.common.world.WorldEngine;
|
||||||
import me.jellysquid.mods.sodium.client.util.MathUtil;
|
import me.jellysquid.mods.sodium.client.util.MathUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class NodeManager2 {
|
public class NodeManager2 {
|
||||||
//Assumptions:
|
//Assumptions:
|
||||||
// all nodes have children (i.e. all nodes have at least one child existence bit set at all times)
|
// all nodes have children (i.e. all nodes have at least one child existence bit set at all times)
|
||||||
@@ -22,6 +27,18 @@ public class NodeManager2 {
|
|||||||
// For the queue processing, will need a redirect node-value type
|
// For the queue processing, will need a redirect node-value type
|
||||||
// since for inner node child resize gpu could take N frames to update
|
// since for inner node child resize gpu could take N frames to update
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//There is a very funny issue that has kinda, just resolved itself accidentally,
|
||||||
|
// however i wonder if i want a better solution for.
|
||||||
|
//That issue is, top level nodes that have no children
|
||||||
|
// the accidental solution, is that when the node is marked, it generates
|
||||||
|
// the child request,
|
||||||
|
// however, since there are no children in it, it sticks around, since there isnt anything to update it and invoke
|
||||||
|
// the finishRequest on it
|
||||||
|
// if the top level node ends up being updated with a child update, it should automatically solve itself
|
||||||
|
// as the new children are added to the already inprogress request!!!!
|
||||||
|
|
||||||
public static final int NULL_GEOMETRY_ID = -1;
|
public static final int NULL_GEOMETRY_ID = -1;
|
||||||
public static final int EMPTY_GEOMETRY_ID = -2;
|
public static final int EMPTY_GEOMETRY_ID = -2;
|
||||||
|
|
||||||
@@ -44,6 +61,7 @@ public class NodeManager2 {
|
|||||||
private final Long2IntOpenHashMap activeSectionMap = new Long2IntOpenHashMap();
|
private final Long2IntOpenHashMap activeSectionMap = new Long2IntOpenHashMap();
|
||||||
private final NodeStore nodeData;
|
private final NodeStore nodeData;
|
||||||
public final int maxNodeCount;
|
public final int maxNodeCount;
|
||||||
|
private final IntArrayList topLevelNodeIds = new IntArrayList();
|
||||||
public NodeManager2(int maxNodeCount, AbstractSectionGeometryManager geometryManager, SectionUpdateRouter updateRouter) {
|
public NodeManager2(int maxNodeCount, AbstractSectionGeometryManager geometryManager, SectionUpdateRouter updateRouter) {
|
||||||
if (!MathUtil.isPowerOfTwo(maxNodeCount)) {
|
if (!MathUtil.isPowerOfTwo(maxNodeCount)) {
|
||||||
throw new IllegalArgumentException("Max node count must be a power of 2");
|
throw new IllegalArgumentException("Max node count must be a power of 2");
|
||||||
@@ -68,6 +86,8 @@ public class NodeManager2 {
|
|||||||
int id = this.singleRequests.put(request);
|
int id = this.singleRequests.put(request);
|
||||||
this.updateRouter.watch(pos, WorldEngine.UPDATE_FLAGS);
|
this.updateRouter.watch(pos, WorldEngine.UPDATE_FLAGS);
|
||||||
this.activeSectionMap.put(pos, id|NODE_TYPE_REQUEST|REQUEST_TYPE_SINGLE);
|
this.activeSectionMap.put(pos, id|NODE_TYPE_REQUEST|REQUEST_TYPE_SINGLE);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeTopLevelNode(long pos) {
|
public void removeTopLevelNode(long pos) {
|
||||||
@@ -77,6 +97,16 @@ public class NodeManager2 {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//TODO: assert is top level node
|
//TODO: assert is top level node
|
||||||
|
|
||||||
|
//TODO:FIXME augment topLevelNodeIds with a hashmap from node id to array index
|
||||||
|
// OR!! just ensure the list is always ordered?? maybe? idk i think hashmap is best
|
||||||
|
// since the array list might get shuffled as nodes are removed
|
||||||
|
// since need to move the entry at the end of the array to fill a hole made
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IntArrayList getTopLevelNodeIds() {
|
||||||
|
return this.topLevelNodeIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==================================================================================================================
|
//==================================================================================================================
|
||||||
@@ -217,6 +247,11 @@ public class NodeManager2 {
|
|||||||
//this.nodeData.setNodeType();
|
//this.nodeData.setNodeType();
|
||||||
this.activeSectionMap.put(request.getPosition(), id|NODE_TYPE_LEAF);//Assume that the result of any single request type is a leaf node
|
this.activeSectionMap.put(request.getPosition(), id|NODE_TYPE_LEAF);//Assume that the result of any single request type is a leaf node
|
||||||
this.nodeUpdates.add(id);
|
this.nodeUpdates.add(id);
|
||||||
|
|
||||||
|
|
||||||
|
//Assume that this is always a top node
|
||||||
|
// FIXME: DONT DO THIS
|
||||||
|
this.topLevelNodeIds.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishRequest(int requestId, NodeChildRequest request) {
|
private void finishRequest(int requestId, NodeChildRequest request) {
|
||||||
@@ -367,4 +402,8 @@ public class NodeManager2 {
|
|||||||
(WorldEngine.getY(basePos)<<1)|((addin>>2)&1),
|
(WorldEngine.getY(basePos)<<1)|((addin>>2)&1),
|
||||||
(WorldEngine.getZ(basePos)<<1)|((addin>>1)&1));
|
(WorldEngine.getZ(basePos)<<1)|((addin>>1)&1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDebug(List<String> debug) {
|
||||||
|
debug.add("NC/IF: " + this.activeSectionMap.size() + "/" + (this.singleRequests.count() + this.childRequests.count()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ public final class NodeStore {
|
|||||||
int w = 0;
|
int w = 0;
|
||||||
|
|
||||||
short flags = 0;
|
short flags = 0;
|
||||||
|
flags |= (short) (this.isNodeRequestInFlight(nodeId)?1:0);
|
||||||
flags |= (short) (this.getChildPtrCount(nodeId)<<2);
|
flags |= (short) (this.getChildPtrCount(nodeId)<<2);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public abstract class AbstractSectionGeometryManager {
|
|||||||
public int uploadSection(BuiltSection section) {return this.uploadReplaceSection(-1, section);}
|
public int uploadSection(BuiltSection section) {return this.uploadReplaceSection(-1, section);}
|
||||||
public abstract int uploadReplaceSection(int oldId, BuiltSection section);
|
public abstract int uploadReplaceSection(int oldId, BuiltSection section);
|
||||||
public abstract void removeSection(int id);
|
public abstract void removeSection(int id);
|
||||||
void tick() {}
|
public void tick() {}
|
||||||
|
|
||||||
public void free() {}
|
public void free() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public class BasicSectionGeometryManager extends AbstractSectionGeometryManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void tick() {
|
public void tick() {
|
||||||
//Upload all invalidated bits
|
//Upload all invalidated bits
|
||||||
if (!this.invalidatedSectionIds.isEmpty()) {
|
if (!this.invalidatedSectionIds.isEmpty()) {
|
||||||
for (int id : this.invalidatedSectionIds) {
|
for (int id : this.invalidatedSectionIds) {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import static org.lwjgl.opengl.GL45.glCopyNamedBufferSubData;
|
|||||||
//Uses MDIC to render the sections
|
//Uses MDIC to render the sections
|
||||||
public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, BasicSectionGeometryManager> {
|
public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, BasicSectionGeometryManager> {
|
||||||
private final Shader terrainShader = Shader.make()
|
private final Shader terrainShader = Shader.make()
|
||||||
|
.defineIf("DEBUG_RENDER", false)
|
||||||
.add(ShaderType.VERTEX, "voxy:lod/gl46/quads2.vert")
|
.add(ShaderType.VERTEX, "voxy:lod/gl46/quads2.vert")
|
||||||
.add(ShaderType.FRAGMENT, "voxy:lod/gl46/quads.frag")
|
.add(ShaderType.FRAGMENT, "voxy:lod/gl46/quads.frag")
|
||||||
.compile();
|
.compile();
|
||||||
@@ -119,11 +120,6 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
public void renderOpaque(MDICViewport viewport) {
|
public void renderOpaque(MDICViewport viewport) {
|
||||||
if (this.geometryManager.getSectionCount() == 0) return;
|
if (this.geometryManager.getSectionCount() == 0) return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Tick the geometry manager to upload all invalidated metadata changes to the gpu before invoking the command gen shader
|
|
||||||
this.geometryManager.tick();
|
|
||||||
|
|
||||||
this.uploadUniformBuffer(viewport);
|
this.uploadUniformBuffer(viewport);
|
||||||
|
|
||||||
//TODO compute the draw calls
|
//TODO compute the draw calls
|
||||||
@@ -193,7 +189,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
@Override
|
@Override
|
||||||
public void addDebug(List<String> lines) {
|
public void addDebug(List<String> lines) {
|
||||||
super.addDebug(lines);
|
super.addDebug(lines);
|
||||||
lines.add("NC/GS: " + this.geometryManager.getSectionCount() + "/" + (this.geometryManager.getGeometryUsed()/(1024*1024)));//Node count/geometry size (MB)
|
lines.add("SC/GS: " + this.geometryManager.getSectionCount() + "/" + (this.geometryManager.getGeometryUsed()/(1024*1024)));//section count/geometry size (MB)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -42,4 +42,8 @@ public class ExpandingObjectAllocationList<T> {
|
|||||||
}
|
}
|
||||||
return this.objects[index];
|
return this.objects[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int count() {
|
||||||
|
return this.bitSet.getCount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,11 +88,13 @@ void traverse(in UnpackedNode node) {
|
|||||||
addRequest(node);
|
addRequest(node);
|
||||||
|
|
||||||
//TODO: Decend into children? maybe add a bitflag saying is bad if the immediate children dont have meshes
|
//TODO: Decend into children? maybe add a bitflag saying is bad if the immediate children dont have meshes
|
||||||
|
if (node.lodLevel != 0) {
|
||||||
enqueueChildren(node);
|
enqueueChildren(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uint nodeId = getCurrentNode();
|
uint nodeId = getCurrentNode();
|
||||||
|
|||||||
Reference in New Issue
Block a user