Culling
This commit is contained in:
@@ -23,7 +23,7 @@ public class DistanceTracker {
|
|||||||
private final int maxYSection;
|
private final int maxYSection;
|
||||||
private final int renderDistance;
|
private final int renderDistance;
|
||||||
|
|
||||||
public DistanceTracker(RenderTracker tracker, int[] lodRingScales, int renderDistance, int cacheDistance, int minY, int maxY) {
|
public DistanceTracker(RenderTracker tracker, int[] lodRingScales, int renderDistance, int minY, int maxY) {
|
||||||
this.loDRings = new TransitionRing2D[lodRingScales.length];
|
this.loDRings = new TransitionRing2D[lodRingScales.length];
|
||||||
this.cacheLoadRings = new TransitionRing2D[lodRingScales.length];
|
this.cacheLoadRings = new TransitionRing2D[lodRingScales.length];
|
||||||
this.cacheUnloadRings = new TransitionRing2D[lodRingScales.length];
|
this.cacheUnloadRings = new TransitionRing2D[lodRingScales.length];
|
||||||
@@ -72,34 +72,28 @@ public class DistanceTracker {
|
|||||||
// the issue is when to uncache these methods
|
// the issue is when to uncache these methods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this.cacheLoadRings[i] = new TransitionRing2D(5 + i, (scale << 1) + cacheDistance, (x, z) -> {
|
//TODO: FIX AND FINISH!!!
|
||||||
|
this.cacheLoadRings[i] = new TransitionRing2D(5 + i, (scale << 1) + 2, (x, z) -> {
|
||||||
//When entering a cache ring, trigger a mesh op and inject into cache
|
//When entering a cache ring, trigger a mesh op and inject into cache
|
||||||
for (int y = this.minYSection >> capRing; y <= this.maxYSection >> capRing; y++) {
|
for (int y = this.minYSection >> capRing; y <= this.maxYSection >> capRing; y++) {
|
||||||
this.tracker.addCache(capRing, x, y, z);
|
this.tracker.addCache(capRing, x, y, z);
|
||||||
}
|
}
|
||||||
}, (x, z) -> {
|
}, (x, z) -> {
|
||||||
int shift = capRing+1;
|
|
||||||
if (shift <= this.loDRings.length) {
|
|
||||||
for (int y = this.minYSection >> shift; y <= this.maxYSection >> shift; y++) {
|
|
||||||
this.tracker.removeCache(shift, x>>1, y, z>>1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.cacheUnloadRings[i] = new TransitionRing2D(5 + i, Math.max(1, (scale << 1) + cacheDistance), (x, z) -> {
|
|
||||||
int shift = capRing+1;
|
|
||||||
if (shift <= this.loDRings.length) {
|
|
||||||
for (int y = this.minYSection >> shift; y <= this.maxYSection >> shift; y++) {
|
|
||||||
this.tracker.addCache(shift, x>>1, y, z>>1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, (x, z) -> {
|
|
||||||
//When exiting the cache unload ring, tell the cache to dump whatever mesh it has cached and not add any mesh from that position
|
|
||||||
for (int y = this.minYSection >> capRing; y <= this.maxYSection >> capRing; y++) {
|
for (int y = this.minYSection >> capRing; y <= this.maxYSection >> capRing; y++) {
|
||||||
this.tracker.removeCache(capRing, x, y, z);
|
this.tracker.removeCache(capRing, x, y, z);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
this.cacheUnloadRings[i] = new TransitionRing2D(5 + i, Math.max(1, (scale << 1) - 2), (x, z) -> {
|
||||||
|
for (int y = this.minYSection >> capRing; y <= this.maxYSection >> capRing; y++) {
|
||||||
|
this.tracker.removeCache(capRing, x, y, z);
|
||||||
|
}
|
||||||
|
}, (x, z) -> {
|
||||||
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTerminatingRing) {
|
if (isTerminatingRing) {
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class VoxelCore {
|
|||||||
|
|
||||||
this.distanceTracker = new DistanceTracker(this.renderTracker, new int[]{q,q,q,q},
|
this.distanceTracker = new DistanceTracker(this.renderTracker, new int[]{q,q,q,q},
|
||||||
(VoxyConfig.CONFIG.renderDistance<0?VoxyConfig.CONFIG.renderDistance:((VoxyConfig.CONFIG.renderDistance+1)/2)),
|
(VoxyConfig.CONFIG.renderDistance<0?VoxyConfig.CONFIG.renderDistance:((VoxyConfig.CONFIG.renderDistance+1)/2)),
|
||||||
3, minY, maxY);
|
minY, maxY);
|
||||||
System.out.println("Distance tracker initialized");
|
System.out.println("Distance tracker initialized");
|
||||||
|
|
||||||
this.postProcessing = new PostProcessing();
|
this.postProcessing = new PostProcessing();
|
||||||
@@ -187,7 +187,11 @@ public class VoxelCore {
|
|||||||
var projection = computeProjectionMat();
|
var projection = computeProjectionMat();
|
||||||
//var projection = RenderSystem.getProjectionMatrix();//computeProjectionMat();
|
//var projection = RenderSystem.getProjectionMatrix();//computeProjectionMat();
|
||||||
var viewport = this.viewportSelector.getViewport();
|
var viewport = this.viewportSelector.getViewport();
|
||||||
viewport.setProjection(projection).setModelView(matrices.peek().getPositionMatrix()).setCamera(cameraX, cameraY, cameraZ);
|
viewport
|
||||||
|
.setProjection(projection)
|
||||||
|
.setModelView(matrices.peek().getPositionMatrix())
|
||||||
|
.setCamera(cameraX, cameraY, cameraZ)
|
||||||
|
.setScreenSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight);
|
||||||
|
|
||||||
int boundFB = GL11.glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING);
|
int boundFB = GL11.glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING);
|
||||||
this.postProcessing.setup(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight, boundFB);
|
this.postProcessing.setup(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight, boundFB);
|
||||||
|
|||||||
@@ -42,10 +42,6 @@ import static org.lwjgl.opengl.NVRepresentativeFragmentTest.GL_REPRESENTATIVE_FR
|
|||||||
// the shader can cull the verticies of any quad that has its index over the expected quuad count
|
// the shader can cull the verticies of any quad that has its index over the expected quuad count
|
||||||
// this could potentially result in a fair bit of memory savings (especially if used in normal mc terrain rendering)
|
// this could potentially result in a fair bit of memory savings (especially if used in normal mc terrain rendering)
|
||||||
public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46MeshletViewport, DefaultGeometryManager> {
|
public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46MeshletViewport, DefaultGeometryManager> {
|
||||||
private final Shader meshletGenerator = Shader.make()
|
|
||||||
.add(ShaderType.COMPUTE, "voxy:lod/gl46mesh/cmdgen.comp")
|
|
||||||
.compile();
|
|
||||||
|
|
||||||
private final Shader lodShader = Shader.make()
|
private final Shader lodShader = Shader.make()
|
||||||
.add(ShaderType.VERTEX, "voxy:lod/gl46mesh/quads.vert")
|
.add(ShaderType.VERTEX, "voxy:lod/gl46mesh/quads.vert")
|
||||||
.add(ShaderType.FRAGMENT, "voxy:lod/gl46mesh/quads.frag")
|
.add(ShaderType.FRAGMENT, "voxy:lod/gl46mesh/quads.frag")
|
||||||
@@ -56,17 +52,26 @@ public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46M
|
|||||||
.add(ShaderType.FRAGMENT, "voxy:lod/gl46mesh/cull.frag")
|
.add(ShaderType.FRAGMENT, "voxy:lod/gl46mesh/cull.frag")
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
|
private final Shader meshletGenerator = Shader.make()
|
||||||
|
.add(ShaderType.COMPUTE, "voxy:lod/gl46mesh/cmdgen.comp")
|
||||||
|
.compile();
|
||||||
|
|
||||||
|
private final Shader meshletCuller = Shader.make()
|
||||||
|
.add(ShaderType.COMPUTE, "voxy:lod/gl46mesh/meshletculler.comp")
|
||||||
|
.compile();
|
||||||
|
|
||||||
private final GlBuffer glDrawIndirect;
|
private final GlBuffer glDrawIndirect;
|
||||||
private final GlBuffer meshletBuffer;
|
private final GlBuffer meshletBuffer;
|
||||||
private final HiZBuffer hiZBuffer = new HiZBuffer();
|
private final HiZBuffer hiZBuffer = new HiZBuffer();
|
||||||
|
private final int hizSampler = glGenSamplers();
|
||||||
|
|
||||||
public Gl46MeshletsFarWorldRenderer(int geometrySize, int maxSections) {
|
public Gl46MeshletsFarWorldRenderer(int geometrySize, int maxSections) {
|
||||||
super(new DefaultGeometryManager(alignUp(geometrySize*8L, 8*32), maxSections, 8*32));
|
super(new DefaultGeometryManager(alignUp(geometrySize*8L, 8*32), maxSections, 8*32));
|
||||||
this.glDrawIndirect = new GlBuffer(4*5);
|
this.glDrawIndirect = new GlBuffer(4*(4+5));
|
||||||
this.meshletBuffer = new GlBuffer(4*1000000);//TODO: Make max meshlet count configurable, not just 1 million (even tho thats a max of 126 million quads per frame)
|
this.meshletBuffer = new GlBuffer(4*1000000);//TODO: Make max meshlet count configurable, not just 1 million (even tho thats a max of 126 million quads per frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void bindResources(Gl46MeshletViewport viewport, boolean bindToDrawIndirect) {
|
protected void bindResources(Gl46MeshletViewport viewport, boolean bindToDrawIndirect, boolean bindToDispatchIndirect, boolean bindHiz) {
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id);
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.geometry.geometryId());
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.geometry.geometryId());
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bindToDrawIndirect?0:this.glDrawIndirect.id);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bindToDrawIndirect?0:this.glDrawIndirect.id);
|
||||||
@@ -77,11 +82,18 @@ public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46M
|
|||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, this.models.getColourBufferId());
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, this.models.getColourBufferId());
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, this.lightDataBuffer.id);//Lighting LUT
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, this.lightDataBuffer.id);//Lighting LUT
|
||||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, bindToDrawIndirect?this.glDrawIndirect.id:0);
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, bindToDrawIndirect?this.glDrawIndirect.id:0);
|
||||||
|
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, bindToDispatchIndirect?this.glDrawIndirect.id:0);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE_BYTE.id());
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE_BYTE.id());
|
||||||
|
|
||||||
//Bind the texture atlas
|
if (!bindHiz) {
|
||||||
glBindSampler(0, this.models.getSamplerId());
|
//Bind the texture atlas
|
||||||
glBindTextureUnit(0, this.models.getTextureId());
|
glBindSampler(0, this.models.getSamplerId());
|
||||||
|
glBindTextureUnit(0, this.models.getTextureId());
|
||||||
|
} else {
|
||||||
|
//Bind the hiz buffer
|
||||||
|
glBindSampler(0, this.hizSampler);
|
||||||
|
glBindTextureUnit(0, this.hiZBuffer.getHizTextureId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUniformBuffer(Gl46MeshletViewport viewport) {
|
private void updateUniformBuffer(Gl46MeshletViewport viewport) {
|
||||||
@@ -101,6 +113,8 @@ public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46M
|
|||||||
}
|
}
|
||||||
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
||||||
MemoryUtil.memPutInt(ptr, viewport.frameId++); ptr += 4;
|
MemoryUtil.memPutInt(ptr, viewport.frameId++); ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, viewport.width); ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, viewport.height); ptr += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -124,24 +138,18 @@ public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46M
|
|||||||
UploadStream.INSTANCE.commit();
|
UploadStream.INSTANCE.commit();
|
||||||
glBindVertexArray(AbstractFarWorldRenderer.STATIC_VAO);
|
glBindVertexArray(AbstractFarWorldRenderer.STATIC_VAO);
|
||||||
|
|
||||||
nglClearNamedBufferSubData(this.glDrawIndirect.id, GL_R32UI, 4, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
|
nglClearNamedBufferSubData(this.glDrawIndirect.id, GL_R32UI, 0, 4*4, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
this.meshletGenerator.bind();
|
|
||||||
this.bindResources(viewport, false);
|
|
||||||
glDispatchCompute((this.geometry.getSectionCount()+63)/64, 1, 1);
|
|
||||||
|
|
||||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT);
|
|
||||||
|
|
||||||
this.lodShader.bind();
|
this.lodShader.bind();
|
||||||
this.bindResources(viewport, true);
|
this.bindResources(viewport, true, false, false);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_BYTE, 0);
|
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_BYTE, 4*4);
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
|
glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
|
||||||
|
|
||||||
this.cullShader.bind();
|
this.cullShader.bind();
|
||||||
this.bindResources(viewport, false);
|
this.bindResources(viewport, false, false, false);
|
||||||
glDepthMask(false);
|
glDepthMask(false);
|
||||||
glColorMask(false, false, false, false);
|
glColorMask(false, false, false, false);
|
||||||
glDrawElementsInstanced(GL_TRIANGLES, 6 * 2 * 3, GL_UNSIGNED_BYTE, (1 << 8) * 6, this.geometry.getSectionCount());
|
glDrawElementsInstanced(GL_TRIANGLES, 6 * 2 * 3, GL_UNSIGNED_BYTE, (1 << 8) * 6, this.geometry.getSectionCount());
|
||||||
@@ -150,12 +158,20 @@ public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46M
|
|||||||
|
|
||||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
|
|
||||||
|
this.meshletGenerator.bind();
|
||||||
|
this.bindResources(viewport, false, false, false);
|
||||||
|
glDispatchCompute((this.geometry.getSectionCount()+63)/64, 1, 1);
|
||||||
|
|
||||||
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT);
|
||||||
|
|
||||||
var i = new int[1];
|
var i = new int[1];
|
||||||
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, i);
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, i);
|
||||||
this.hiZBuffer.buildMipChain(i[0], MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight);
|
this.hiZBuffer.buildMipChain(i[0], MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight);
|
||||||
|
|
||||||
|
this.meshletCuller.bind();
|
||||||
|
this.bindResources(viewport, false, true, true);
|
||||||
|
glDispatchComputeIndirect(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
@@ -178,14 +194,16 @@ public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer<Gl46M
|
|||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
super.shutdown();
|
super.shutdown();
|
||||||
this.meshletGenerator.free();
|
|
||||||
this.lodShader.free();
|
this.lodShader.free();
|
||||||
this.cullShader.free();
|
this.cullShader.free();
|
||||||
|
this.meshletGenerator.free();
|
||||||
|
this.meshletCuller.free();
|
||||||
|
|
||||||
this.glDrawIndirect.free();
|
this.glDrawIndirect.free();
|
||||||
this.meshletBuffer.free();
|
this.meshletBuffer.free();
|
||||||
|
|
||||||
this.hiZBuffer.free();
|
this.hiZBuffer.free();
|
||||||
|
glDeleteSamplers(this.hizSampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long alignUp(long n, long alignment) {
|
public static long alignUp(long n, long alignment) {
|
||||||
|
|||||||
@@ -95,4 +95,8 @@ public class HiZBuffer {
|
|||||||
this.texture = null;
|
this.texture = null;
|
||||||
glDeleteSamplers(this.sampler);
|
glDeleteSamplers(this.sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getHizTextureId() {
|
||||||
|
return this.texture.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import org.joml.Matrix4f;
|
|||||||
|
|
||||||
public abstract class Viewport <A extends Viewport<A>> {
|
public abstract class Viewport <A extends Viewport<A>> {
|
||||||
private final AbstractFarWorldRenderer renderer;
|
private final AbstractFarWorldRenderer renderer;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
int frameId;
|
int frameId;
|
||||||
Matrix4f projection;
|
Matrix4f projection;
|
||||||
Matrix4f modelView;
|
Matrix4f modelView;
|
||||||
@@ -39,4 +40,10 @@ public abstract class Viewport <A extends Viewport<A>> {
|
|||||||
this.cameraZ = z;
|
this.cameraZ = z;
|
||||||
return (A) this;
|
return (A) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public A setScreenSize(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
return (A) this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,25 @@ import me.cortex.voxy.client.core.util.Mesher2D;
|
|||||||
|
|
||||||
public class QuadEncoder {
|
public class QuadEncoder {
|
||||||
|
|
||||||
|
public static int getX(long data) {
|
||||||
|
return (int) ((data>>21)&0b11111);
|
||||||
|
}
|
||||||
|
public static int getY(long data) {
|
||||||
|
return (int) ((data>>16)&0b11111);
|
||||||
|
}
|
||||||
|
public static int getZ(long data) {
|
||||||
|
return (int) ((data>>11)&0b11111);
|
||||||
|
}
|
||||||
|
public static int getW(long data) {
|
||||||
|
return (int) ((data>>3)&0b1111)+1;
|
||||||
|
}
|
||||||
|
public static int getH(long data) {
|
||||||
|
return (int) ((data>>7)&0b1111)+1;
|
||||||
|
}
|
||||||
|
public static int getFace(long data) {
|
||||||
|
return (int) (data&0b111);
|
||||||
|
}
|
||||||
|
|
||||||
//Note: the encodedMeshedData is from the Mesher2D
|
//Note: the encodedMeshedData is from the Mesher2D
|
||||||
public static int encodePosition(int face, int otherAxis, int encodedMeshedData) {
|
public static int encodePosition(int face, int otherAxis, int encodedMeshedData) {
|
||||||
if (false&&(Mesher2D.getW(encodedMeshedData) > 16 || Mesher2D.getH(encodedMeshedData) > 16)) {
|
if (false&&(Mesher2D.getW(encodedMeshedData) > 16 || Mesher2D.getH(encodedMeshedData) > 16)) {
|
||||||
|
|||||||
@@ -118,24 +118,55 @@ public class RenderDataFactory {
|
|||||||
|
|
||||||
//Ordering is: translucent, double sided quads, directional quads
|
//Ordering is: translucent, double sided quads, directional quads
|
||||||
offsets[0] = meshlet;
|
offsets[0] = meshlet;
|
||||||
|
int mix = 32, miy = 32, miz = 32, max = 0, may = 0, maz = 0;
|
||||||
for (long data : this.translucentQuadCollector) {
|
for (long data : this.translucentQuadCollector) {
|
||||||
if (innerQuadCount == 0) {
|
if (innerQuadCount == 0) {
|
||||||
//Write out meshlet header
|
//Write out meshlet header
|
||||||
|
|
||||||
//Write out the section position
|
//Write out the section position
|
||||||
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2), key);
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2), key);
|
||||||
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, 0);
|
|
||||||
}
|
}
|
||||||
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + (2 + innerQuadCount++) * 8L, data);
|
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + (2 + innerQuadCount++) * 8L, data);
|
||||||
|
int x = QuadEncoder.getX(data), y = QuadEncoder.getY(data), z = QuadEncoder.getZ(data), f = QuadEncoder.getFace(data);
|
||||||
|
mix = Math.min(x, mix); miy = Math.min(y, miy); miz = Math.min(z, miz);
|
||||||
|
if ((f>>1)==0) {
|
||||||
|
max = Math.max(x + QuadEncoder.getW(data), max);
|
||||||
|
may = Math.max(y, may);
|
||||||
|
maz = Math.max(z + QuadEncoder.getH(data), maz);
|
||||||
|
} else if ((f>>1)==1) {
|
||||||
|
max = Math.max(x + QuadEncoder.getW(data), max);
|
||||||
|
may = Math.max(y + QuadEncoder.getH(data), may);
|
||||||
|
maz = Math.max(z, maz);
|
||||||
|
} else {
|
||||||
|
max = Math.max(x, max);
|
||||||
|
may = Math.max(y + QuadEncoder.getW(data), may);
|
||||||
|
maz = Math.max(z + QuadEncoder.getH(data), maz);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (innerQuadCount == QUADS_PER_MESHLET) {
|
if (innerQuadCount == QUADS_PER_MESHLET) {
|
||||||
|
//Write out the meshlet size data
|
||||||
|
long sizeData = ((long)mix)|(((long)miy)<<8)|(((long)miz)<<16)|
|
||||||
|
(((long)max)<<24)|(((long)may)<<32)|(((long)maz)<<40);
|
||||||
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, sizeData);
|
||||||
|
|
||||||
|
|
||||||
innerQuadCount = 0;
|
innerQuadCount = 0;
|
||||||
meshlet++;
|
meshlet++;
|
||||||
|
mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (innerQuadCount != 0) {
|
if (innerQuadCount != 0) {
|
||||||
|
//Write out the meshlet size data
|
||||||
|
long sizeData = ((long)mix)|(((long)miy)<<8)|(((long)miz)<<16)|
|
||||||
|
(((long)max)<<24)|(((long)may)<<32)|(((long)maz)<<40);
|
||||||
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, sizeData);
|
||||||
|
|
||||||
meshlet++;
|
meshlet++;
|
||||||
innerQuadCount = 0;
|
innerQuadCount = 0;
|
||||||
|
mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
offsets[1] = meshlet;
|
offsets[1] = meshlet;
|
||||||
@@ -145,18 +176,46 @@ public class RenderDataFactory {
|
|||||||
|
|
||||||
//Write out the section position
|
//Write out the section position
|
||||||
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2), key);
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2), key);
|
||||||
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, 0);
|
|
||||||
}
|
}
|
||||||
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + (2 + innerQuadCount++) * 8L, data);
|
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + (2 + innerQuadCount++) * 8L, data);
|
||||||
|
int x = QuadEncoder.getX(data), y = QuadEncoder.getY(data), z = QuadEncoder.getZ(data), f = QuadEncoder.getFace(data);
|
||||||
|
mix = Math.min(x, mix); miy = Math.min(y, miy); miz = Math.min(z, miz);
|
||||||
|
if ((f>>1)==0) {
|
||||||
|
max = Math.max(x + QuadEncoder.getW(data), max);
|
||||||
|
may = Math.max(y, may);
|
||||||
|
maz = Math.max(z + QuadEncoder.getH(data), maz);
|
||||||
|
} else if ((f>>1)==1) {
|
||||||
|
max = Math.max(x + QuadEncoder.getW(data), max);
|
||||||
|
may = Math.max(y + QuadEncoder.getH(data), may);
|
||||||
|
maz = Math.max(z, maz);
|
||||||
|
} else {
|
||||||
|
max = Math.max(x, max);
|
||||||
|
may = Math.max(y + QuadEncoder.getW(data), may);
|
||||||
|
maz = Math.max(z + QuadEncoder.getH(data), maz);
|
||||||
|
}
|
||||||
if (innerQuadCount == QUADS_PER_MESHLET) {
|
if (innerQuadCount == QUADS_PER_MESHLET) {
|
||||||
|
//Write out the meshlet size data
|
||||||
|
long sizeData = ((long)mix)|(((long)miy)<<8)|(((long)miz)<<16)|
|
||||||
|
(((long)max)<<24)|(((long)may)<<32)|(((long)maz)<<40);
|
||||||
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, sizeData);
|
||||||
|
|
||||||
|
|
||||||
innerQuadCount = 0;
|
innerQuadCount = 0;
|
||||||
meshlet++;
|
meshlet++;
|
||||||
|
mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (innerQuadCount != 0) {
|
if (innerQuadCount != 0) {
|
||||||
|
//Write out the meshlet size data
|
||||||
|
long sizeData = ((long)mix)|(((long)miy)<<8)|(((long)miz)<<16)|
|
||||||
|
(((long)max)<<24)|(((long)may)<<32)|(((long)maz)<<40);
|
||||||
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, sizeData);
|
||||||
|
|
||||||
|
|
||||||
meshlet++;
|
meshlet++;
|
||||||
innerQuadCount = 0;
|
innerQuadCount = 0;
|
||||||
|
mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int face = 0; face < 6; face++) {
|
for (int face = 0; face < 6; face++) {
|
||||||
@@ -167,18 +226,46 @@ public class RenderDataFactory {
|
|||||||
|
|
||||||
//Write out the section position
|
//Write out the section position
|
||||||
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2), key);
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2), key);
|
||||||
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, 0);
|
|
||||||
}
|
}
|
||||||
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + (2 + innerQuadCount++) * 8L, data);
|
MemoryUtil.memPutLong(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + (2 + innerQuadCount++) * 8L, data);
|
||||||
|
int x = QuadEncoder.getX(data), y = QuadEncoder.getY(data), z = QuadEncoder.getZ(data), f = QuadEncoder.getFace(data);
|
||||||
|
mix = Math.min(x, mix); miy = Math.min(y, miy); miz = Math.min(z, miz);
|
||||||
|
if ((f>>1)==0) {
|
||||||
|
max = Math.max(x + QuadEncoder.getW(data), max);
|
||||||
|
may = Math.max(y, may);
|
||||||
|
maz = Math.max(z + QuadEncoder.getH(data), maz);
|
||||||
|
} else if ((f>>1)==1) {
|
||||||
|
max = Math.max(x + QuadEncoder.getW(data), max);
|
||||||
|
may = Math.max(y + QuadEncoder.getH(data), may);
|
||||||
|
maz = Math.max(z, maz);
|
||||||
|
} else {
|
||||||
|
max = Math.max(x, max);
|
||||||
|
may = Math.max(y + QuadEncoder.getW(data), may);
|
||||||
|
maz = Math.max(z + QuadEncoder.getH(data), maz);
|
||||||
|
}
|
||||||
if (innerQuadCount == QUADS_PER_MESHLET) {
|
if (innerQuadCount == QUADS_PER_MESHLET) {
|
||||||
|
//Write out the meshlet size data
|
||||||
|
long sizeData = ((long)mix)|(((long)miy)<<8)|(((long)miz)<<16)|
|
||||||
|
(((long)max)<<24)|(((long)may)<<32)|(((long)maz)<<40);
|
||||||
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, sizeData);
|
||||||
|
|
||||||
|
|
||||||
innerQuadCount = 0;
|
innerQuadCount = 0;
|
||||||
meshlet++;
|
meshlet++;
|
||||||
|
mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (innerQuadCount != 0) {
|
if (innerQuadCount != 0) {
|
||||||
|
//Write out the meshlet size data
|
||||||
|
long sizeData = ((long)mix)|(((long)miy)<<8)|(((long)miz)<<16)|
|
||||||
|
(((long)max)<<24)|(((long)may)<<32)|(((long)maz)<<40);
|
||||||
|
writePos(ptr + meshlet * 8L * (QUADS_PER_MESHLET+2) + 8, sizeData);
|
||||||
|
|
||||||
|
|
||||||
meshlet++;
|
meshlet++;
|
||||||
innerQuadCount = 0;
|
innerQuadCount = 0;
|
||||||
|
mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ layout(binding = 0, std140) uniform SceneUniform {
|
|||||||
Frustum frustum;
|
Frustum frustum;
|
||||||
vec3 cameraSubPos;
|
vec3 cameraSubPos;
|
||||||
uint frameId;
|
uint frameId;
|
||||||
|
uvec2 screensize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlockModel {
|
struct BlockModel {
|
||||||
@@ -38,8 +39,17 @@ struct DrawCommand {
|
|||||||
int baseVertex;
|
int baseVertex;
|
||||||
uint baseInstance;
|
uint baseInstance;
|
||||||
};
|
};
|
||||||
|
struct DispatchIndirect {
|
||||||
|
uint x;
|
||||||
|
uint y;
|
||||||
|
uint z;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef BIND_SAMPLER_AS_HIZ
|
||||||
|
layout(binding = 0) uniform sampler2D hizSampler;
|
||||||
|
#else
|
||||||
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef Quad
|
#ifndef Quad
|
||||||
#define Quad ivec2
|
#define Quad ivec2
|
||||||
@@ -49,13 +59,12 @@ layout(binding = 1, std430) readonly restrict buffer GeometryBuffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 2, std430) restrict buffer DrawBuffer {
|
layout(binding = 2, std430) restrict buffer DrawBuffer {
|
||||||
|
DispatchIndirect dispatchCmd;
|
||||||
|
uint fullMeshletCount;
|
||||||
DrawCommand drawCmd;
|
DrawCommand drawCmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef MESHLET_ACCESS
|
layout(binding = 3, std430) restrict buffer MeshletListData {
|
||||||
#define MESHLET_ACCESS readonly writeonly
|
|
||||||
#endif
|
|
||||||
layout(binding = 3, std430) MESHLET_ACCESS restrict buffer MeshletListData {
|
|
||||||
uint meshlets[];
|
uint meshlets[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
#import <voxy:lod/quad_format.glsl>
|
#import <voxy:lod/quad_format.glsl>
|
||||||
#import <voxy:lod/gl46mesh/bindings.glsl>
|
#import <voxy:lod/gl46mesh/bindings.glsl>
|
||||||
#import <voxy:lod/section.glsl>
|
#import <voxy:lod/section.glsl>
|
||||||
#define extractMeshletStart extractQuadStart
|
#import <voxy:lod/gl46mesh/meshlet.glsl>
|
||||||
|
|
||||||
layout(local_size_x = 64) in;
|
layout(local_size_x = 64) in;
|
||||||
#define QUADS_PER_MESHLET 30
|
|
||||||
|
|
||||||
void emitMeshlets(inout uint mli, inout uint meshletPtr, uint mskedCnt, uint cnt) {
|
void emitMeshlets(inout uint mli, inout uint meshletPtr, uint mskedCnt, uint cnt) {
|
||||||
for (;mskedCnt != 0; mskedCnt--,mli++) {
|
for (;mskedCnt != 0; mskedCnt--,mli++) {
|
||||||
@@ -17,19 +17,19 @@ void emitMeshlets(inout uint mli, inout uint meshletPtr, uint mskedCnt, uint cnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
//Clear here as it stops the need to dispatch a glClearData instruction
|
||||||
if (gl_GlobalInvocationID.x == 0) {
|
if (gl_GlobalInvocationID.x == 0) {
|
||||||
//Setup the remaining state of the drawElementsIndirect command
|
drawCmd.instanceCount = 0;
|
||||||
drawCmd.count = QUADS_PER_MESHLET*6;
|
dispatchCmd.y = 1;
|
||||||
drawCmd.firstIndex = 0;
|
dispatchCmd.z = 1;
|
||||||
drawCmd.baseVertex = 0;
|
|
||||||
drawCmd.baseInstance = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gl_GlobalInvocationID.x >= sectionCount) {
|
if (gl_GlobalInvocationID.x >= sectionCount) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check the occlusion data from last frame
|
//Check the occlusion data from last frame
|
||||||
bool shouldRender = visibilityData[gl_GlobalInvocationID.x] == frameId - 1;
|
bool shouldRender = visibilityData[gl_GlobalInvocationID.x] == frameId;
|
||||||
if (shouldRender) {
|
if (shouldRender) {
|
||||||
SectionMeta meta = sectionData[gl_GlobalInvocationID.x];
|
SectionMeta meta = sectionData[gl_GlobalInvocationID.x];
|
||||||
uint detail = extractDetail(meta);
|
uint detail = extractDetail(meta);
|
||||||
@@ -46,7 +46,12 @@ void main() {
|
|||||||
uint e = ((meta.cntD>>16)&0xFFFF) * uint(relative.x<1 );
|
uint e = ((meta.cntD>>16)&0xFFFF) * uint(relative.x<1 );
|
||||||
uint total = a + u + d + s + n + w + e;
|
uint total = a + u + d + s + n + w + e;
|
||||||
|
|
||||||
uint mli = atomicAdd(drawCmd.instanceCount, total);//meshletListIndex
|
uint mli = atomicAdd(fullMeshletCount, total);//meshletListIndex
|
||||||
|
//Need to increment the glDispatchComputeIndirect with respect to the workgroup
|
||||||
|
uint addWorkAmount = ((mli+total)>>7)-(mli>>7);//the >>7 is cause the workgroup size is 128
|
||||||
|
addWorkAmount += uint(mli==0); //If we where the first to add to the meshlet counter then we need to add an extra dispatch
|
||||||
|
// to account for trailing data
|
||||||
|
atomicAdd(dispatchCmd.x, addWorkAmount);
|
||||||
|
|
||||||
uint meshletPtr = extractMeshletStart(meta) + (meta.cntA&0xFFFF);
|
uint meshletPtr = extractMeshletStart(meta) + (meta.cntA&0xFFFF);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#define QUADS_PER_MESHLET 30
|
||||||
|
|
||||||
|
#define extractMeshletStart extractQuadStart
|
||||||
|
#define PosHeader Quad
|
||||||
|
#define AABBHeader Quad
|
||||||
|
|
||||||
|
//There are 16 bytes of metadata at the start of the meshlet
|
||||||
|
#define MESHLET_SIZE (QUADS_PER_MESHLET+2)
|
||||||
|
|
||||||
|
#ifdef GL_ARB_gpu_shader_int64
|
||||||
|
ivec3 extractPosition(PosHeader pos64) {
|
||||||
|
//((long)lvl<<60)|((long)(y&0xFF)<<52)|((long)(z&((1<<24)-1))<<28)|((long)(x&((1<<24)-1))<<4);
|
||||||
|
//return ivec3((pos64<<4)&uint64_t(0xFFFFFFFF),(pos64>>28)&uint64_t(0xFFFFFFFF),(pos64>>24)&uint64_t(0xFFFFFFFF))>>ivec3(8,24,8);
|
||||||
|
return (ivec3(int(pos64>>4)&((1<<24)-1), int(pos64>>52)&0xFF, int(pos64>>28)&((1<<24)-1))<<ivec3(8,24,8))>>ivec3(8,24,8);
|
||||||
|
}
|
||||||
|
uint extractDetail(PosHeader pos64) {
|
||||||
|
return uint(pos64>>60);
|
||||||
|
}
|
||||||
|
uvec3 extractMin(AABBHeader aabb) {
|
||||||
|
return uvec3(uint(aabb&0xFF),uint((aabb>>8)&0xFF),uint((aabb>>16)&0xFF));
|
||||||
|
}
|
||||||
|
uvec3 extractMax(AABBHeader aabb) {
|
||||||
|
return uvec3(uint((aabb>>24)&0xFF),uint((aabb>>32)&0xFF),uint((aabb>>40)&0xFF));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ivec3 extractPosition(PosHeader pos) {
|
||||||
|
int y = ((int(pos.x)<<4)>>24);
|
||||||
|
int x = (int(pos.y)<<4)>>8;
|
||||||
|
int z = int((pos.x&((1<<20)-1))<<4);
|
||||||
|
z |= int(pos.y>>28)&0xF;
|
||||||
|
z <<= 8;
|
||||||
|
z >>= 8;
|
||||||
|
return ivec3(x,y,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint extractDetail(PosHeader pos) {
|
||||||
|
return uint(pos.x)>>28;
|
||||||
|
}
|
||||||
|
|
||||||
|
uvec3 extractMin(AABBHeader aabb) {
|
||||||
|
return uvec3(aabb.x&0xFF,(aabb.x>>8)&0xFF,(aabb.x>>16)&0xFF);
|
||||||
|
}
|
||||||
|
uvec3 extractMax(AABBHeader aabb) {
|
||||||
|
return uvec3((aabb.x>>24)&0xFF,aabb.y&0xFF,(aabb.y>>8)&0xFF);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#version 450
|
||||||
|
#extension GL_ARB_gpu_shader_int64 : enable
|
||||||
|
|
||||||
|
#define MESHLET_ACCESS
|
||||||
|
#define BIND_SAMPLER_AS_HIZ
|
||||||
|
#import <voxy:lod/quad_format.glsl>
|
||||||
|
#import <voxy:lod/gl46mesh/bindings.glsl>
|
||||||
|
#import <voxy:lod/section.glsl>
|
||||||
|
#import <voxy:lod/gl46mesh/meshlet.glsl>
|
||||||
|
layout(local_size_x=128) in;
|
||||||
|
|
||||||
|
vec3 proj(vec3 pos) {
|
||||||
|
vec4 t = MVP * vec4(vec3(pos),1);
|
||||||
|
return t.xyz/t.w;
|
||||||
|
}
|
||||||
|
bool testHiZ(PosHeader secPos, AABBHeader aabb) {
|
||||||
|
ivec3 section = extractPosition(secPos);
|
||||||
|
uint detail = extractDetail(secPos);
|
||||||
|
ivec3 pos = (((section<<detail)-baseSectionPos)<<5);
|
||||||
|
uvec3 cmin = extractMin(aabb)*(1<<detail);
|
||||||
|
uvec3 cmax = extractMax(aabb)*(1<<detail);
|
||||||
|
|
||||||
|
vec3 minBB = proj(pos);
|
||||||
|
vec3 maxBB = minBB;
|
||||||
|
for (int i = 1; i < 8; i++) {
|
||||||
|
vec3 point = proj(pos+mix(cmin, cmax, bvec3((i&1)!=0,(i&2)!=0,(i&4)!=0)));
|
||||||
|
minBB = min(minBB, point);
|
||||||
|
maxBB = max(maxBB, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
minBB = minBB*0.5+0.5;
|
||||||
|
maxBB = maxBB*0.5+0.5;
|
||||||
|
|
||||||
|
vec2 size = (maxBB.xy - minBB.xy) * vec2(screensize);
|
||||||
|
float miplevel = ceil(log2(max(size.x, size.y)/2));//NOTE: the /2 is cause the mipmaps dont include bottom level depth
|
||||||
|
|
||||||
|
float a = textureLod(hizSampler,minBB.xy,miplevel).r;
|
||||||
|
float b = textureLod(hizSampler,vec2(minBB.x,maxBB.y),miplevel).r;
|
||||||
|
float c = textureLod(hizSampler,maxBB.xy,miplevel).r;
|
||||||
|
float d = textureLod(hizSampler,vec2(maxBB.x,minBB.y),miplevel).r;
|
||||||
|
float depth = max(max(a,b),max(c,d));
|
||||||
|
|
||||||
|
return minBB.z <= depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if (gl_GlobalInvocationID.x >= fullMeshletCount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gl_GlobalInvocationID.x == 0) {
|
||||||
|
//Setup the state of the drawElementsIndirect command, instanceCount is cleared externally
|
||||||
|
drawCmd.count = QUADS_PER_MESHLET*6;
|
||||||
|
drawCmd.firstIndex = 0;
|
||||||
|
drawCmd.baseVertex = 0;
|
||||||
|
drawCmd.baseInstance = fullMeshletCount;//Start at the begining of the newly emitted meshlet array
|
||||||
|
}
|
||||||
|
uint meshletId = meshlets[gl_GlobalInvocationID.x];
|
||||||
|
PosHeader pos = geometryPool[meshletId*MESHLET_SIZE];
|
||||||
|
AABBHeader aabb = geometryPool[meshletId*MESHLET_SIZE+1];
|
||||||
|
|
||||||
|
if (true||testHiZ(pos, aabb)) {//If didnt cull, insert it back into the stream
|
||||||
|
meshlets[atomicAdd(drawCmd.instanceCount, 1)+fullMeshletCount] = meshletId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +1,10 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
#extension GL_ARB_gpu_shader_int64 : enable
|
||||||
#define QUADS_PER_MESHLET 30
|
|
||||||
|
|
||||||
#define MESHLET_ACCESS readonly
|
|
||||||
//There are 16 bytes of metadata at the start of the meshlet
|
|
||||||
#define MESHLET_SIZE (QUADS_PER_MESHLET+2)
|
|
||||||
#import <voxy:lod/quad_format.glsl>
|
#import <voxy:lod/quad_format.glsl>
|
||||||
#import <voxy:lod/gl46mesh/bindings.glsl>
|
#import <voxy:lod/gl46mesh/bindings.glsl>
|
||||||
#import <voxy:lod/block_model.glsl>
|
#import <voxy:lod/block_model.glsl>
|
||||||
#define PosHeader Quad
|
#import <voxy:lod/gl46mesh/meshlet.glsl>
|
||||||
|
|
||||||
|
|
||||||
#ifdef GL_ARB_gpu_shader_int64
|
|
||||||
ivec3 extractPosition(PosHeader pos64) {
|
|
||||||
//((long)lvl<<60)|((long)(y&0xFF)<<52)|((long)(z&((1<<24)-1))<<28)|((long)(x&((1<<24)-1))<<4);
|
|
||||||
//return ivec3((pos64<<4)&uint64_t(0xFFFFFFFF),(pos64>>28)&uint64_t(0xFFFFFFFF),(pos64>>24)&uint64_t(0xFFFFFFFF))>>ivec3(8,24,8);
|
|
||||||
return (ivec3(int(pos64>>4)&((1<<24)-1), int(pos64>>52)&0xFF, int(pos64>>28)&((1<<24)-1))<<ivec3(8,24,8))>>ivec3(8,24,8);
|
|
||||||
}
|
|
||||||
uint extractDetail(PosHeader pos64) {
|
|
||||||
return uint(pos64>>60);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ivec3 extractPosition(PosHeader pos) {
|
|
||||||
int y = ((int(pos.x)<<4)>>24);
|
|
||||||
int x = (int(pos.y)<<4)>>8;
|
|
||||||
int z = int((pos.x&((1<<20)-1))<<4);
|
|
||||||
z |= int(pos.y>>28)&0xF;
|
|
||||||
z <<= 8;
|
|
||||||
z >>= 8;
|
|
||||||
return ivec3(x,y,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint extractDetail(PosHeader pos) {
|
|
||||||
return uint(pos.x)>>28;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
layout(location = 6) out flat uint meshlet;
|
layout(location = 6) out flat uint meshlet;
|
||||||
PosHeader meshletPosition;
|
PosHeader meshletPosition;
|
||||||
|
|||||||
Reference in New Issue
Block a user