Rasterized occlusion culling
This commit is contained in:
@@ -24,10 +24,13 @@ public class DistanceTracker {
|
|||||||
this.rings = new TransitionRing2D[rings+1];
|
this.rings = new TransitionRing2D[rings+1];
|
||||||
this.tracker = tracker;
|
this.tracker = tracker;
|
||||||
|
|
||||||
int DIST = 16;
|
//NOTE: This is in our render distance units, to convert to chunks at lvl 0 multiply by 2
|
||||||
|
int DIST = 24;
|
||||||
|
|
||||||
this.rings[0] = new TransitionRing2D(5, DIST, (x,z)->{
|
this.rings[0] = new TransitionRing2D(5, DIST, (x,z)->{
|
||||||
if (true) return;
|
if (true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (int y = -2; y < 10; y++) {
|
for (int y = -2; y < 10; y++) {
|
||||||
this.tracker.remLvl0(x, y, z);
|
this.tracker.remLvl0(x, y, z);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
|||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
private final GlBuffer glCommandBuffer = new GlBuffer(100_000*5*4, 0);
|
private final GlBuffer glCommandBuffer = new GlBuffer(100_000*5*4, 0);
|
||||||
|
private final GlBuffer glVisibilityBuffer = new GlBuffer(100_000*4, 0);
|
||||||
|
|
||||||
public Gl46FarWorldRenderer() {
|
public Gl46FarWorldRenderer() {
|
||||||
super();
|
super();
|
||||||
@@ -63,9 +64,10 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
|||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.geometry.geometryId());
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.geometry.geometryId());
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, this.glCommandBuffer.id);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, this.glCommandBuffer.id);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, this.geometry.metaId());
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, this.geometry.metaId());
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, this.stateDataBuffer.id);//State LUT
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, this.glVisibilityBuffer.id);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, this.biomeDataBuffer.id);//Biome LUT
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, this.stateDataBuffer.id);//State LUT
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0);//Lighting LUT
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.biomeDataBuffer.id);//Biome LUT
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, 0);//Lighting LUT
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,11 +93,23 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
|||||||
|
|
||||||
glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT|GL_FRAMEBUFFER_BARRIER_BIT);
|
glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT|GL_FRAMEBUFFER_BARRIER_BIT);
|
||||||
//TODO: add gpu occlusion culling here (after the lod drawing) (maybe, finish the rest of the PoC first)
|
//TODO: add gpu occlusion culling here (after the lod drawing) (maybe, finish the rest of the PoC first)
|
||||||
|
cullShader.bind();
|
||||||
|
|
||||||
|
glColorMask(false,false,false,false);
|
||||||
|
glDepthMask(false);
|
||||||
|
glDrawElementsInstanced(GL_TRIANGLES, 6*2*3, GL_UNSIGNED_BYTE, (1<<16)*6*2, this.geometry.getSectionCount());
|
||||||
|
glDepthMask(true);
|
||||||
|
glColorMask(true,true,true,true);
|
||||||
|
|
||||||
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
RenderLayer.getCutoutMipped().endDrawing();
|
RenderLayer.getCutoutMipped().endDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: dont do something like this as it breaks multiviewport mods
|
||||||
|
private int frameId = 0;
|
||||||
private void updateUniformBuffer(MatrixStack stack, double cx, double cy, double cz) {
|
private void updateUniformBuffer(MatrixStack stack, double cx, double cy, double cz) {
|
||||||
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, this.uniformBuffer.size());
|
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, this.uniformBuffer.size());
|
||||||
var mat = new Matrix4f(RenderSystem.getProjectionMatrix()).mul(stack.peek().getPositionMatrix());
|
var mat = new Matrix4f(RenderSystem.getProjectionMatrix()).mul(stack.peek().getPositionMatrix());
|
||||||
@@ -111,6 +125,7 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
|||||||
plane.getToAddress(ptr); ptr += 4*4;
|
plane.getToAddress(ptr); ptr += 4*4;
|
||||||
}
|
}
|
||||||
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
||||||
|
MemoryUtil.memPutInt(ptr, this.frameId++); ptr += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -119,6 +134,8 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
|||||||
this.commandGen.free();
|
this.commandGen.free();
|
||||||
this.lodShader.free();
|
this.lodShader.free();
|
||||||
this.cullShader.free();
|
this.cullShader.free();
|
||||||
|
this.glCommandBuffer.free();
|
||||||
|
this.glVisibilityBuffer.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -167,19 +167,23 @@ public class RenderTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getBuildFlagsOrAbort(WorldSection section) {
|
public int getBuildFlagsOrAbort(WorldSection section) {
|
||||||
|
var cam = MinecraftClient.getInstance().cameraEntity;
|
||||||
|
if (cam == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
var holder = this.activeSections.get(section.getKey());
|
var holder = this.activeSections.get(section.getKey());
|
||||||
int buildMask = 0;
|
int buildMask = 0;
|
||||||
if (holder != null) {
|
if (holder != null) {
|
||||||
if (section.z< (((int)MinecraftClient.getInstance().cameraEntity.getPos().z)>>(5+section.lvl))+1) {
|
if (section.z<(((int)cam.getPos().z)>>(5+section.lvl))+1) {
|
||||||
buildMask |= 1<< Direction.SOUTH.getId();
|
buildMask |= 1<< Direction.SOUTH.getId();
|
||||||
}
|
}
|
||||||
if (section.z>(((int)MinecraftClient.getInstance().cameraEntity.getPos().z)>>(5+section.lvl))-1) {
|
if (section.z>(((int)cam.getPos().z)>>(5+section.lvl))-1) {
|
||||||
buildMask |= 1<<Direction.NORTH.getId();
|
buildMask |= 1<<Direction.NORTH.getId();
|
||||||
}
|
}
|
||||||
if (section.x<(((int)MinecraftClient.getInstance().cameraEntity.getPos().x)>>(5+section.lvl))+1) {
|
if (section.x<(((int)cam.getPos().x)>>(5+section.lvl))+1) {
|
||||||
buildMask |= 1<<Direction.EAST.getId();
|
buildMask |= 1<<Direction.EAST.getId();
|
||||||
}
|
}
|
||||||
if (section.x>(((int)MinecraftClient.getInstance().cameraEntity.getPos().x)>>(5+section.lvl))-1) {
|
if (section.x>(((int)cam.getPos().x)>>(5+section.lvl))-1) {
|
||||||
buildMask |= 1<<Direction.WEST.getId();
|
buildMask |= 1<<Direction.WEST.getId();
|
||||||
}
|
}
|
||||||
buildMask |= 1<<Direction.UP.getId();
|
buildMask |= 1<<Direction.UP.getId();
|
||||||
|
|||||||
@@ -1,39 +1,89 @@
|
|||||||
package me.cortex.voxelmon.core.rendering;
|
package me.cortex.voxelmon.core.rendering;
|
||||||
|
|
||||||
|
import me.cortex.voxelmon.core.gl.GlBuffer;
|
||||||
import me.cortex.voxelmon.core.rendering.util.BufferArena;
|
import me.cortex.voxelmon.core.rendering.util.BufferArena;
|
||||||
|
import me.cortex.voxelmon.core.rendering.util.UploadStream;
|
||||||
import me.cortex.voxelmon.core.util.IndexUtil;
|
import me.cortex.voxelmon.core.util.IndexUtil;
|
||||||
|
import me.cortex.voxelmon.core.util.MemoryBuffer;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
|
||||||
|
//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 SharedIndexBuffer INSTANCE = new SharedIndexBuffer();
|
public static final SharedIndexBuffer INSTANCE = new SharedIndexBuffer();
|
||||||
|
|
||||||
private int commonIndexBufferOffset = -1;
|
private final GlBuffer indexBuffer;
|
||||||
private int commonIndexQuadCount;
|
|
||||||
|
|
||||||
private final BufferArena indexBuffer;
|
|
||||||
|
|
||||||
public SharedIndexBuffer() {
|
public SharedIndexBuffer() {
|
||||||
this.indexBuffer = new BufferArena((1L << 16)*(2*6), 2 * 6);
|
this.indexBuffer = new GlBuffer((1<<16)*6*2 + 6*2*3, 0);
|
||||||
this.getSharedIndexBuffer(16380);
|
var quadIndexBuff = IndexUtil.generateQuadIndicesShort(16380);
|
||||||
|
var cubeBuff = generateCubeIndexBuffer();
|
||||||
|
|
||||||
|
long ptr = UploadStream.INSTANCE.upload(this.indexBuffer, 0, this.indexBuffer.size());
|
||||||
|
quadIndexBuff.cpyTo(ptr);
|
||||||
|
cubeBuff.cpyTo((1<<16)*2*6 + ptr);
|
||||||
|
|
||||||
|
quadIndexBuff.free();
|
||||||
|
cubeBuff.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSharedIndexBuffer(int newQuadCount) {
|
private static MemoryBuffer generateCubeIndexBuffer() {
|
||||||
if (this.commonIndexBufferOffset == -1 || this.commonIndexQuadCount < newQuadCount) {
|
var buffer = new MemoryBuffer(6*2*3);
|
||||||
if (this.commonIndexBufferOffset != -1) {
|
long ptr = buffer.address;
|
||||||
this.indexBuffer.free(this.commonIndexBufferOffset);
|
MemoryUtil.memSet(ptr, 0, 6*2*3 );
|
||||||
}
|
|
||||||
var buffer = IndexUtil.generateQuadIndices(newQuadCount);
|
//Bottom face
|
||||||
long offset = this.indexBuffer.upload(buffer);
|
MemoryUtil.memPutByte(ptr++, (byte) 0);
|
||||||
if (offset >= 1L<<31) {
|
MemoryUtil.memPutByte(ptr++, (byte) 1);
|
||||||
throw new IllegalStateException();
|
MemoryUtil.memPutByte(ptr++, (byte) 2);
|
||||||
}
|
MemoryUtil.memPutByte(ptr++, (byte) 3);
|
||||||
this.commonIndexBufferOffset = (int) offset;
|
MemoryUtil.memPutByte(ptr++, (byte) 2);
|
||||||
buffer.free();
|
MemoryUtil.memPutByte(ptr++, (byte) 1);
|
||||||
this.commonIndexQuadCount = newQuadCount;
|
|
||||||
}
|
//top face
|
||||||
return this.commonIndexBufferOffset * 6;
|
MemoryUtil.memPutByte(ptr++, (byte) 6);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 5);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 4);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 5);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 6);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 7);
|
||||||
|
|
||||||
|
//north face
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 0);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 4);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 1);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 5);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 1);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 4);
|
||||||
|
|
||||||
|
//south face
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 3);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 6);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 2);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 6);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 3);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 7);
|
||||||
|
|
||||||
|
//west face
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 2);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 4);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 0);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 4);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 2);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 6);
|
||||||
|
|
||||||
|
//east face
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 1);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 5);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 3);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 7);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 3);
|
||||||
|
MemoryUtil.memPutByte(ptr++, (byte) 5);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int id() {
|
public int id() {
|
||||||
return this.indexBuffer.id();
|
return this.indexBuffer.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,19 +115,20 @@ public class RenderGenerationService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wait for the ingest to finish
|
//Since this is just render data, dont care about any tasks needing to finish
|
||||||
while (this.taskCounter.availablePermits() != 0) {
|
|
||||||
Thread.onSpinWait();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Shutdown
|
|
||||||
this.running = false;
|
this.running = false;
|
||||||
this.taskCounter.release(1000);
|
this.taskCounter.release(1000);
|
||||||
|
|
||||||
//Wait for thread to join
|
//Wait for thread to join
|
||||||
try {
|
try {
|
||||||
for (var worker : this.workers) {
|
for (var worker : this.workers) {
|
||||||
worker.join();
|
worker.join();
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {throw new RuntimeException(e);}
|
} catch (InterruptedException e) {throw new RuntimeException(e);}
|
||||||
|
|
||||||
|
//Cleanup any remaining data
|
||||||
|
while (!this.taskQueue.isEmpty()) {
|
||||||
|
this.taskQueue.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package me.cortex.voxelmon.core.util;
|
|||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
public class IndexUtil {
|
public class IndexUtil {
|
||||||
public static MemoryBuffer generateQuadIndices(int quadCount) {
|
public static MemoryBuffer generateQuadIndicesShort(int quadCount) {
|
||||||
if ((quadCount*4) >= 1<<16) {
|
if ((quadCount*4) >= 1<<16) {
|
||||||
throw new IllegalArgumentException("Quad count to large");
|
throw new IllegalArgumentException("Quad count to large");
|
||||||
}
|
}
|
||||||
@@ -22,4 +22,19 @@ public class IndexUtil {
|
|||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MemoryBuffer generateQuadIndicesInt(int quadCount) {
|
||||||
|
MemoryBuffer buffer = new MemoryBuffer(quadCount * 6L * 2);
|
||||||
|
long ptr = buffer.address;
|
||||||
|
for(int i = 0; i < quadCount*4; i += 4) {
|
||||||
|
MemoryUtil.memPutInt(ptr + (0*4), i);
|
||||||
|
MemoryUtil.memPutInt(ptr + (1*4), (i + 1));
|
||||||
|
MemoryUtil.memPutInt(ptr + (2*4), (i + 2));
|
||||||
|
MemoryUtil.memPutInt(ptr + (3*4), (i + 1));
|
||||||
|
MemoryUtil.memPutInt(ptr + (4*4), (i + 3));
|
||||||
|
MemoryUtil.memPutInt(ptr + (5*4), (i + 2));
|
||||||
|
ptr += 6 * 4;
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,11 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
//Use an LMDB backend to store the world, use a local inmemory cache for lod sections
|
//Use an LMDB backend to store the world, use a local inmemory cache for lod sections
|
||||||
// automatically manages and invalidates sections of the world as needed
|
// automatically manages and invalidates sections of the world as needed
|
||||||
public class WorldEngine {
|
public class WorldEngine {
|
||||||
private static final int ACTIVE_CACHE_SIZE = 10;
|
|
||||||
|
|
||||||
public final StorageBackend storage;
|
public final StorageBackend storage;
|
||||||
private final Mapper mapper;
|
private final Mapper mapper;
|
||||||
private final ActiveSectionTracker sectionTracker;
|
private final ActiveSectionTracker sectionTracker;
|
||||||
public final VoxelIngestService ingestService = new VoxelIngestService(this);
|
public final VoxelIngestService ingestService;
|
||||||
public final SectionSavingService savingService;
|
public final SectionSavingService savingService;
|
||||||
private RenderTracker renderTracker;
|
private RenderTracker renderTracker;
|
||||||
|
|
||||||
@@ -42,6 +41,7 @@ public class WorldEngine {
|
|||||||
this.sectionTracker = new ActiveSectionTracker(maxMipLayers, this::unsafeLoadSection);
|
this.sectionTracker = new ActiveSectionTracker(maxMipLayers, this::unsafeLoadSection);
|
||||||
|
|
||||||
this.savingService = new SectionSavingService(this, savingServiceWorkers);
|
this.savingService = new SectionSavingService(this, savingServiceWorkers);
|
||||||
|
this.ingestService = new VoxelIngestService(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean unsafeLoadSection(WorldSection into) {
|
private boolean unsafeLoadSection(WorldSection into) {
|
||||||
@@ -69,7 +69,7 @@ public class WorldEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Marks a section as dirty, enqueuing it for saving and or render data rebuilding
|
//Marks a section as dirty, enqueuing it for saving and or render data rebuilding
|
||||||
private void markDirty(WorldSection section) {
|
public void markDirty(WorldSection section) {
|
||||||
this.renderTracker.sectionUpdated(section);
|
this.renderTracker.sectionUpdated(section);
|
||||||
//TODO: add an option for having synced saving, that is when call enqueueSave, that will instead, instantly
|
//TODO: add an option for having synced saving, that is when call enqueueSave, that will instead, instantly
|
||||||
// save to the db, this can be useful for just reducing the amount of thread pools in total
|
// save to the db, this can be useful for just reducing the amount of thread pools in total
|
||||||
|
|||||||
@@ -50,17 +50,21 @@ layout(binding = 3, std430) readonly restrict buffer SectionBuffer {
|
|||||||
SectionMeta sectionData[];
|
SectionMeta sectionData[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 4, std430) readonly restrict buffer StateBuffer {
|
|
||||||
State stateData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 5, std430) readonly restrict buffer BiomeBuffer {
|
|
||||||
Biome biomeData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef VISIBILITY_ACCESS
|
#ifndef VISIBILITY_ACCESS
|
||||||
#define VISIBILITY_ACCESS readonly
|
#define VISIBILITY_ACCESS readonly
|
||||||
#endif
|
#endif
|
||||||
layout(binding = 6, std430) VISIBILITY_ACCESS restrict buffer VisibilityBuffer {
|
layout(binding = 4, std430) VISIBILITY_ACCESS restrict buffer VisibilityBuffer {
|
||||||
uint visibilityData[];
|
uint visibilityData[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
layout(binding = 5, std430) readonly restrict buffer StateBuffer {
|
||||||
|
State stateData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 6, std430) readonly restrict buffer BiomeBuffer {
|
||||||
|
Biome biomeData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 7, std430) readonly restrict buffer LightingBuffer {
|
||||||
|
vec4 lightData[];
|
||||||
|
};
|
||||||
|
|||||||
@@ -34,12 +34,20 @@ void main() {
|
|||||||
uint detail = extractDetail(meta);
|
uint detail = extractDetail(meta);
|
||||||
ivec3 ipos = extractPosition(meta);
|
ivec3 ipos = extractPosition(meta);
|
||||||
|
|
||||||
//TODO: fixme; i dont think this is correct
|
|
||||||
vec3 cornerPos = vec3(((ipos<<detail)-baseSectionPos)<<5)-cameraSubPos;
|
vec3 cornerPos = vec3(((ipos<<detail)-baseSectionPos)<<5)-cameraSubPos;
|
||||||
|
|
||||||
|
|
||||||
bool shouldRender = testFrustum(frustum, cornerPos, cornerPos+vec3(1<<(detail+5)));
|
bool shouldRender = testFrustum(frustum, cornerPos, cornerPos+vec3(1<<(detail+5)));
|
||||||
|
|
||||||
|
//Check the occlusion data from last frame
|
||||||
|
if (visibilityData[gl_GlobalInvocationID.x] != frameId - 1) {
|
||||||
|
shouldRender = false;
|
||||||
|
}
|
||||||
|
//Clear the occlusion data (not strictly? needed? i think???)
|
||||||
|
//visibilityData[gl_GlobalInvocationID.x] = 0;
|
||||||
|
|
||||||
|
//TODO: need to make it check that only if it was also in the frustum last frame does it apply the visibilityData check!
|
||||||
|
|
||||||
//This prevents overflow of the relative position encoder
|
//This prevents overflow of the relative position encoder
|
||||||
if (shouldRender) {
|
if (shouldRender) {
|
||||||
shouldRender = !any(lessThan(ivec3(254), abs(ipos-(baseSectionPos>>detail))));
|
shouldRender = !any(lessThan(ivec3(254), abs(ipos-(baseSectionPos>>detail))));
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
#import <voxelmon:lod/gl46/bindings.glsl>
|
#import <voxelmon:lod/gl46/bindings.glsl>
|
||||||
flat in uint id;
|
flat in uint id;
|
||||||
flat in uint value;
|
flat in uint value;
|
||||||
|
//out vec4 colour;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
visibilityData[id] = value;
|
visibilityData[id] = value;
|
||||||
|
//colour = vec4(float(id&7)/7, float((id>>3)&7)/7, float((id>>6)&7)/7, 1);
|
||||||
}
|
}
|
||||||
@@ -8,18 +8,20 @@ flat out uint id;
|
|||||||
flat out uint value;
|
flat out uint value;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
SectionMeta section = sectionData[gl_VertexID>>3];
|
uint sid = gl_InstanceID;
|
||||||
|
|
||||||
|
SectionMeta section = sectionData[sid];
|
||||||
|
|
||||||
uint detail = extractDetail(section);
|
uint detail = extractDetail(section);
|
||||||
ivec3 ipos = extractPosition(section);
|
ivec3 ipos = extractPosition(section);
|
||||||
|
|
||||||
//Transform ipos with respect to the vertex corner
|
//Transform ipos with respect to the vertex corner
|
||||||
ipos += ivec3(gl_VertexID&1, (gl_VertexID>>1)&1, (gl_VertexID>>2)&1);
|
ipos += ivec3(gl_VertexID&1, (gl_VertexID>>2)&1, (gl_VertexID>>1)&1);
|
||||||
|
|
||||||
vec3 cornerPos = vec3(((ipos<<detail)-baseSectionPos)<<5);
|
vec3 cornerPos = vec3(((ipos<<detail)-baseSectionPos)<<5);
|
||||||
gl_Position = MVP * vec4(cornerPos,1);
|
gl_Position = MVP * vec4(cornerPos,1);
|
||||||
|
|
||||||
//Write to this id
|
//Write to this id
|
||||||
id = gl_VertexID>>3;
|
id = sid;
|
||||||
value = frameId;
|
value = frameId;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user