From 52baa303dcdbc00e8e3f62d653b36c7c12b4937a Mon Sep 17 00:00:00 2001 From: mcrcortex <{ID}+{username}@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:22:11 +1000 Subject: [PATCH] Culling --- .../voxy/client/core/DistanceTracker.java | 32 +++---- .../me/cortex/voxy/client/core/VoxelCore.java | 8 +- .../Gl46MeshletsFarWorldRenderer.java | 58 ++++++++---- .../voxy/client/core/rendering/HiZBuffer.java | 4 + .../voxy/client/core/rendering/Viewport.java | 9 +- .../core/rendering/building/QuadEncoder.java | 19 ++++ .../rendering/building/RenderDataFactory.java | 93 ++++++++++++++++++- .../voxy/shaders/lod/gl46mesh/bindings.glsl | 17 +++- .../voxy/shaders/lod/gl46mesh/cmdgen.comp | 23 +++-- .../voxy/shaders/lod/gl46mesh/meshlet.glsl | 46 +++++++++ .../shaders/lod/gl46mesh/meshletculler.comp | 65 +++++++++++++ .../voxy/shaders/lod/gl46mesh/quads.vert | 32 +------ 12 files changed, 317 insertions(+), 89 deletions(-) create mode 100644 src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshlet.glsl create mode 100644 src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshletculler.comp diff --git a/src/main/java/me/cortex/voxy/client/core/DistanceTracker.java b/src/main/java/me/cortex/voxy/client/core/DistanceTracker.java index 08c3566c..1cc1767e 100644 --- a/src/main/java/me/cortex/voxy/client/core/DistanceTracker.java +++ b/src/main/java/me/cortex/voxy/client/core/DistanceTracker.java @@ -23,7 +23,7 @@ public class DistanceTracker { private final int maxYSection; 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.cacheLoadRings = 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 + + /* - 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 for (int y = this.minYSection >> capRing; y <= this.maxYSection >> capRing; y++) { this.tracker.addCache(capRing, x, y, 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++) { 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) { diff --git a/src/main/java/me/cortex/voxy/client/core/VoxelCore.java b/src/main/java/me/cortex/voxy/client/core/VoxelCore.java index 7a896f9f..2d442bff 100644 --- a/src/main/java/me/cortex/voxy/client/core/VoxelCore.java +++ b/src/main/java/me/cortex/voxy/client/core/VoxelCore.java @@ -104,7 +104,7 @@ public class VoxelCore { this.distanceTracker = new DistanceTracker(this.renderTracker, new int[]{q,q,q,q}, (VoxyConfig.CONFIG.renderDistance<0?VoxyConfig.CONFIG.renderDistance:((VoxyConfig.CONFIG.renderDistance+1)/2)), - 3, minY, maxY); + minY, maxY); System.out.println("Distance tracker initialized"); this.postProcessing = new PostProcessing(); @@ -187,7 +187,11 @@ public class VoxelCore { var projection = computeProjectionMat(); //var projection = RenderSystem.getProjectionMatrix();//computeProjectionMat(); 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); this.postProcessing.setup(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight, boundFB); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/Gl46MeshletsFarWorldRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/Gl46MeshletsFarWorldRenderer.java index 9902a2a0..a13e120f 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/Gl46MeshletsFarWorldRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/Gl46MeshletsFarWorldRenderer.java @@ -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 // this could potentially result in a fair bit of memory savings (especially if used in normal mc terrain rendering) public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer { - private final Shader meshletGenerator = Shader.make() - .add(ShaderType.COMPUTE, "voxy:lod/gl46mesh/cmdgen.comp") - .compile(); - private final Shader lodShader = Shader.make() .add(ShaderType.VERTEX, "voxy:lod/gl46mesh/quads.vert") .add(ShaderType.FRAGMENT, "voxy:lod/gl46mesh/quads.frag") @@ -56,17 +52,26 @@ public class Gl46MeshletsFarWorldRenderer extends AbstractFarWorldRenderer> { private final AbstractFarWorldRenderer renderer; - + int width; + int height; int frameId; Matrix4f projection; Matrix4f modelView; @@ -39,4 +40,10 @@ public abstract class Viewport > { this.cameraZ = z; return (A) this; } + + public A setScreenSize(int width, int height) { + this.width = width; + this.height = height; + return (A) this; + } } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/building/QuadEncoder.java b/src/main/java/me/cortex/voxy/client/core/rendering/building/QuadEncoder.java index dc20a35f..379bfd14 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/building/QuadEncoder.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/building/QuadEncoder.java @@ -6,6 +6,25 @@ import me.cortex.voxy.client.core.util.Mesher2D; 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 public static int encodePosition(int face, int otherAxis, int encodedMeshedData) { if (false&&(Mesher2D.getW(encodedMeshedData) > 16 || Mesher2D.getH(encodedMeshedData) > 16)) { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java b/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java index 925d8b98..721aa088 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java @@ -118,24 +118,55 @@ public class RenderDataFactory { //Ordering is: translucent, double sided quads, directional quads offsets[0] = meshlet; + int mix = 32, miy = 32, miz = 32, max = 0, may = 0, maz = 0; for (long data : this.translucentQuadCollector) { if (innerQuadCount == 0) { //Write out meshlet header //Write out the section position 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); + 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) { + //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; meshlet++; + mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 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++; innerQuadCount = 0; + mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0; } offsets[1] = meshlet; @@ -145,18 +176,46 @@ public class RenderDataFactory { //Write out the section position 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); + 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) { + //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; meshlet++; + mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 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++; innerQuadCount = 0; + mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0; } for (int face = 0; face < 6; face++) { @@ -167,18 +226,46 @@ public class RenderDataFactory { //Write out the section position 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); + 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) { + //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; meshlet++; + mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 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++; innerQuadCount = 0; + mix = 32; miy = 32; miz = 32; max = 0; may = 0; maz = 0; } } } else { diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/bindings.glsl b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/bindings.glsl index 68767a12..7061e2e9 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/bindings.glsl +++ b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/bindings.glsl @@ -10,6 +10,7 @@ layout(binding = 0, std140) uniform SceneUniform { Frustum frustum; vec3 cameraSubPos; uint frameId; + uvec2 screensize; }; struct BlockModel { @@ -38,8 +39,17 @@ struct DrawCommand { int baseVertex; 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; +#endif #ifndef Quad #define Quad ivec2 @@ -49,13 +59,12 @@ layout(binding = 1, std430) readonly restrict buffer GeometryBuffer { }; layout(binding = 2, std430) restrict buffer DrawBuffer { + DispatchIndirect dispatchCmd; + uint fullMeshletCount; DrawCommand drawCmd; }; -#ifndef MESHLET_ACCESS -#define MESHLET_ACCESS readonly writeonly -#endif -layout(binding = 3, std430) MESHLET_ACCESS restrict buffer MeshletListData { +layout(binding = 3, std430) restrict buffer MeshletListData { uint meshlets[]; }; diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/cmdgen.comp b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/cmdgen.comp index a2b05aa6..fb4be61e 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/cmdgen.comp +++ b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/cmdgen.comp @@ -5,9 +5,9 @@ #import #import #import -#define extractMeshletStart extractQuadStart +#import + layout(local_size_x = 64) in; -#define QUADS_PER_MESHLET 30 void emitMeshlets(inout uint mli, inout uint meshletPtr, uint mskedCnt, uint cnt) { for (;mskedCnt != 0; mskedCnt--,mli++) { @@ -17,19 +17,19 @@ void emitMeshlets(inout uint mli, inout uint meshletPtr, uint mskedCnt, uint cnt } void main() { + //Clear here as it stops the need to dispatch a glClearData instruction if (gl_GlobalInvocationID.x == 0) { - //Setup the remaining state of the drawElementsIndirect command - drawCmd.count = QUADS_PER_MESHLET*6; - drawCmd.firstIndex = 0; - drawCmd.baseVertex = 0; - drawCmd.baseInstance = 0; + drawCmd.instanceCount = 0; + dispatchCmd.y = 1; + dispatchCmd.z = 1; } + if (gl_GlobalInvocationID.x >= sectionCount) { return; } //Check the occlusion data from last frame - bool shouldRender = visibilityData[gl_GlobalInvocationID.x] == frameId - 1; + bool shouldRender = visibilityData[gl_GlobalInvocationID.x] == frameId; if (shouldRender) { SectionMeta meta = sectionData[gl_GlobalInvocationID.x]; uint detail = extractDetail(meta); @@ -46,7 +46,12 @@ void main() { uint e = ((meta.cntD>>16)&0xFFFF) * uint(relative.x<1 ); 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); diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshlet.glsl b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshlet.glsl new file mode 100644 index 00000000..fdcb3a3f --- /dev/null +++ b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshlet.glsl @@ -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); +} +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 \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshletculler.comp b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshletculler.comp new file mode 100644 index 00000000..d99868ca --- /dev/null +++ b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/meshletculler.comp @@ -0,0 +1,65 @@ +#version 450 +#extension GL_ARB_gpu_shader_int64 : enable + +#define MESHLET_ACCESS +#define BIND_SAMPLER_AS_HIZ +#import +#import +#import +#import +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<= 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; + } +} \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/quads.vert b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/quads.vert index 06f23145..8e0432b3 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46mesh/quads.vert +++ b/src/main/resources/assets/voxy/shaders/lod/gl46mesh/quads.vert @@ -1,40 +1,10 @@ #version 450 #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 #import #import -#define PosHeader Quad - - -#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); -} -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 +#import layout(location = 6) out flat uint meshlet; PosHeader meshletPosition;