Temporal coherance
This commit is contained in:
@@ -11,6 +11,7 @@ import me.cortex.voxy.client.core.rendering.RenderService;
|
|||||||
import me.cortex.voxy.client.core.rendering.SharedIndexBuffer;
|
import me.cortex.voxy.client.core.rendering.SharedIndexBuffer;
|
||||||
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.UploadStream;
|
import me.cortex.voxy.client.core.rendering.util.UploadStream;
|
||||||
|
import me.cortex.voxy.common.Logger;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
@@ -36,6 +37,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 static final int TRANSLUCENT_OFFSET = 400_000;//in draw calls
|
private static final int TRANSLUCENT_OFFSET = 400_000;//in draw calls
|
||||||
|
private static final int TEMPORAL_OFFSET = 500_000;//in draw calls
|
||||||
private static final int STATISTICS_BUFFER_BINDING = 7;
|
private static final int STATISTICS_BUFFER_BINDING = 7;
|
||||||
private final Shader terrainShader = Shader.make()
|
private final Shader terrainShader = Shader.make()
|
||||||
.defineIf("DEBUG_RENDER", false)
|
.defineIf("DEBUG_RENDER", false)
|
||||||
@@ -45,6 +47,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
|
|
||||||
private final Shader commandGenShader = Shader.make()
|
private final Shader commandGenShader = Shader.make()
|
||||||
.define("TRANSLUCENT_OFFSET", TRANSLUCENT_OFFSET)
|
.define("TRANSLUCENT_OFFSET", TRANSLUCENT_OFFSET)
|
||||||
|
.define("TEMPORAL_OFFSET", TEMPORAL_OFFSET)
|
||||||
|
|
||||||
.defineIf("HAS_STATISTICS", RenderStatistics.enabled)
|
.defineIf("HAS_STATISTICS", RenderStatistics.enabled)
|
||||||
.defineIf("STATISTICS_BUFFER_BINDING", RenderStatistics.enabled, STATISTICS_BUFFER_BINDING)
|
.defineIf("STATISTICS_BUFFER_BINDING", RenderStatistics.enabled, STATISTICS_BUFFER_BINDING)
|
||||||
@@ -65,14 +68,17 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
|
|
||||||
//TODO: needs to be in the viewport, since it contains the compute indirect call/values
|
//TODO: needs to be in the viewport, since it contains the compute indirect call/values
|
||||||
private final GlBuffer drawCountCallBuffer = new GlBuffer(1024).zero();
|
private final GlBuffer drawCountCallBuffer = new GlBuffer(1024).zero();
|
||||||
private final GlBuffer drawCallBuffer = new GlBuffer(5*4*(400_000+100_000)).zero();//400k draw calls
|
private final GlBuffer drawCallBuffer = new GlBuffer(5*4*(400_000+100_000+100_000)).zero();//400k draw calls
|
||||||
private final GlBuffer positionScratchBuffer = new GlBuffer(8*400000).zero();//400k positions
|
private final GlBuffer positionScratchBuffer = new GlBuffer(8*400000).zero();//400k positions
|
||||||
|
|
||||||
//Statistics
|
//Statistics
|
||||||
private final GlBuffer statisticsBuffer = new GlBuffer(1024).zero();
|
private final GlBuffer statisticsBuffer = new GlBuffer(1024).zero();
|
||||||
|
|
||||||
|
private final int maxSectionCount;
|
||||||
|
|
||||||
public MDICSectionRenderer(ModelStore modelStore, int maxSectionCount, long geometryCapacity) {
|
public MDICSectionRenderer(ModelStore modelStore, int maxSectionCount, long geometryCapacity) {
|
||||||
super(modelStore, new BasicSectionGeometryManager(maxSectionCount, geometryCapacity));
|
super(modelStore, new BasicSectionGeometryManager(maxSectionCount, geometryCapacity));
|
||||||
|
this.maxSectionCount = maxSectionCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -90,7 +96,11 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
MemoryUtil.memPutInt(ptr, sx); ptr += 4;
|
MemoryUtil.memPutInt(ptr, sx); ptr += 4;
|
||||||
MemoryUtil.memPutInt(ptr, sy); ptr += 4;
|
MemoryUtil.memPutInt(ptr, sy); ptr += 4;
|
||||||
MemoryUtil.memPutInt(ptr, sz); ptr += 4;
|
MemoryUtil.memPutInt(ptr, sz); ptr += 4;
|
||||||
MemoryUtil.memPutInt(ptr, viewport.frameId); ptr += 4;
|
if (viewport.frameId<0) {
|
||||||
|
Logger.error("Frame ID negative, this will cause things to break, wrapping around");
|
||||||
|
viewport.frameId &= 0x7fffffff;
|
||||||
|
}
|
||||||
|
MemoryUtil.memPutInt(ptr, viewport.frameId&0x7fffffff); ptr += 4;
|
||||||
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
||||||
|
|
||||||
UploadStream.INSTANCE.commit();
|
UploadStream.INSTANCE.commit();
|
||||||
@@ -116,7 +126,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderTerrain() {
|
private void renderTerrain(long indirectOffset, long drawCountOffset, int maxDrawCount) {
|
||||||
//RenderLayer.getCutoutMipped().startDrawing();
|
//RenderLayer.getCutoutMipped().startDrawing();
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
@@ -125,7 +135,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
glBindVertexArray(RenderService.STATIC_VAO);//Needs to be before binding
|
glBindVertexArray(RenderService.STATIC_VAO);//Needs to be before binding
|
||||||
this.bindRenderingBuffers();
|
this.bindRenderingBuffers();
|
||||||
|
|
||||||
glMultiDrawElementsIndirectCountARB(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0, 4*3, Math.min((int)(this.geometryManager.getSectionCount()*4.4+128), 400_000), 0);
|
glMultiDrawElementsIndirectCountARB(GL_TRIANGLES, GL_UNSIGNED_SHORT, indirectOffset, drawCountOffset, maxDrawCount, 0);
|
||||||
|
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
@@ -143,7 +153,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
|
|
||||||
this.uploadUniformBuffer(viewport);
|
this.uploadUniformBuffer(viewport);
|
||||||
|
|
||||||
this.renderTerrain();
|
this.renderTerrain(0, 4*3, Math.min((int)(this.geometryManager.getSectionCount()*4.4+128), 400_000));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,6 +254,9 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Render temporal
|
||||||
|
this.renderTerrain(TEMPORAL_OFFSET*5*4, 4*5, Math.min(this.geometryManager.getSectionCount(), 100_000));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -254,7 +267,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MDICViewport createViewport() {
|
public MDICViewport createViewport() {
|
||||||
return new MDICViewport();
|
return new MDICViewport(this.maxSectionCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import me.cortex.voxy.client.core.gl.GlBuffer;
|
|||||||
import me.cortex.voxy.client.core.rendering.Viewport;
|
import me.cortex.voxy.client.core.rendering.Viewport;
|
||||||
|
|
||||||
public class MDICViewport extends Viewport<MDICViewport> {
|
public class MDICViewport extends Viewport<MDICViewport> {
|
||||||
public final GlBuffer visibilityBuffer = new GlBuffer(100_000*4);
|
|
||||||
public final GlBuffer indirectLookupBuffer = new GlBuffer(100_000*4+4);
|
public final GlBuffer indirectLookupBuffer = new GlBuffer(100_000*4+4);
|
||||||
|
public final GlBuffer visibilityBuffer;
|
||||||
|
|
||||||
|
public MDICViewport(int maxSectionCount) {
|
||||||
|
this.visibilityBuffer = new GlBuffer(maxSectionCount*4L);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void delete0() {
|
protected void delete0() {
|
||||||
|
|||||||
@@ -59,20 +59,16 @@ void main() {
|
|||||||
vec3 cornerPos = vec3(((ipos<<detail)-baseSectionPos)<<5)-cameraSubPos;
|
vec3 cornerPos = vec3(((ipos<<detail)-baseSectionPos)<<5)-cameraSubPos;
|
||||||
|
|
||||||
|
|
||||||
//Note! its not with respect to the sectionId
|
uint dat = visibilityData[sectionId];
|
||||||
//
|
|
||||||
//Check the occlusion data from this frame occlusion
|
|
||||||
bool shouldRender = visibilityData[gl_GlobalInvocationID.x] == frameId;
|
|
||||||
|
|
||||||
//Clear the occlusion data (not strictly? needed? i think???)
|
//if the section was visible this frame
|
||||||
//visibilityData[gl_GlobalInvocationID.x] = 0;
|
bool shouldRender = (dat&0x7fffffffu) == frameId;
|
||||||
|
bool renderTemporally = (dat&0x80000000u)==0;// means, if it was not visible last frame
|
||||||
//TODO: need to make it check that only if it was also in the frustum last frame does it apply the visibilityData check!
|
|
||||||
// this fixes temporal coherance
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (shouldRender) {
|
if (shouldRender) {
|
||||||
|
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
atomicAdd(visibleSectionCounts[detail], 1);
|
atomicAdd(visibleSectionCounts[detail], 1);
|
||||||
#endif
|
#endif
|
||||||
@@ -95,8 +91,15 @@ void main() {
|
|||||||
msk |= uint(((meta.cntA>>16)&0xFFFF)!=0)<<6;
|
msk |= uint(((meta.cntA>>16)&0xFFFF)!=0)<<6;
|
||||||
|
|
||||||
|
|
||||||
uint cmdPtr = atomicAdd(opaqueDrawCount, bitCount(msk));
|
uint cmdCnt = bitCount(msk);
|
||||||
|
uint cmdPtr = atomicAdd(opaqueDrawCount, cmdCnt);
|
||||||
|
|
||||||
|
uint tCmdPtr = 0;
|
||||||
|
if (renderTemporally) {
|
||||||
|
tCmdPtr = atomicAdd(temporalOpaqueDrawCount, cmdCnt) + TEMPORAL_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: make totalQuads also have temporal amount
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
uint totalQuads = 0;
|
uint totalQuads = 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -117,6 +120,9 @@ void main() {
|
|||||||
count = (meta.cntA>>16)&0xFFFF;
|
count = (meta.cntA>>16)&0xFFFF;
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
writeCmd(cmdPtr++, drawId, ptr, count);
|
writeCmd(cmdPtr++, drawId, ptr, count);
|
||||||
|
if (renderTemporally) {
|
||||||
|
writeCmd(tCmdPtr++, drawId, ptr, count);
|
||||||
|
}
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
totalQuads += count;
|
totalQuads += count;
|
||||||
#endif
|
#endif
|
||||||
@@ -127,6 +133,9 @@ void main() {
|
|||||||
count = (meta.cntB)&0xFFFF;
|
count = (meta.cntB)&0xFFFF;
|
||||||
if (((msk&(1u<<0))!=0)) {
|
if (((msk&(1u<<0))!=0)) {
|
||||||
writeCmd(cmdPtr++, drawId, ptr, count);
|
writeCmd(cmdPtr++, drawId, ptr, count);
|
||||||
|
if (renderTemporally) {
|
||||||
|
writeCmd(tCmdPtr++, drawId, ptr, count);
|
||||||
|
}
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
totalQuads += count;
|
totalQuads += count;
|
||||||
#endif
|
#endif
|
||||||
@@ -137,6 +146,9 @@ void main() {
|
|||||||
count = (meta.cntB>>16)&0xFFFF;
|
count = (meta.cntB>>16)&0xFFFF;
|
||||||
if ((msk&(1u<<1))!=0) {
|
if ((msk&(1u<<1))!=0) {
|
||||||
writeCmd(cmdPtr++, drawId, ptr, count);
|
writeCmd(cmdPtr++, drawId, ptr, count);
|
||||||
|
if (renderTemporally) {
|
||||||
|
writeCmd(tCmdPtr++, drawId, ptr, count);
|
||||||
|
}
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
totalQuads += count;
|
totalQuads += count;
|
||||||
#endif
|
#endif
|
||||||
@@ -147,6 +159,9 @@ void main() {
|
|||||||
count = (meta.cntC)&0xFFFF;
|
count = (meta.cntC)&0xFFFF;
|
||||||
if ((msk&(1u<<2))!=0) {
|
if ((msk&(1u<<2))!=0) {
|
||||||
writeCmd(cmdPtr++, drawId, ptr, count);
|
writeCmd(cmdPtr++, drawId, ptr, count);
|
||||||
|
if (renderTemporally) {
|
||||||
|
writeCmd(tCmdPtr++, drawId, ptr, count);
|
||||||
|
}
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
totalQuads += count;
|
totalQuads += count;
|
||||||
#endif
|
#endif
|
||||||
@@ -157,6 +172,9 @@ void main() {
|
|||||||
count = (meta.cntC>>16)&0xFFFF;
|
count = (meta.cntC>>16)&0xFFFF;
|
||||||
if ((msk&(1u<<3))!=0) {
|
if ((msk&(1u<<3))!=0) {
|
||||||
writeCmd(cmdPtr++, drawId, ptr, count);
|
writeCmd(cmdPtr++, drawId, ptr, count);
|
||||||
|
if (renderTemporally) {
|
||||||
|
writeCmd(tCmdPtr++, drawId, ptr, count);
|
||||||
|
}
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
totalQuads += count;
|
totalQuads += count;
|
||||||
#endif
|
#endif
|
||||||
@@ -167,6 +185,9 @@ void main() {
|
|||||||
count = (meta.cntD)&0xFFFF;
|
count = (meta.cntD)&0xFFFF;
|
||||||
if ((msk&(1u<<4))!=0) {
|
if ((msk&(1u<<4))!=0) {
|
||||||
writeCmd(cmdPtr++, drawId, ptr, count);
|
writeCmd(cmdPtr++, drawId, ptr, count);
|
||||||
|
if (renderTemporally) {
|
||||||
|
writeCmd(tCmdPtr++, drawId, ptr, count);
|
||||||
|
}
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
totalQuads += count;
|
totalQuads += count;
|
||||||
#endif
|
#endif
|
||||||
@@ -177,6 +198,9 @@ void main() {
|
|||||||
count = (meta.cntD>>16)&0xFFFF;
|
count = (meta.cntD>>16)&0xFFFF;
|
||||||
if ((msk&(1u<<5))!=0) {
|
if ((msk&(1u<<5))!=0) {
|
||||||
writeCmd(cmdPtr++, drawId, ptr, count);
|
writeCmd(cmdPtr++, drawId, ptr, count);
|
||||||
|
if (renderTemporally) {
|
||||||
|
writeCmd(tCmdPtr++, drawId, ptr, count);
|
||||||
|
}
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
totalQuads += count;
|
totalQuads += count;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ layout(early_fragment_tests) in;
|
|||||||
|
|
||||||
flat in uint id;
|
flat in uint id;
|
||||||
flat in uint value;
|
flat in uint value;
|
||||||
out vec4 colour;
|
//out vec4 colour;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
visibilityData[id] = value;
|
visibilityData[id] = value;
|
||||||
colour = vec4(float(id&7u)/7, float((id>>3)&7u)/7, float((id>>6)&7u)/7, 1);
|
//colour = vec4(float(id&7u)/7, float((id>>3)&7u)/7, float((id>>6)&7u)/7, 1);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#version 460 core
|
#version 460 core
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
#extension GL_ARB_gpu_shader_int64 : enable
|
||||||
#define VISIBILITY_ACCESS writeonly
|
#define VISIBILITY_ACCESS readonly
|
||||||
|
|
||||||
#define SECTION_METADATA_BUFFER_BINDING 1
|
#define SECTION_METADATA_BUFFER_BINDING 1
|
||||||
#define VISIBILITY_BUFFER_BINDING 2
|
#define VISIBILITY_BUFFER_BINDING 2
|
||||||
@@ -29,7 +29,10 @@ void main() {
|
|||||||
|
|
||||||
gl_Position = MVP * vec4(vec3(pos),1);
|
gl_Position = MVP * vec4(vec3(pos),1);
|
||||||
|
|
||||||
//Write to this id
|
//Write to the section id, to track temporal over time (litterally just need a single bit, 1 fking bit, but no)
|
||||||
id = gl_InstanceID;//Note!! we write to the instance id _not_ the section id
|
id = sid;
|
||||||
value = frameId;
|
|
||||||
|
uint previous = visibilityData[sid]&0x7fffffffu;
|
||||||
|
bool wasVisibleLastFrame = previous==(frameId-1);
|
||||||
|
value = (frameId&0x7fffffffu)|(uint(wasVisibleLastFrame)<<31);//Encode if it was visible last frame
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user