From ce7051d8ca7d72120da1e5047a2d6a930aea48c8 Mon Sep 17 00:00:00 2001 From: Halbear Date: Wed, 16 Sep 2026 20:38:37 +0100 Subject: [PATCH] i did a little memory optimisation (19GB of VRAM -> 2.6GB of VRAM), lost some FPS in vertex rendering as a result but i'll figure it out --- .../VoxelComputeShaders/meshGeneration.glsl | 4 +- .../meshGenerationShared.glsl | 257 +++-------------- .../resetVoxelDrawShared.glsl | 22 +- .../voxelGenerationShared.glsl | 260 +++++------------- .../packed_scene_individual_vertex.glsl | 96 +++++++ .../shaders/packed_scene_vertex.glsl | 149 ++++++++++ .../shaders/shadow_vertex_packed.glsl | 84 ++++++ .../EngineCore/Display/VulkanRenderer.java | 2 +- .../Terrain4J/EngineCore/Main/GameCore.java | 14 +- .../EngineCore/Profiling/CPUMonitor.java | 4 +- .../ComputeVoxelTerrain.java | 2 +- .../VoxelTerrainGeneration/RenderChunk.java | 3 +- .../SharedVoxelTerrainResources.java | 77 +++--- .../VoxelChunkGenerator.java | 20 +- .../VoxelTerrainGeneration/VoxelMeshPool.java | 76 +++-- .../VoxelTerrainHeightSampler.java | 2 +- .../VoxelWorldManager.java | 69 +++-- .../DeferredSceneRender.java | 82 ++++-- .../Forward/ForwardSceneRender.java | 70 ++++- .../ScreenSpace/AmbientOcclusionRenderer.java | 2 +- .../RenderPasses/Shadows/ShadowRenderer.java | 63 ++++- 21 files changed, 766 insertions(+), 592 deletions(-) create mode 100644 resources/EngineResources/shaders/packed_scene_individual_vertex.glsl create mode 100644 resources/EngineResources/shaders/packed_scene_vertex.glsl create mode 100644 resources/EngineResources/shaders/shadow_vertex_packed.glsl diff --git a/resources/EngineResources/VoxelComputeShaders/meshGeneration.glsl b/resources/EngineResources/VoxelComputeShaders/meshGeneration.glsl index 91b77ec..c2ce601 100644 --- a/resources/EngineResources/VoxelComputeShaders/meshGeneration.glsl +++ b/resources/EngineResources/VoxelComputeShaders/meshGeneration.glsl @@ -7,6 +7,7 @@ const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE; const int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE; const uint FLOATS_PER_VERTEX = 14u; +const uint INTEGERS_PER_VERTEX = 1u; const uint VERTICES_PER_FACE = 4u; const uint INDICES_PER_FACE = 6u; @@ -89,13 +90,12 @@ void emitFace(ivec3 voxelPos, int faceIndex) { return; } - vec3 p = vec3(chunkPos * CHUNK_SIZE + voxelPos); + vec3 p = vec3(voxelPos); vec3 normal; vec3 tangent; vec3 bitangent; - vec3 v0; vec3 v1; vec3 v2; diff --git a/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl b/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl index eeb73a7..95ea105 100644 --- a/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl +++ b/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl @@ -6,261 +6,72 @@ const int CHUNK_SIZE = 16; const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE; const int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE; -const uint FLOATS_PER_VERTEX = 14u; -const uint VERTICES_PER_FACE = 4u; -const uint INDICES_PER_FACE = 6u; - -const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * 12); -const uint MAX_VERTICES = MAX_VISIBLE_FACES_PER_CHUNK * VERTICES_PER_FACE; -const uint MAX_INDICES = MAX_VISIBLE_FACES_PER_CHUNK * INDICES_PER_FACE; +const uint VERTICES_PER_FACE = 6u; +const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 6); layout(std430, binding = 0) readonly buffer VoxelData { uint voxels[]; }; -layout(std430, binding = 1) buffer VertexBuffer { - float vertices[]; -}; - -layout(std430, binding = 2) buffer IndexBuffer { - uint indices[]; +layout(std430, binding = 1) buffer FaceBuffer { + uint faces[]; }; struct DrawCommand { - uint indexCount; + uint vertexCount; uint instanceCount; - uint firstIndex; - int vertexOffset; + uint firstVertex; uint firstInstance; }; -layout(std430, binding = 3) buffer DrawCommands { +layout(std430, binding = 2) buffer DrawCommands { DrawCommand drawCmds[]; }; +layout(std430, binding = 3) buffer Counters { + uint faceCount; +} counters; + layout(push_constant) uniform ChunkInfo { ivec3 chunkPos; int slot; - uint vertexFloatOffset; - uint indexOffset; + uint faceOffset; + uint unused0; uint indirectCommandIndex; uint padding0; }; - -layout(std430, binding = 4) buffer Counters { - uint vertexCount; - uint indexCount; -} counters; - - uint flatten(ivec3 pos) { return uint((pos.x * CHUNK_AREA) + (pos.y * CHUNK_SIZE) + pos.z); } uint getVoxel(ivec3 pos) { - if (pos.x < 0 || pos.x >= CHUNK_SIZE) return 0; - if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0; - if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0; + if (pos.x < 0 || pos.x >= CHUNK_SIZE) return 0u; + if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0u; + if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0u; return voxels[flatten(pos)]; } -void writeVertex(uint vertexIndex, vec3 position, vec3 normal, vec3 tangent, vec3 bitangent, vec2 uv) { - uint base = vertexFloatOffset + vertexIndex * FLOATS_PER_VERTEX; - - vertices[base + 0u] = position.x; - vertices[base + 1u] = position.y; - vertices[base + 2u] = position.z; - - vertices[base + 3u] = normal.x; - vertices[base + 4u] = normal.y; - vertices[base + 5u] = normal.z; - - vertices[base + 6u] = tangent.x; - vertices[base + 7u] = tangent.y; - vertices[base + 8u] = tangent.z; - - vertices[base + 9u] = bitangent.x; - vertices[base + 10u] = bitangent.y; - vertices[base + 11u] = bitangent.z; - - vertices[base + 12u] = uv.x; - vertices[base + 13u] = uv.y; +uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId, uint ao) { + return (voxelPos.x & 0x1Fu) | + ((voxelPos.y & 0x1Fu) << 5u) | + ((voxelPos.z & 0x1Fu) << 10u) | + ((faceIndex & 0x7u) << 15u) | + ((materialId & 0xFFu) << 18u) | + ((ao & 0x3u) << 26u); } -void emitFace(ivec3 voxelPos, int faceIndex, uint VoxelType) { - uint localBaseVertex = atomicAdd(counters.vertexCount, VERTICES_PER_FACE); - uint localBaseIndex = atomicAdd(counters.indexCount, INDICES_PER_FACE); +void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) { + uint localFace = atomicAdd(counters.faceCount, 1u); - if (localBaseVertex + VERTICES_PER_FACE > MAX_VERTICES || - localBaseIndex + INDICES_PER_FACE > MAX_INDICES) { + if (localFace >= MAX_VISIBLE_FACES_PER_CHUNK) { return; } - uint baseVertex = localBaseVertex; - uint baseIndex = indexOffset + localBaseIndex; + faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType, 0u); - vec3 p = vec3(chunkPos * CHUNK_SIZE + voxelPos); - - vec3 normal; - vec3 tangent; - vec3 bitangent; - - - vec3 v0; - vec3 v1; - vec3 v2; - vec3 v3; - - vec2 uv0; - vec2 uv1; - vec2 uv2; - vec2 uv3; - - if (faceIndex == 0) { - // Top +Y - normal = vec3(0.0, 1.0, 0.0); - tangent = vec3(1.0, 0.0, 0.0); - bitangent = vec3(0.0, 0.0, 1.0); - - v0 = p + vec3(0.0, 1.0, 0.0); - v1 = p + vec3(0.0, 1.0, 1.0); - v2 = p + vec3(1.0, 1.0, 1.0); - v3 = p + vec3(1.0, 1.0, 0.0); - - if(VoxelType == 1) { - uv0 = vec2(0.0, 0.5); - uv1 = vec2(0.0, 1.0); - uv2 = vec2(0.5, 1.0); - uv3 = vec2(0.5, 0.5); - } else{ - uv0 = vec2(0.5, 0.0); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(1.0, 0.5); - uv3 = vec2(1.0, 0.0); - } - } else if (faceIndex == 1) { - // Bottom -Y - normal = vec3(0.0, -1.0, 0.0); - tangent = vec3(1.0, 0.0, 0.0); - bitangent = vec3(0.0, 0.0, -1.0); - - v0 = p + vec3(0.0, 0.0, 0.0); - v1 = p + vec3(1.0, 0.0, 0.0); - v2 = p + vec3(1.0, 0.0, 1.0); - v3 = p + vec3(0.0, 0.0, 1.0); - uv0 = vec2(0.5, 0.0); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(1.0, 0.5); - uv3 = vec2(1.0, 0.0); - } else if (faceIndex == 2) { - // Right +X - normal = vec3(1.0, 0.0, 0.0); - tangent = vec3(0.0, 0.0, -1.0); - bitangent = vec3(0.0, 1.0, 0.0); - - v0 = p + vec3(1.0, 0.0, 0.0); - v1 = p + vec3(1.0, 1.0, 0.0); - v2 = p + vec3(1.0, 1.0, 1.0); - v3 = p + vec3(1.0, 0.0, 1.0); - if(VoxelType == 1) { - - uv2 = vec2(0.0, 0.0); - uv3 = vec2(0.0, 0.5); - uv0 = vec2(0.5, 0.5); - uv1 = vec2(0.5, 0.0); - } else{ - uv0 = vec2(0.5, 0.0); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(1.0, 0.5); - uv3 = vec2(1.0, 0.0); - } - } else if (faceIndex == 3) { - // Left -X - normal = vec3(-1.0, 0.0, 0.0); - tangent = vec3(0.0, 0.0, 1.0); - bitangent = vec3(0.0, 1.0, 0.0); - - v0 = p + vec3(0.0, 0.0, 0.0); - v1 = p + vec3(0.0, 0.0, 1.0); - v2 = p + vec3(0.0, 1.0, 1.0); - v3 = p + vec3(0.0, 1.0, 0.0); - - if(VoxelType == 1) { - - uv3 = vec2(0.0, 0.0); - uv0 = vec2(0.0, 0.5); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(0.5, 0.0); - } else{ - uv0 = vec2(0.5, 0.0); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(1.0, 0.5); - uv3 = vec2(1.0, 0.0); - } - } else if (faceIndex == 4) { - // Front +Z - normal = vec3(0.0, 0.0, 1.0); - tangent = vec3(1.0, 0.0, 0.0); - bitangent = vec3(0.0, 1.0, 0.0); - - v0 = p + vec3(0.0, 0.0, 1.0); - v1 = p + vec3(1.0, 0.0, 1.0); - v2 = p + vec3(1.0, 1.0, 1.0); - v3 = p + vec3(0.0, 1.0, 1.0); - - if(VoxelType == 1) { - - uv3 = vec2(0.0, 0.0); - uv0 = vec2(0.0, 0.5); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(0.5, 0.0); - } else{ - uv0 = vec2(0.5, 0.0); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(1.0, 0.5); - uv3 = vec2(1.0, 0.0); - } - } else { - // Back -Z - normal = vec3(0.0, 0.0, -1.0); - tangent = vec3(-1.0, 0.0, 0.0); - bitangent = vec3(0.0, 1.0, 0.0); - - v0 = p + vec3(0.0, 0.0, 0.0); - v1 = p + vec3(0.0, 1.0, 0.0); - v2 = p + vec3(1.0, 1.0, 0.0); - v3 = p + vec3(1.0, 0.0, 0.0); - - if(VoxelType == 1) { - - uv2 = vec2(0.0, 0.0); - uv3 = vec2(0.0, 0.5); - uv0 = vec2(0.5, 0.5); - uv1 = vec2(0.5, 0.0); - } else{ - uv0 = vec2(0.5, 0.0); - uv1 = vec2(0.5, 0.5); - uv2 = vec2(1.0, 0.5); - uv3 = vec2(1.0, 0.0); - } - } - - writeVertex(baseVertex + 0u, v0, normal, tangent, bitangent, uv0); - writeVertex(baseVertex + 1u, v1, normal, tangent, bitangent, uv1); - writeVertex(baseVertex + 2u, v2, normal, tangent, bitangent, uv2); - writeVertex(baseVertex + 3u, v3, normal, tangent, bitangent, uv3); - - indices[baseIndex + 0u] = baseVertex + 0u; - indices[baseIndex + 1u] = baseVertex + 1u; - indices[baseIndex + 2u] = baseVertex + 2u; - - indices[baseIndex + 3u] = baseVertex + 0u; - indices[baseIndex + 4u] = baseVertex + 2u; - indices[baseIndex + 5u] = baseVertex + 3u; - - atomicAdd(drawCmds[indirectCommandIndex].indexCount, INDICES_PER_FACE); + atomicAdd(drawCmds[indirectCommandIndex].vertexCount, VERTICES_PER_FACE); } void main() { @@ -276,10 +87,10 @@ void main() { return; } - if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0,current); - if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1,current); - if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2,current); - if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3,current); - if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4,current); - if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5,current); + if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0u, current); + if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1u, current); + if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2u, current); + if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3u, current); + if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4u, current); + if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5u, current); } \ No newline at end of file diff --git a/resources/EngineResources/VoxelComputeShaders/resetVoxelDrawShared.glsl b/resources/EngineResources/VoxelComputeShaders/resetVoxelDrawShared.glsl index fab801d..dc84fbb 100644 --- a/resources/EngineResources/VoxelComputeShaders/resetVoxelDrawShared.glsl +++ b/resources/EngineResources/VoxelComputeShaders/resetVoxelDrawShared.glsl @@ -2,13 +2,10 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; -const uint FLOATS_PER_VERTEX = 14u; - struct DrawCommand { - uint indexCount; + uint vertexCount; uint instanceCount; - uint firstIndex; - int vertexOffset; + uint firstVertex; uint firstInstance; }; @@ -17,26 +14,23 @@ layout(std430, binding = 0) buffer DrawCommands { }; layout(std430, binding = 1) buffer Counters { - uint vertexCount; - uint indexCount; + uint faceCount; } counters; layout(push_constant) uniform ChunkInfo { ivec3 chunkPos; int slot; - uint vertexFloatOffset; - uint indexOffset; + uint faceOffset; + uint unused0; uint indirectCommandIndex; uint padding0; }; void main() { - drawCmds[indirectCommandIndex].indexCount = 0u; + drawCmds[indirectCommandIndex].vertexCount = 0u; drawCmds[indirectCommandIndex].instanceCount = 1u; - drawCmds[indirectCommandIndex].firstIndex = indexOffset; - drawCmds[indirectCommandIndex].vertexOffset = int(vertexFloatOffset / FLOATS_PER_VERTEX); + drawCmds[indirectCommandIndex].firstVertex = faceOffset * 6u; drawCmds[indirectCommandIndex].firstInstance = 0u; - counters.vertexCount = 0u; - counters.indexCount = 0u; + counters.faceCount = 0u; } \ No newline at end of file diff --git a/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl b/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl index bfcebc6..dfce9e2 100644 --- a/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl +++ b/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl @@ -9,187 +9,70 @@ layout(std430, binding = 0) buffer VoxelData { uint voxels[]; }; -layout(push_constant) uniform ChunkOffset { +layout(push_constant) uniform ChunkInfo { ivec3 chunkPos; int slot; - uint vertexFloatOffset; - uint indexOffset; + uint faceOffset; + uint unused0; uint indirectCommandIndex; uint padding0; }; -// Description : Array and textureless GLSL 2D/3D/4D simplex -// noise functions. -// Author : Ian McEwan, Ashima Arts. -// Maintainer : stegu -// Lastmod : 20110822 (ijm) -// License : Copyright (C) 2011 Ashima Arts. All rights reserved. -// Distributed under the MIT License. See LICENSE file. -// https://github.com - -vec4 permute(vec4 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); } -vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; } - -float simplex_noise(vec3 v) { - const vec2 C = vec2(1.0/6.0, 1.0/3.0); - const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); - - // First corner - vec3 i = floor(v + dot(v, C.yyy)); - vec3 x0 = v - i + dot(i, C.xxx); - - // Other corners - vec3 g = step(x0.yzx, x0.xyz); - vec3 l = 1.0 - g; - vec3 i1 = min(g.xyz, l.zxy); - vec3 i2 = max(g.xyz, l.zxy); - - // x0 = x0 - 0.0 + 0.0 * C.xxx; - // x1 = x0 - i1 + 1.0 * C.xxx; - // x2 = x0 - i2 + 2.0 * C.xxx; - // x3 = x0 - 1.0 + 3.0 * C.xxx; - vec3 x1 = x0 - i1 + C.xxx; - vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y - vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y - - // Permutations - i = mod(i, 289.0); - vec4 p = permute(permute(permute( - i.z + vec4(0.0, i1.z, i2.z, 1.0)) - + i.y + vec4(0.0, i1.y, i2.y, 1.0)) - + i.x + vec4(0.0, i1.x, i2.x, 1.0)); - - // Gradients: 7x7 points over a square, mapped onto an octahedron. - // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) - float n_ = 0.142857142857; // 1.0/7.0 - vec3 ns = n_ * D.wyz - D.xzx; - - vec4 j = p - 49.0 * floor(p * ns.z); // mod(p,7*7) - - vec4 x_ = floor(j * ns.z); - vec4 y_ = floor(j - 7.0 * x_); // mod(j,N) - - vec4 x = x_ * ns.x + ns.yyyy; - vec4 y = y_ * ns.x + ns.yyyy; - vec4 h = 1.0 - abs(x) - abs(y); - - vec4 b0 = vec4(x.xy, y.xy); - vec4 b1 = vec4(x.zw, y.zw); - - //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; - //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; - vec4 s0 = floor(b0) * 2.0 + 1.0; - vec4 s1 = floor(b1) * 2.0 + 1.0; - vec4 sh = -step(h, vec4(0.0)); - - vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; - vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww; - - vec3 p0 = vec3(a0.xy, h.x); - vec3 p1 = vec3(a0.zw, h.y); - vec3 p2 = vec3(a1.xy, h.z); - vec3 p3 = vec3(a1.zw, h.w); - - // Normalise gradients - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - - // Mix final noise value - vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); - m = m * m; - - // Returns a value scaled exactly between -1.0 and 1.0 - return 42.0 * dot(m * m, vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3))); -} -float noise2D(vec2 p) { - return simplex_noise(vec3(p.x, p.y, 0.0)); +vec3 random3(vec3 st) { + return fract(sin(vec3( + dot(st, vec3(127.1, 311.7, 74.7)), + dot(st, vec3(269.5, 183.3, 246.1)), + dot(st, vec3(113.5, 271.9, 124.6)) + )) * 43758.5453123); } -float fbm(vec2 p, int octaves, float lacunarity, float gain) { - float value = 0.0; - float amplitude = 0.5; - float frequency = 1.0; - float amplitudeSum = 0.0; - - for (int i = 0; i < octaves; i++) { - value += noise2D(p * frequency) * amplitude; - amplitudeSum += amplitude; - - frequency *= lacunarity; - amplitude *= gain; - } - - return value / amplitudeSum; +float random3to1(vec3 st) { + return fract(sin(dot(st, vec3(127.1, 311.7, 74.7))) * 43758.5453123); } -float ridgedFbm(vec2 p, int octaves, float lacunarity, float gain) { - float value = 0.0; - float amplitude = 0.5; - float frequency = 1.0; - float amplitudeSum = 0.0; +float interpolate(float a, float b, float c, float d, float x) { + float p = (d - c) - (a - b); - for (int i = 0; i < octaves; i++) { - float n = noise2D(p * frequency); - n = 1.0 - abs(n); - n = n * n; - - value += n * amplitude; - amplitudeSum += amplitude; - - frequency *= lacunarity; - amplitude *= gain; - } - - return value / amplitudeSum; + return x * (x * (x * p + ((a - b) - p)) + (c - a)) + b; } -vec2 domainWarp(vec2 p) { - float wx = fbm(p + vec2(17.31, 91.73), 3, 2.0, 0.5); - float wz = fbm(p + vec2(43.17, 12.89), 3, 2.0, 0.5); +float sampleX(vec3 at) { + float floored = floor(at.x); - return p + vec2(wx, wz) * 35.0; + return interpolate( + random3to1(vec3(floored - 1.0, at.yz)), + random3to1(vec3(floored, at.yz)), + random3to1(vec3(floored + 1.0, at.yz)), + random3to1(vec3(floored + 2.0, at.yz)), + at.x - floored) * 0.5 + 0.25; } -float terrainHeight(vec2 worldXZ) { - vec2 p = worldXZ; +float sampleY(vec3 at) { + float floored = floor(at.y); - vec2 warped = domainWarp(p * 0.004); - - float broad = fbm(warped * 0.45, 5, 2.0, 0.5); - broad = broad * 0.5 + 0.5; - - float hills = fbm(p * 0.025, 4, 2.0, 0.48); - float detail = fbm(p * 0.085, 2, 2.0, 0.4); - - float height = 8.0; - height += broad * 12.0; - height += hills * 6.0; - height += detail * 2.0; - - return clamp(height, 4.0, 28.0); + return interpolate( + sampleX(vec3(at.x, floored - 1.0, at.z)), + sampleX(vec3(at.x, floored, at.z)), + sampleX(vec3(at.x, floored + 1.0, at.z)), + sampleX(vec3(at.x, floored + 2.0, at.z)), + at.y - floored); } +float cubicNoise(vec3 at) { + float floored = floor(at.z); + + return interpolate( + sampleY(vec3(at.xy, floored - 1.0)), + sampleY(vec3(at.xy, floored)), + sampleY(vec3(at.xy, floored + 1.0)), + sampleY(vec3(at.xy, floored + 2.0)), + at.z - floored); +} + + float rand(vec2 co) { return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453123); } -float fbm3D(vec3 p, int octaves, float lacunarity, float gain) { - float value = 0.0; - float amplitude = 0.5; - float frequency = 1.0; - float amplitudeSum = 0.0; - for (int i = 0; i < octaves; i++) { - value += simplex_noise(p * frequency) * amplitude; - amplitudeSum += amplitude; - - frequency *= lacunarity; - amplitude *= gain; - } - - return value / amplitudeSum; -} float valueNoise(vec2 st) { vec2 i = floor(st); vec2 f = fract(st); @@ -205,37 +88,29 @@ float valueNoise(vec2 st) { (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; } +bool isCave(vec3 worldPos) { + vec3 X = vec3(worldPos); + X = mat3( + 0.788675134594813, -0.211324865405187, -0.577350269189626, + -0.211324865405187, 0.788675134594813, -0.577350269189626, + 0.577350269189626, 0.577350269189626, 0.577350269189626) * X; + float n = cubicNoise(X); -vec2 randG(vec2 p) { - p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3))); - return -1.0 + 2.0 * fract(sin(p) * 43758.5453123); + return n > 0.5; } - -float perlinNoise(vec2 st) { - vec2 i = floor(st); - vec2 f = fract(st); - - vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0); - - float dotTopLeft = dot(randG(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0)); - float dotTopRight = dot(randG(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)); - float dotBottomLeft = dot(randG(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)); - float dotBottomRight = dot(randG(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)); - - return mix(mix(dotTopLeft, dotTopRight, u.x), - mix(dotBottomLeft, dotBottomRight, u.x), u.y); -} - void main() { ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz); ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos; - float height = valueNoise(vec2(worldPos.x, worldPos.z) * 0.005) * 100 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.01) * 10 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5; - //height = clamp(height, 4.0, 28.0); + float islandheight = valueNoise(vec2(worldPos.z, worldPos.x) * 0.005) * 100 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 20 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5 - 15; + float height = valueNoise(vec2(worldPos.x, worldPos.z) * 0.005) * 100 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.01) * 10 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5; + float height2 = valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.005) * 100 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.01) * 10 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.1) * 5+ valueNoise(vec2(-worldPos.x, -worldPos.z)) * 0.5 + 100; + float islandheight2 = 100 + valueNoise(vec2(-worldPos.z, -worldPos.x) * 0.005) * 100 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.1) * 20 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5 - 5; + //height = clamp(height, 4.0, 28.0); uint voxelType = 0u; - if (float(worldPos.y) <= height && float(floor(worldPos.y/CHUNK_SIZE) * CHUNK_SIZE + CHUNK_SIZE * 2) >= height) { + if (float(worldPos.y) <= height && float(worldPos.y) >= islandheight) { float depthBelowSurface = height - float(worldPos.y); if (depthBelowSurface < 1.5) { @@ -246,14 +121,23 @@ void main() { voxelType = 3u; // Stone } } + if(float(worldPos.y) <= height2 && float(worldPos.y) >= islandheight2){ + float depthBelowSurface = height2 - float(worldPos.y); -// if (voxelType != 0u && worldPos.y < int(height) - 6) { -// float cave = fbm3D(vec3(worldPos) * 0.045, 4, 2.0, 0.5); -// -// if (cave > 0.42) { -// voxelType = 0u; -// } -// } + if (depthBelowSurface < 1.5) { + voxelType = 1u; // Grass/topsoil + } else if (depthBelowSurface < 5.0) { + voxelType = 2u; // Dirt + } else { + voxelType = 3u; // Stone + } + } + + if (voxelType != 0u) { + if (isCave(vec3(worldPos*0.05))) { + voxelType = 0u; + } + } uint index = uint((localPos.x * CHUNK_AREA) + (localPos.y * CHUNK_SIZE) + localPos.z); voxels[index] = voxelType; diff --git a/resources/EngineResources/shaders/packed_scene_individual_vertex.glsl b/resources/EngineResources/shaders/packed_scene_individual_vertex.glsl new file mode 100644 index 0000000..8832915 --- /dev/null +++ b/resources/EngineResources/shaders/packed_scene_individual_vertex.glsl @@ -0,0 +1,96 @@ +#version 450 + +layout(location = 0) in uint inPackedVertex; + +layout(location = 0) out vec4 outPos; +layout(location = 1) out vec3 outNormal; +layout(location = 2) out vec3 outTangent; +layout(location = 3) out vec3 outBitangent; +layout(location = 4) out vec2 outTextCoords; +layout(location = 5) out mat4 viewMatrix; + +const vec3 NORMALS[6] = vec3[6]( + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, -1.0, 0.0), + vec3( 1.0, 0.0, 0.0), + vec3(-1.0, 0.0, 0.0), + vec3( 0.0, 0.0, 1.0), + vec3( 0.0, 0.0, -1.0) +); + +const vec3 TANGENTS[6] = vec3[6]( + vec3( 1.0, 0.0, 0.0), + vec3( 1.0, 0.0, 0.0), + vec3( 0.0, 0.0, -1.0), + vec3( 0.0, 0.0, 1.0), + vec3( 1.0, 0.0, 0.0), + vec3(-1.0, 0.0, 0.0) +); + +const vec3 BITANGENTS[6] = vec3[6]( + vec3( 0.0, 0.0, 1.0), + vec3( 0.0, 0.0, -1.0), + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, 1.0, 0.0) +); + +const vec2 CORNER_UVS[16] = vec2[16]( + vec2(0.5, 0.0), + vec2(0.5, 0.5), + vec2(1.0, 0.5), + vec2(1.0, 0.0), + + vec2(0.0, 0.5), + vec2(0.0, 1.0), + vec2(0.5, 1.0), + vec2(0.5, 0.5), + + vec2(0.5, 0.0), + vec2(0.5, 0.5), + vec2(1.0, 0.5), + vec2(1.0, 0.0), + + vec2(0.5, 0.0), + vec2(0.5, 0.5), + vec2(1.0, 0.5), + vec2(1.0, 0.0) +); + + +layout(set = 0, binding = 0) uniform ProjUniform { mat4 matrix; } projUniform; +layout(set = 1, binding = 0) uniform ViewUniform { mat4 matrix; } viewUniform; +layout(push_constant) uniform pc { + vec4 ModelOffset; + vec4 Padding0; + vec4 Padding1; + vec4 Padding2; +} push_constants; + +void main() { + viewMatrix = viewUniform.matrix; + + uint posX = inPackedVertex & 0x1Fu; + uint posY = (inPackedVertex >> 5u) & 0x1Fu; + uint posZ = (inPackedVertex >> 10u) & 0x1Fu; + uint faceIdx = (inPackedVertex >> 15u) & 0x7u; + uint cornerIdx = (inPackedVertex >> 18u) & 0x3u; + uint matId = (inPackedVertex >> 20u) & 0xFFu; + + vec3 inPos = vec3(posX, posY, posZ) + push_constants.ModelOffset.xyz * 16.0; + vec3 inNormal = NORMALS[faceIdx]; + vec3 inTangent = TANGENTS[faceIdx]; + vec3 inBitangent = BITANGENTS[faceIdx]; + + vec2 inTextCoords = CORNER_UVS[cornerIdx + 4 * matId]; + + vec4 worldPos = vec4(inPos, 1.0); + gl_Position = projUniform.matrix * viewUniform.matrix * worldPos; + + outPos = worldPos; + outNormal = inNormal; + outTangent = inTangent; + outBitangent = inBitangent; + outTextCoords = inTextCoords; +} \ No newline at end of file diff --git a/resources/EngineResources/shaders/packed_scene_vertex.glsl b/resources/EngineResources/shaders/packed_scene_vertex.glsl new file mode 100644 index 0000000..0726e3d --- /dev/null +++ b/resources/EngineResources/shaders/packed_scene_vertex.glsl @@ -0,0 +1,149 @@ +#version 450 + +layout(location = 0) out vec4 outPos; +layout(location = 1) out vec3 outNormal; +layout(location = 2) out vec3 outTangent; +layout(location = 3) out vec3 outBitangent; +layout(location = 4) out vec2 outTextCoords; +layout(location = 5) out mat4 viewMatrix; + +layout(set = 0, binding = 0) uniform ProjUniform { mat4 matrix; } projUniform; +layout(set = 1, binding = 0) uniform ViewUniform { mat4 matrix; } viewUniform; + +layout(set = 4, binding = 0) readonly buffer FaceBuffer { + uint faces[]; +}; + +layout(push_constant) uniform pc { + vec4 ModelOffset; + vec4 Padding0; + vec4 Padding1; + vec4 Padding2; +} push_constants; + +const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u); + +const vec3 NORMALS[6] = vec3[6]( + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, -1.0, 0.0), + vec3( 1.0, 0.0, 0.0), + vec3(-1.0, 0.0, 0.0), + vec3( 0.0, 0.0, 1.0), + vec3( 0.0, 0.0, -1.0) +); + +const vec3 TANGENTS[6] = vec3[6]( + vec3( 1.0, 0.0, 0.0), + vec3( 1.0, 0.0, 0.0), + vec3( 0.0, 0.0, -1.0), + vec3( 0.0, 0.0, 1.0), + vec3( 1.0, 0.0, 0.0), + vec3(-1.0, 0.0, 0.0) +); + +const vec3 BITANGENTS[6] = vec3[6]( + vec3( 0.0, 0.0, 1.0), + vec3( 0.0, 0.0, -1.0), + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, 1.0, 0.0), + vec3( 0.0, 1.0, 0.0) +); + +const vec2 CORNER_UVS[16] = vec2[16]( + vec2(0.5, 0.0), + vec2(0.5, 0.5), + vec2(1.0, 0.5), + vec2(1.0, 0.0), + + vec2(0.0, 0.5), + vec2(0.0, 1.0), + vec2(0.5, 1.0), + vec2(0.5, 0.5), + + vec2(0.5, 0.0), + vec2(0.5, 0.5), + vec2(1.0, 0.5), + vec2(1.0, 0.0), + + vec2(0.5, 0.0), + vec2(0.5, 0.5), + vec2(1.0, 0.5), + vec2(1.0, 0.0) +); + +vec3 buildFaceCornerPosition(uvec3 voxelPos, uint faceId, uint cornerIndex) { + vec3 p = vec3(voxelPos); + + if (faceId == 0u) { + if (cornerIndex == 0u) return p + vec3(0.0, 1.0, 0.0); + if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 1.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0); + return p + vec3(1.0, 1.0, 0.0); + } + + if (faceId == 1u) { + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 0.0); + if (cornerIndex == 2u) return p + vec3(1.0, 0.0, 1.0); + return p + vec3(0.0, 0.0, 1.0); + } + + if (faceId == 2u) { + if (cornerIndex == 0u) return p + vec3(1.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(1.0, 1.0, 0.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0); + return p + vec3(1.0, 0.0, 1.0); + } + + if (faceId == 3u) { + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(0.0, 0.0, 1.0); + if (cornerIndex == 2u) return p + vec3(0.0, 1.0, 1.0); + return p + vec3(0.0, 1.0, 0.0); + } + + if (faceId == 4u) { + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 1.0); + if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 1.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0); + return p + vec3(0.0, 1.0, 1.0); + } + + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 0.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 0.0); + return p + vec3(1.0, 0.0, 0.0); +} + +void main() { + viewMatrix = viewUniform.matrix; + + uint faceRecordIndex = uint(gl_VertexIndex) / 6u; + uint triangleVertex = uint(gl_VertexIndex) % 6u; + uint cornerIndex = TRI_TO_CORNER[triangleVertex]; + + uint packedFace = faces[faceRecordIndex]; + + uint voxelX = packedFace & 0x1Fu; + uint voxelY = (packedFace >> 5u) & 0x1Fu; + uint voxelZ = (packedFace >> 10u) & 0x1Fu; + uint faceId = (packedFace >> 15u) & 0x7u; + uint matId = (packedFace >> 18u) & 0xFFu; + + faceId = min(faceId, 5u); + matId = min(matId, 3u); + + vec3 localPos = buildFaceCornerPosition(uvec3(voxelX, voxelY, voxelZ), faceId, cornerIndex); + vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0; + + vec4 worldPosVec4 = vec4(worldPos, 1.0); + + gl_Position = projUniform.matrix * viewUniform.matrix * worldPosVec4; + + outPos = worldPosVec4; + outNormal = NORMALS[faceId]; + outTangent = TANGENTS[faceId]; + outBitangent = BITANGENTS[faceId]; + outTextCoords = CORNER_UVS[cornerIndex + 4u * matId]; +} \ No newline at end of file diff --git a/resources/EngineResources/shaders/shadow_vertex_packed.glsl b/resources/EngineResources/shaders/shadow_vertex_packed.glsl new file mode 100644 index 0000000..8833df7 --- /dev/null +++ b/resources/EngineResources/shaders/shadow_vertex_packed.glsl @@ -0,0 +1,84 @@ +#version 450 + +layout(set = 3, binding = 0) readonly buffer FaceBuffer { + uint faces[]; +}; + +layout(push_constant) uniform matrices { + vec4 ModelOffset; + vec4 Padding0; + vec4 Padding1; + vec4 Padding2; + uint materialIdx; +} push_constants; + +layout(location = 0) out vec2 outTextCoord; +layout(location = 1) out flat uint outMaterialIdx; + +const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u); + +vec3 buildFaceCornerPosition(uvec3 voxelPos, uint faceId, uint cornerIndex) { + vec3 p = vec3(voxelPos); + + if (faceId == 0u) { + if (cornerIndex == 0u) return p + vec3(0.0, 1.0, 0.0); + if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 1.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0); + return p + vec3(1.0, 1.0, 0.0); + } + + if (faceId == 1u) { + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 0.0); + if (cornerIndex == 2u) return p + vec3(1.0, 0.0, 1.0); + return p + vec3(0.0, 0.0, 1.0); + } + + if (faceId == 2u) { + if (cornerIndex == 0u) return p + vec3(1.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(1.0, 1.0, 0.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0); + return p + vec3(1.0, 0.0, 1.0); + } + + if (faceId == 3u) { + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(0.0, 0.0, 1.0); + if (cornerIndex == 2u) return p + vec3(0.0, 1.0, 1.0); + return p + vec3(0.0, 1.0, 0.0); + } + + if (faceId == 4u) { + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 1.0); + if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 1.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0); + return p + vec3(0.0, 1.0, 1.0); + } + + if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0); + if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 0.0); + if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 0.0); + return p + vec3(1.0, 0.0, 0.0); +} + +void main() { + uint faceRecordIndex = uint(gl_VertexIndex) / 6u; + uint triangleVertex = uint(gl_VertexIndex) % 6u; + uint cornerIndex = TRI_TO_CORNER[triangleVertex]; + + uint packedFace = faces[faceRecordIndex]; + + uint voxelX = packedFace & 0x1Fu; + uint voxelY = (packedFace >> 5u) & 0x1Fu; + uint voxelZ = (packedFace >> 10u) & 0x1Fu; + uint faceId = (packedFace >> 15u) & 0x7u; + uint matId = (packedFace >> 18u) & 0xFFu; + + vec3 localPos = buildFaceCornerPosition(uvec3(voxelX, voxelY, voxelZ), faceId, cornerIndex); + vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0; + + outTextCoord = vec2(0.0); + outMaterialIdx = matId; + + gl_Position = vec4(worldPos, 1.0); +} \ No newline at end of file diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java index 8703583..966e6b7 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java @@ -183,7 +183,7 @@ public class VulkanRenderer implements Renderer { spriteRenderer.CompileSprites(RendererContext,modelsCache, textureCache); spriteRenderer.LoadMaterials(RendererContext,materialsCache,textureCache); GuiRender.LoadTextures(RendererContext,initData.GuiTextures(),textureCache); - VoxelWorldManager.Init(RendererContext); + //VoxelWorldManager.Init(RendererContext); // VoxelWorldManager.GenerateChunks(new Vector3i(0,0,0), new Vector3i(16,0,16)); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java index 31345c3..e8344bc 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -660,13 +660,13 @@ public class GameCore implements GameLogic { if(!PrimaryRuntime.IsServer && !RenderThread.Headless) { CamPos.set(engineInstance.scene().GetCamera().GetPosition()); Vector3i ChunkPos = new Vector3i((int)Math.floor(CamPos.x/ (float) VoxelChunkGenerator.CHUNK_SIZE),(int)Math.floor(CamPos.y/ (float)VoxelChunkGenerator.CHUNK_SIZE),(int)Math.floor(CamPos.z/ (float)VoxelChunkGenerator.CHUNK_SIZE)); - if(ChunkPos.x != VoxelWorldManager.LastPosition.x || ChunkPos.y != VoxelWorldManager.LastPosition.y || ChunkPos.z != VoxelWorldManager.LastPosition.z) { - VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(5, 3, 5)); - VoxelWorldManager.UnloadFarChunks(ChunkPos, 10); - } else { - VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(24,10,24)); - VoxelWorldManager.UnloadFarChunks(ChunkPos, 48); - } + // if(ChunkPos.x != VoxelWorldManager.LastPosition.x || ChunkPos.y != VoxelWorldManager.LastPosition.y || ChunkPos.z != VoxelWorldManager.LastPosition.z) { + // VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(5, 5, 5)); + // VoxelWorldManager.UnloadFarChunks(ChunkPos, 10); + //} else { + VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(24,5,24)); + VoxelWorldManager.UnloadFarChunks(ChunkPos, 24); + //} for (int i = 0; i < VisualisedCollisionActor3D.CollisionVisuals.size(); i++) { VisualisedCollisionActor3D.CollisionVisuals.get(i).Update(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java index 9400ba9..5ed3af8 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java @@ -93,10 +93,10 @@ public class CPUMonitor { break; } } - return output.toString().isEmpty() ? "Unknown CPU" : output.toString(); + return output.toString().isEmpty() || output.toString().contains("cannot") ? "Unknown CPU" : output.toString(); } } catch (Exception e) { - return "Error reading CPU name: " + e.getMessage(); + return "Couldn't read CPU name"; } } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/ComputeVoxelTerrain.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/ComputeVoxelTerrain.java index 6ad847f..9d0f271 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/ComputeVoxelTerrain.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/ComputeVoxelTerrain.java @@ -48,7 +48,7 @@ public class ComputeVoxelTerrain { private static final int FLOATS_PER_VERTEX = 14; private static final int VERTEX_SIZE_BYTES = FLOATS_PER_VERTEX * Float.BYTES; - private static final int DRAW_INDEXED_INDIRECT_COMMAND_SIZE = 5 * Integer.BYTES; + private static final int DRAW_INDEXED_INDIRECT_COMMAND_SIZE = 4 * Integer.BYTES; private static final int COUNTER_BUFFER_SIZE = 2 * Integer.BYTES; private final String DESCRIPTOR_ID_MESH; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/RenderChunk.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/RenderChunk.java index 9ca26fd..3253037 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/RenderChunk.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/RenderChunk.java @@ -1,6 +1,7 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration; +import org.joml.Matrix4f; import org.joml.Vector3i; -public record RenderChunk(Vector3i position, int slot,long vertexOffsetBytes, long indexOffsetBytes,int maxIndexCount,long indirectCommandOffsetBytes) { +public record RenderChunk(Vector3i position, int slot, long faceOffsetBytes,int maxFaceCount,long indirectCommandOffsetBytes, Matrix4f ModelMatrix) { } \ No newline at end of file diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java index 6129788..fc60b0d 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java @@ -17,31 +17,15 @@ public class SharedVoxelTerrainResources { public static final int CHUNK_SIZE = 16; public static final int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE; - public static final int DRAW_INDEXED_INDIRECT_COMMAND_SIZE = 5 * Integer.BYTES; - public static final int COUNTER_BUFFER_SIZE = 2 * Integer.BYTES; - + public static final int DRAW_INDIRECT_COMMAND_SIZE = 4 * Integer.BYTES; + public static final int COUNTER_BUFFER_SIZE = Integer.BYTES; public static final int TERRAIN_GENERATION_PUSH_CONSTANT_SIZE = Integer.BYTES * 8; - /*Push constants: - int chunkX - int chunkY - int chunkZ - int slot - uint vertexFloatOffset - uint indexOffset - uint indirectCommandOffset - uint padding */ + private static final String DESC_ID_VOXEL_GENERATION = "VOXEL_SHARED_DESC_GENERATION"; private static final String DESC_ID_RESET = "VOXEL_SHARED_DESC_RESET"; private static final String DESC_ID_MESH = "VOXEL_SHARED_DESC_MESH"; - - private static final String MESH_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl"; - private static final String VOXEL_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl"; - private static final String VOXEL_RESET_GLSL = "resources/EngineResources/VoxelComputeShaders/resetVoxelDrawShared.glsl"; - - private static final String MESH_GENERATION_SPV = MESH_GENERATION_GLSL + ".spv"; - private static final String VOXEL_GENERATION_SPV = VOXEL_GENERATION_GLSL + ".spv"; - private static final String VOXEL_RESET_SPV = VOXEL_RESET_GLSL + ".spv"; + private static final String DESC_ID_FACE_GRAPHICS = "VOXEL_SHARED_DESC_FACE_GRAPHICS"; private final VoxelMeshPool meshPool; @@ -51,6 +35,15 @@ public class SharedVoxelTerrainResources { private final DescriptorSetLayout voxelGenerationLayout; private final DescriptorSetLayout resetLayout; private final DescriptorSetLayout meshGenerationLayout; + private final DescriptorSetLayout faceGraphicsLayout; + + private static final String MESH_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl"; + private static final String VOXEL_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl"; + private static final String VOXEL_RESET_GLSL = "resources/EngineResources/VoxelComputeShaders/resetVoxelDrawShared.glsl"; + + private static final String MESH_GENERATION_SPV = MESH_GENERATION_GLSL + ".spv"; + private static final String VOXEL_GENERATION_SPV = VOXEL_GENERATION_GLSL + ".spv"; + private static final String VOXEL_RESET_SPV = VOXEL_RESET_GLSL + ".spv"; private final Pipeline voxelGenerationPipeline; private final Pipeline resetPipeline; @@ -60,26 +53,29 @@ public class SharedVoxelTerrainResources { meshPool = new VoxelMeshPool(VkCtx, maxResidentChunks); voxelData = new VulkanBuffer(VkCtx, (long) VOXEL_COUNT * Integer.BYTES, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,0,0 ); + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, 0); - counters = new VulkanBuffer( VkCtx,COUNTER_BUFFER_SIZE,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,0,0 ); + counters = new VulkanBuffer(VkCtx, COUNTER_BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, 0); voxelGenerationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{ - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,0,1,VK_SHADER_STAGE_COMPUTE_BIT) + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT) }); resetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{ - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,0,1,VK_SHADER_STAGE_COMPUTE_BIT), - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,1,1,VK_SHADER_STAGE_COMPUTE_BIT) + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT), + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, 1, VK_SHADER_STAGE_COMPUTE_BIT) }); meshGenerationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{ - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,0,1,VK_SHADER_STAGE_COMPUTE_BIT), - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,1,1,VK_SHADER_STAGE_COMPUTE_BIT), - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,2,1,VK_SHADER_STAGE_COMPUTE_BIT), - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,3,1,VK_SHADER_STAGE_COMPUTE_BIT), - new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,4,1,VK_SHADER_STAGE_COMPUTE_BIT) + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT), + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, 1, VK_SHADER_STAGE_COMPUTE_BIT), + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2, 1, VK_SHADER_STAGE_COMPUTE_BIT), + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, 1, VK_SHADER_STAGE_COMPUTE_BIT) + }); + + faceGraphicsLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{ + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,0,1,VK_SHADER_STAGE_VERTEX_BIT ) }); createDescriptorSets(VkCtx); @@ -124,10 +120,20 @@ public class SharedVoxelTerrainResources { DescriptorSet meshSet = allocator.AddDescriptorSet(device, DESC_ID_MESH, meshGenerationLayout); meshSet.SetBuffer(device, voxelData, voxelData.GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); - meshSet.SetBuffer(device, meshPool.vertexPool(), meshPool.vertexPool().GetRequestedSize(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); - meshSet.SetBuffer(device, meshPool.indexPool(), meshPool.indexPool().GetRequestedSize(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); - meshSet.SetBuffer(device, meshPool.indirectPool(), meshPool.indirectPool().GetRequestedSize(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); - meshSet.SetBuffer(device, counters, counters.GetRequestedSize(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + meshSet.SetBuffer(device, meshPool.facePool(), meshPool.facePool().GetRequestedSize(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + meshSet.SetBuffer(device, meshPool.indirectPool(), meshPool.indirectPool().GetRequestedSize(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + meshSet.SetBuffer(device, counters, counters.GetRequestedSize(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + + DescriptorSet faceGraphicsSet = allocator.AddDescriptorSet(device, DESC_ID_FACE_GRAPHICS, faceGraphicsLayout); + faceGraphicsSet.SetBuffer(device, meshPool.facePool(), meshPool.facePool().GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + } + + public DescriptorSetLayout faceGraphicsLayout() { + return faceGraphicsLayout; + } + + public String faceGraphicsDescriptorId() { + return DESC_ID_FACE_GRAPHICS; } public VoxelMeshPool meshPool() { @@ -174,6 +180,7 @@ public class SharedVoxelTerrainResources { resetLayout.CleanUp(VkCtx); voxelGenerationLayout.CleanUp(VkCtx); meshGenerationLayout.CleanUp(VkCtx); + faceGraphicsLayout.CleanUp(VkCtx); voxelData.cleanup(VkCtx); counters.cleanup(VkCtx); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java index 0dcfd58..2a16932 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java @@ -30,16 +30,15 @@ public class VoxelChunkGenerator { ByteBuffer pushConstants = stack.malloc(SharedVoxelTerrainResources.TERRAIN_GENERATION_PUSH_CONSTANT_SIZE); - int vertexFloatOffset = (int) (chunk.vertexOffsetBytes() / Float.BYTES); - int indexOffset = (int) (chunk.indexOffsetBytes() / Integer.BYTES); - int indirectCommandIndex = (int) (chunk.indirectCommandOffsetBytes() / VoxelMeshPool.DRAW_INDEXED_INDIRECT_COMMAND_SIZE); + int indirectCommandIndex = (int) (chunk.indirectCommandOffsetBytes() / VoxelMeshPool.DRAW_INDIRECT_COMMAND_SIZE); + int faceOffset = (int) (chunk.faceOffsetBytes() / VoxelMeshPool.FACE_RECORD_SIZE_BYTES); pushConstants.putInt(0, chunk.position().x); pushConstants.putInt(4, chunk.position().y); pushConstants.putInt(8, chunk.position().z); pushConstants.putInt(12, chunk.slot()); - pushConstants.putInt(16, vertexFloatOffset); - pushConstants.putInt(20, indexOffset); + pushConstants.putInt(16, faceOffset); + pushConstants.putInt(20, 0); pushConstants.putInt(24, indirectCommandIndex); pushConstants.putInt(28, 0); @@ -101,19 +100,16 @@ public class VoxelChunkGenerator { new long[]{ resources.voxelData().GetBuffer(), resources.counters().GetBuffer(), - resources.meshPool().vertexPoolHandle(), - resources.meshPool().indexPoolHandle(), + resources.meshPool().facePoolHandle(), resources.meshPool().indirectPoolHandle() }, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT | - VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT | + VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, - VK_ACCESS_2_SHADER_READ_BIT | - VK_ACCESS_2_SHADER_WRITE_BIT | - VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT | - VK_ACCESS_2_INDEX_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_READ_BIT | + VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT ); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelMeshPool.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelMeshPool.java index fb5d577..4af7e19 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelMeshPool.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelMeshPool.java @@ -2,6 +2,8 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerr import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer; +import org.joml.Matrix4f; +import org.joml.Vector3f; import org.joml.Vector3i; import java.util.ArrayDeque; @@ -13,24 +15,16 @@ import static org.lwjgl.vulkan.VK13.*; public class VoxelMeshPool{ public static final int CHUNK_SIZE = 16; - public static final int FLOATS_PER_VERTEX = 14; - public static final int VERTEX_SIZE_BYTES = FLOATS_PER_VERTEX * Float.BYTES; - - public static final int MAX_VISIBLE_FACES_PER_CHUNK = CHUNK_SIZE * CHUNK_SIZE * 12; - public static final int MAX_VERTICES_PER_CHUNK = MAX_VISIBLE_FACES_PER_CHUNK * 4; - public static final int MAX_INDICES_PER_CHUNK = MAX_VISIBLE_FACES_PER_CHUNK * 6; - - public static final int INDEX_SIZE_BYTES = Integer.BYTES; - public static final int DRAW_INDEXED_INDIRECT_COMMAND_SIZE = 5 * Integer.BYTES; + public static final int MAX_VISIBLE_FACES_PER_CHUNK = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 6; + public static final int FACE_RECORD_SIZE_BYTES = Integer.BYTES; + public static final int DRAW_INDIRECT_COMMAND_SIZE = 4 * Integer.BYTES; private final int maxChunks; - private final long vertexSlotSizeBytes; - private final long indexSlotSizeBytes; + private final long faceSlotSizeBytes; private final long indirectSlotSizeBytes; - private final VulkanBuffer vertexPool; - private final VulkanBuffer indexPool; + private final VulkanBuffer facePool; private final VulkanBuffer indirectPool; private final Queue freeSlots = new ArrayDeque<>(); @@ -38,19 +32,14 @@ public class VoxelMeshPool{ public VoxelMeshPool(VulkanContext VkCtx, int maxChunks) { this.maxChunks = maxChunks; - this.vertexSlotSizeBytes = (long) MAX_VERTICES_PER_CHUNK * VERTEX_SIZE_BYTES; - this.indexSlotSizeBytes = (long) MAX_INDICES_PER_CHUNK * INDEX_SIZE_BYTES; - this.indirectSlotSizeBytes = DRAW_INDEXED_INDIRECT_COMMAND_SIZE; + this.faceSlotSizeBytes = (long) MAX_VISIBLE_FACES_PER_CHUNK * FACE_RECORD_SIZE_BYTES; + this.indirectSlotSizeBytes = DRAW_INDIRECT_COMMAND_SIZE; - long vertexPoolSize = vertexSlotSizeBytes * maxChunks; - long indexPoolSize = indexSlotSizeBytes * maxChunks; + long facePoolSize = faceSlotSizeBytes * maxChunks; long indirectPoolSize = indirectSlotSizeBytes * maxChunks; - - vertexPool = new VulkanBuffer(VkCtx,vertexPoolSize,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + facePool = new VulkanBuffer(VkCtx,facePoolSize,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,0,0); - indexPool = new VulkanBuffer(VkCtx,indexPoolSize,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,0,0); indirectPool = new VulkanBuffer(VkCtx,indirectPoolSize,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,0,0); @@ -66,44 +55,44 @@ public class VoxelMeshPool{ if (slot == null) { return null; } - - return new RenderChunk(new Vector3i(position),slot, vertexOffsetBytes(slot),indexOffsetBytes(slot),MAX_INDICES_PER_CHUNK,indirectCommandOffsetBytes(slot)); + return new RenderChunk( + new Vector3i(position), + slot, + faceOffsetBytes(slot), + MAX_VISIBLE_FACES_PER_CHUNK, + indirectCommandOffsetBytes(slot), + new Matrix4f().identity().translate( + new Vector3f( + position.x * CHUNK_SIZE, + position.y * CHUNK_SIZE, + position.z * CHUNK_SIZE + ) + ) + ); } public void free(RenderChunk chunk) { freeSlots.add(chunk.slot()); } - public long vertexOffsetBytes(int slot) { - return vertexSlotSizeBytes * slot; - } - - public long indexOffsetBytes(int slot) { - return indexSlotSizeBytes * slot; + public long faceOffsetBytes(int slot) { + return faceSlotSizeBytes * slot; } public long indirectCommandOffsetBytes(int slot) { return indirectSlotSizeBytes * slot; } - public VulkanBuffer vertexPool() { - return vertexPool; - } - - public VulkanBuffer indexPool() { - return indexPool; + public VulkanBuffer facePool() { + return facePool; } public VulkanBuffer indirectPool() { return indirectPool; } - public long vertexPoolHandle() { - return vertexPool.GetBuffer(); - } - - public long indexPoolHandle() { - return indexPool.GetBuffer(); + public long facePoolHandle() { + return facePool.GetBuffer(); } public long indirectPoolHandle() { @@ -119,8 +108,7 @@ public class VoxelMeshPool{ } public void cleanup(VulkanContext VkCtx) { - vertexPool.cleanup(VkCtx); - indexPool.cleanup(VkCtx); + facePool.cleanup(VkCtx); indirectPool.cleanup(VkCtx); } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelTerrainHeightSampler.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelTerrainHeightSampler.java index 9210387..5b2d71c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelTerrainHeightSampler.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelTerrainHeightSampler.java @@ -98,7 +98,7 @@ public final class VoxelTerrainHeightSampler { double minHeight = minHeightForChunkXZ(chunkX, chunkZ, chunkSize); double maxHeight = maxHeightForChunkXZ(chunkX, chunkZ, chunkSize); - double safetyPadding = 32.0; + double safetyPadding = 16.0; if (chunkMinY > maxHeight + safetyPadding) { return VoxelChunkVisibility.EMPTY_AIR; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java index 29244e6..2cc5a55 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java @@ -4,22 +4,21 @@ import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Pipeline; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.MaterialsCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; -import org.joml.Matrix4f; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils; import org.joml.Vector3i; -import org.lwjgl.system.MemoryStack; +import org.joml.Vector4f; import org.lwjgl.vulkan.VkCommandBuffer; import org.tinylog.Logger; import java.nio.ByteBuffer; -import java.nio.LongBuffer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import static org.lwjgl.vulkan.VK13.*; public class VoxelWorldManager { - private static final int MAX_RESIDENT_CHUNKS = 512 * 24; - private static final int MAX_CHUNK_GENERATIONS_PER_FRAME = 32; + private static final int MAX_RESIDENT_CHUNKS = 8192 * 2; + private static final int MAX_CHUNK_GENERATIONS_PER_FRAME = 256; private static final ConcurrentLinkedQueue RequestedChunks = new ConcurrentLinkedQueue<>(); private static final ConcurrentHashMap RenderChunks = new ConcurrentHashMap<>(); @@ -41,8 +40,8 @@ public class VoxelWorldManager { Generator = new VoxelChunkGenerator(Resources); GraphicsPushConstants = org.lwjgl.system.MemoryUtil.memAlloc( - net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.MATRIX4X4_SIZE + - net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.INT_SIZE + VulkanUtils.MATRIX4X4_SIZE + + VulkanUtils.INT_SIZE ); } @@ -116,7 +115,7 @@ public class VoxelWorldManager { // VoxelChunkGenerator.CHUNK_SIZE // ); // -// if (visibility != VoxelChunkVisibility.SURFACE) { +// if (visibility == VoxelChunkVisibility.EMPTY_AIR) { // CulledChunks.put(new Vector3i(position), visibility); // continue; // } @@ -136,48 +135,42 @@ public class VoxelWorldManager { } } - public static void RecordRender(VkCommandBuffer CommandBuffer,Pipeline graphicsPipeline, MaterialsCache materialsCache) { + public static SharedVoxelTerrainResources Resources() { + return Resources; + } + + public static void RecordRender(VkCommandBuffer CommandBuffer, Pipeline graphicsPipeline, MaterialsCache materialsCache, boolean shadowPass) { if (Resources == null) { return; } - int terrainMaterialIndex = materialsCache.GetPosition("VoxelTerrain"); + int terrainMaterialIndex; - if (terrainMaterialIndex < 0) { + if (materialsCache.GetPosition("VoxelTerrain") < 0) { terrainMaterialIndex = 0; + } else { + terrainMaterialIndex = materialsCache.GetPosition("VoxelTerrain"); } - try (MemoryStack stack = MemoryStack.stackPush()) { - Matrix4f identity = new Matrix4f().identity(); + RenderChunks.forEach((position, chunk) -> { + SetPushConstants(CommandBuffer, new Vector4f(position, 0), graphicsPipeline, terrainMaterialIndex, shadowPass); + vkCmdDrawIndirect(CommandBuffer, Resources.meshPool().indirectPoolHandle(), chunk.indirectCommandOffsetBytes(), + 1, VoxelMeshPool.DRAW_INDIRECT_COMMAND_SIZE); + }); + } - identity.get(0, GraphicsPushConstants); - GraphicsPushConstants.putInt( - net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.MATRIX4X4_SIZE, - terrainMaterialIndex - ); - - vkCmdPushConstants(CommandBuffer, graphicsPipeline.GetVulkanPipelineLayout(),VK_SHADER_STAGE_VERTEX_BIT, - 0,GraphicsPushConstants.slice( - 0, - net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.MATRIX4X4_SIZE)); - - vkCmdPushConstants(CommandBuffer,graphicsPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, - net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.MATRIX4X4_SIZE, - GraphicsPushConstants.slice( - net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.MATRIX4X4_SIZE, - net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.INT_SIZE ) ); - - LongBuffer vertexBuffers = stack.longs(Resources.meshPool().vertexPoolHandle()); - LongBuffer offsets = stack.longs(0L); - - vkCmdBindVertexBuffers(CommandBuffer, 0, vertexBuffers, offsets); - vkCmdBindIndexBuffer(CommandBuffer, Resources.meshPool().indexPoolHandle(), 0, VK_INDEX_TYPE_UINT32); - - RenderChunks.forEach((position, chunk) -> vkCmdDrawIndexedIndirect(CommandBuffer,Resources.meshPool().indirectPoolHandle(), - chunk.indirectCommandOffsetBytes(), 1,VoxelMeshPool.DRAW_INDEXED_INDIRECT_COMMAND_SIZE)); + private static void SetPushConstants(VkCommandBuffer CmdHandle, Vector4f ModelMatrix, Pipeline VkPipeline, int MaterialIndex, boolean shadowPass){ + ModelMatrix.get(0,GraphicsPushConstants); + GraphicsPushConstants.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex); + vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, + GraphicsPushConstants.slice(0,VulkanUtils.MATRIX4X4_SIZE)); + if(!shadowPass){ + vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE, + GraphicsPushConstants.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE)); } } + public static void UnloadFarChunks(Vector3i centerChunk, int unloadRadius) { int maxDistSq = unloadRadius * unloadRadius; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java index f1a879c..5fd0dd8 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java @@ -82,6 +82,9 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering private static final String FRAGMENT_OPAQUE_SHADER_FILE_SPV = FRAGMENT_OPAQUE_SHADER_FILE_GLSL + ".spv"; private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_vertex.glsl"; private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; + private static final String PACKED_VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/packed_scene_vertex.glsl"; + private static final String PACKED_VERTEX_SHADER_FILE_SPV = PACKED_VERTEX_SHADER_FILE_GLSL + ".spv"; + private Pipeline VkVoxelPipeline; private final VulkanBuffer[] BufferViewMatrices; private Pipeline VkPipeline; private Pipeline VkPipelineOpaque; @@ -166,6 +169,19 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,2); VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2); Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext)); + VoxelWorldManager.Init(vulkanContext); + + DescriptorSetLayout[] voxelLayouts = new DescriptorSetLayout[]{ + descriptorLayoutVertexUniform, + descriptorLayoutVertexUniform, + descriptorLayoutFragStorage, + descriptorLayoutTexture, + VoxelWorldManager.Resources().faceGraphicsLayout() + }; + + shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext, 3); + VkVoxelPipeline = CreateVoxelPipeline(vulkanContext, shaderModules, voxelLayouts); + Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext)); DescriptorSetLayout[] skyboxLayouts = new DescriptorSetLayout[]{ descriptorLayoutVertexUniform, @@ -229,11 +245,11 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){ if(EngineConfig.getInstance().RecompileShaders()){ - ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); + ShaderCompiler.CompileGLSLShaderOnChange(Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_GLSL : VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); ShaderCompiler.CompileGLSLShaderOnChange( Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_GLSL : FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); } return new ShaderModule[]{ - new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV,null), + new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_SPV :VERTEX_SHADER_FILE_SPV,null), new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_SPV : FRAGMENT_SHADER_FILE_SPV,null) }; } @@ -282,6 +298,41 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering } } + private static Pipeline CreateVoxelPipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts) { + int[] colorFormats = new int[]{ + MultiRenderTargetAttachments.POSITION_FORMAT, + MultiRenderTargetAttachments.ALBEDO_FORMAT, + MultiRenderTargetAttachments.NORMAL_FORMAT, + MultiRenderTargetAttachments.PBR_FORMAT, + MultiRenderTargetAttachments.EMISSIVE_FORMAT, + MultiRenderTargetAttachments.TRANSLUCECNY_FORMAT, + MultiRenderTargetAttachments.OPACITY_FORMAT, + MultiRenderTargetAttachments.VIEW_POS_FORMAT + }; + + try (MemoryStack stack = MemoryStack.stackPush()) { + VkPipelineVertexInputStateCreateInfo vertexInputState = VkPipelineVertexInputStateCreateInfo.calloc(stack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO) + .pVertexBindingDescriptions(null) + .pVertexAttributeDescriptions(null); + + var BuildInfo = new PipelineBuildInfo(ShaderModules, vertexInputState, colorFormats) + .SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT) + .SetDepthWrite(true) + .SetPushConstantRanges(new PushConstantsRange[]{ + new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT, 0, VulkanUtils.MATRIX4X4_SIZE), + new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE) + }) + .SetDescriptorSetLayouts(DescriptorSetLayouts) + .SetBlendingMethod(0) + .BlendingIsUsed(false) + .SetDualPass(false) + .SetAlphaToCoverage(true); + + return new DefaultPipeline(VkCtx, BuildInfo); + } + } + private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage, int BlendingMethod){ var vertexBufferStructure = new VertexBufferStructure(); var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{ @@ -356,18 +407,6 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferViewMatrices[CurrentFrame],engineInstance.scene().GetCamera().GetViewMatrix(), 0); // here - /* LongBuffer vBuffers = memAllocLong(1).put(0, terrainMesh.GetVertexBuffer()); - LongBuffer offsets = memAllocLong(1).put(0, 0L); - - vkCmdBindVertexBuffers(commandBuffer.GetVulkanCommandBuffer(), 0, vBuffers, offsets); - vkCmdBindIndexBuffer(commandBuffer.GetVulkanCommandBuffer(), terrainMesh.GetIndexBuffer(), 0, VK_INDEX_TYPE_UINT32); - - // Draw the procedural geometry primitives - vkCmdDrawIndexed(commandBuffer.GetVulkanCommandBuffer(), terrainMesh.GetIndexCount(), 1, 0, 0, 0); - - memFree(vBuffers); - memFree(offsets); - */ vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipeline() : VkPipeline.GetVulkanPipeline()); DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator(); @@ -377,10 +416,20 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering .put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet()) .put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()); vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); - RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false); - VoxelWorldManager.RecordRender(CommandHandle, DualPassRendering ? VkPipelineOpaque : VkPipeline,materialsCache); + vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkVoxelPipeline.GetVulkanPipeline()); + + LongBuffer voxelDescriptorSets = MemStack.mallocLong(5) + .put(0, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet()) + .put(1, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW, CurrentFrame).GetVkDescriptorSet()) + .put(2, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet()) + .put(3, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()) + .put(4, descriptorAllocator.GetDescriptorSet(VoxelWorldManager.Resources().faceGraphicsDescriptorId()).GetVkDescriptorSet()); + + vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkVoxelPipeline.GetVulkanPipelineLayout(), 0, voxelDescriptorSets, null); + + VoxelWorldManager.RecordRender(CommandHandle, VkVoxelPipeline, materialsCache, false); Matrix4f skyboxViewMatrix = new Matrix4f().identity(); skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix()); @@ -542,6 +591,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering public void cleanup(VulkanContext VkCtx){ VkPipeline.CleanUp(VkCtx); // VkSkyboxPipeline.CleanUp(VkCtx); + VkVoxelPipeline.CleanUp(VkCtx); VkPipelineOpaque.CleanUp(VkCtx); VkPipelineTranslucent.CleanUp(VkCtx); Arrays.asList(BufferViewMatrices).forEach(b -> b.cleanup(VkCtx)); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java index 1ec818c..18c6c6c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java @@ -7,6 +7,7 @@ import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3D; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3DElement; import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration.SharedVoxelTerrainResources; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration.VoxelWorldManager; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.RenderPasses.DeferredRendering.DeferredSceneRender; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView; @@ -65,6 +66,9 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering public static String SkyBoxID = "SKYBOX_TEXTURE"; private static final int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE; private final VulkanBuffer BufferProjectionMatrix; + private static final String PACKED_VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/packed_scene_vertex.glsl"; + private static final String PACKED_VERTEX_SHADER_FILE_SPV = PACKED_VERTEX_SHADER_FILE_GLSL + ".spv"; + private Pipeline VkVoxelPipeline; private final DescriptorSetLayout descriptorLayoutFragStorage; private final DescriptorSetLayout descriptorLayoutTexture; private final DescriptorSetLayout descriptorLayoutVertexUniform; @@ -169,6 +173,19 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering shaderModules = CreateShaderModules(vulkanContext,2); VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2); Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext)); + VoxelWorldManager.Init(vulkanContext); + + DescriptorSetLayout[] voxelLayouts = new DescriptorSetLayout[]{ + descriptorLayoutVertexUniform, + descriptorLayoutVertexUniform, + descriptorLayoutFragStorage, + descriptorLayoutTexture, + VoxelWorldManager.Resources().faceGraphicsLayout() + }; + + shaderModules = CreateShaderModules(vulkanContext, 3); + VkVoxelPipeline = CreateVoxelPipeline(vulkanContext, shaderModules, voxelLayouts); + Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext)); DescriptorSetLayout[] skyboxLayouts = new DescriptorSetLayout[]{ descriptorLayoutVertexUniform, @@ -198,6 +215,40 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering return new Attachment(VkCtx, SwapChainExtent.width(), SwapChainExtent.height(), COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); } + private static Pipeline CreateVoxelPipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts) { + int[] colorFormats = new int[]{ + MultiRenderTargetAttachments.POSITION_FORMAT, + MultiRenderTargetAttachments.ALBEDO_FORMAT, + MultiRenderTargetAttachments.NORMAL_FORMAT, + MultiRenderTargetAttachments.PBR_FORMAT, + MultiRenderTargetAttachments.EMISSIVE_FORMAT, + MultiRenderTargetAttachments.TRANSLUCECNY_FORMAT, + MultiRenderTargetAttachments.OPACITY_FORMAT, + MultiRenderTargetAttachments.VIEW_POS_FORMAT + }; + + try (MemoryStack stack = MemoryStack.stackPush()) { + VkPipelineVertexInputStateCreateInfo vertexInputState = VkPipelineVertexInputStateCreateInfo.calloc(stack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO) + .pVertexBindingDescriptions(null) + .pVertexAttributeDescriptions(null); + + var BuildInfo = new PipelineBuildInfo(ShaderModules, vertexInputState, colorFormats) + .SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT) + .SetDepthWrite(true) + .SetPushConstantRanges(new PushConstantsRange[]{ + new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT, 0, VulkanUtils.MATRIX4X4_SIZE), + new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE) + }) + .SetDescriptorSetLayouts(DescriptorSetLayouts) + .SetBlendingMethod(0) + .BlendingIsUsed(false) + .SetDualPass(false) + .SetAlphaToCoverage(true); + + return new DefaultPipeline(VkCtx, BuildInfo); + } + } private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue ClearValue){ return VkRenderingAttachmentInfo.calloc(1) @@ -241,11 +292,11 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){ if(EngineConfig.getInstance().RecompileShaders()){ - ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); + ShaderCompiler.CompileGLSLShaderOnChange(Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_GLSL :VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); ShaderCompiler.CompileGLSLShaderOnChange( Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_GLSL : FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); } return new ShaderModule[]{ - new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV,null), + new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_SPV : VERTEX_SHADER_FILE_SPV,null), new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_SPV : FRAGMENT_SHADER_FILE_SPV,null) }; @@ -364,7 +415,19 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering .put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()); vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false); - VoxelWorldManager.RecordRender(CommandHandle, DualPassRendering ? VkPipelineOpaque : VkPipeline,materialsCache); + vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkVoxelPipeline.GetVulkanPipeline()); + + LongBuffer voxelDescriptorSets = MemStack.mallocLong(5) + .put(0, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet()) + .put(1, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW, CurrentFrame).GetVkDescriptorSet()) + .put(2, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet()) + .put(3, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()) + .put(4, descriptorAllocator.GetDescriptorSet(VoxelWorldManager.Resources().faceGraphicsDescriptorId()).GetVkDescriptorSet()); + + vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkVoxelPipeline.GetVulkanPipelineLayout(), 0, voxelDescriptorSets, null); + + VoxelWorldManager.RecordRender(CommandHandle, VkVoxelPipeline, materialsCache, false); + Matrix4f skyboxViewMatrix = new Matrix4f().identity(); skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix()); @@ -530,6 +593,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering VkPipeline.CleanUp(VkCtx); VkPipelineTranslucent.CleanUp(VkCtx); VkPipelineOpaque.CleanUp(VkCtx); + VkVoxelPipeline.CleanUp(VkCtx); Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx)); RenderInfo.free(); AttachmentInfoColour.free(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/ScreenSpace/AmbientOcclusionRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/ScreenSpace/AmbientOcclusionRenderer.java index e20af0e..7baa556 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/ScreenSpace/AmbientOcclusionRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/ScreenSpace/AmbientOcclusionRenderer.java @@ -46,7 +46,7 @@ public class AmbientOcclusionRenderer { VulkanUtils.VEC4_SIZE + // screenSize.xy, radius, bias VulkanUtils.VEC4_SIZE; // kernelSize + padding private static final int SSAO_KERNEL_SIZE = 64; - private static final float SSAO_RADIUS = 0.75f; + private static final float SSAO_RADIUS = 0.35f; private static final float SSAO_BIAS = 0.025f; private static final long SSAO_KERNEL_BUFFER_SIZE = SSAO_KERNEL_SIZE * 4L * VulkanUtils.FLOAT_SIZE; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Shadows/ShadowRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Shadows/ShadowRenderer.java index 7d90759..880866a 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Shadows/ShadowRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Shadows/ShadowRenderer.java @@ -14,6 +14,7 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.I import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Pipeline; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PipelineBuildInfo; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PushConstantsRange; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.RenderPasses.DeferredRendering.MultiRenderTargetAttachments; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.*; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VertexBufferStructure; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*; @@ -80,7 +81,8 @@ public class ShadowRenderer { private static final String SHADOW_GEOMETRY_SHADER_FILE_SPV = SHADOW_GEOMETRY_SHADER_FILE_GLSL + ".spv"; private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/shadow_vertex.glsl"; private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; - + private static final String PACKED_VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/shadow_vertex_packed.glsl"; + private static final String PACKED_VERTEX_SHADER_FILE_SPV = PACKED_VERTEX_SHADER_FILE_GLSL + ".spv"; private final CascadeShadows[] cascadeShadows; private final VkClearValue ClearValueColour; private final VkClearValue ClearValueDepth; @@ -90,6 +92,7 @@ public class ShadowRenderer { private VkRenderingAttachmentInfo depthAttachmentInfo; private final DescriptorSetLayout descLayoutFrgStorage; private Pipeline pipeline; + private Pipeline pipelinePacked; private final VulkanBuffer[] prjBuffers; private final ByteBuffer pushConstBuff; private VkRenderingInfo renderingInfo; @@ -180,6 +183,14 @@ public class ShadowRenderer { pipeline = createPipeline(VulkanContext, shaderModules, new DescriptorSetLayout[]{uniformGeomDescriptorSetLayout, textDescriptorSetLayout, descLayoutFrgStorage}); Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VulkanContext)); + shaderModules = createPackedVertexShaderModules(VulkanContext); + pipelinePacked = CreateVoxelPipeline(VulkanContext, shaderModules, new DescriptorSetLayout[]{ + uniformGeomDescriptorSetLayout, + textDescriptorSetLayout, + descLayoutFrgStorage, + VoxelWorldManager.Resources().faceGraphicsLayout() + }); + Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VulkanContext)); cascadeShadows = new CascadeShadows[VulkanUtils.MAX_IN_FLIGHT]; for (int i = 0; i < VulkanUtils.MAX_IN_FLIGHT; i++) { @@ -238,6 +249,32 @@ public class ShadowRenderer { return pipeline; } + private static Pipeline CreateVoxelPipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts) { + int[] colorFormats = new int[]{ + ATTACHMENT_FORMATT + }; + + try (MemoryStack stack = MemoryStack.stackPush()) { + VkPipelineVertexInputStateCreateInfo vertexInputState = VkPipelineVertexInputStateCreateInfo.calloc(stack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO) + .pVertexBindingDescriptions(null) + .pVertexAttributeDescriptions(null); + + var BuildInfo = new PipelineBuildInfo(ShaderModules, vertexInputState, colorFormats) + .SetDepthFormat(DEPTH_FORMAT) + .SetPushConstantRanges( + new PushConstantsRange[]{ + new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT, 0, PUSH_CONSTANTS_SIZE) + }) + .SetDescriptorSetLayouts(DescriptorSetLayouts) + .SetDepthClamp(VkCtx.GetDevice().getDepthClamp()) + .CullMode(VK_CULL_MODE_FRONT_BIT) + .DepthBuffer(VK_COMPARE_OP_LESS_OR_EQUAL); + + return new DefaultPipeline(VkCtx, BuildInfo); + } + } + private static VkRenderingInfo createRenderInfo(VkRenderingAttachmentInfo.Buffer colorAttachmentInfo, VkRenderingAttachmentInfo depthAttachments) { var result = VkRenderingInfo.calloc().sType$Default(); @@ -254,7 +291,18 @@ public class ShadowRenderer { } return result; } - + private static ShaderModule[] createPackedVertexShaderModules(VulkanContext VulkanContext) { + if (EngineConfig.getInstance().RecompileShaders()) { + ShaderCompiler.CompileGLSLShaderOnChange(PACKED_VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); + ShaderCompiler.CompileGLSLShaderOnChange(SHADOW_GEOMETRY_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_geometry_shader); + ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); + } + return new ShaderModule[]{ + new ShaderModule(VulkanContext, VK_SHADER_STAGE_VERTEX_BIT, PACKED_VERTEX_SHADER_FILE_SPV, null), + new ShaderModule(VulkanContext, VK_SHADER_STAGE_GEOMETRY_BIT, SHADOW_GEOMETRY_SHADER_FILE_SPV, null), + new ShaderModule(VulkanContext, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, null), + }; + } private static ShaderModule[] createShaderModules(VulkanContext VulkanContext) { if (EngineConfig.getInstance().RecompileShaders()) { ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); @@ -271,6 +319,7 @@ public class ShadowRenderer { public void cleanup(VulkanContext VulkanContext) { AllowShadowRendering(false); pipeline.CleanUp(VulkanContext); + pipelinePacked.CleanUp(VulkanContext); uniformGeomDescriptorSetLayout.CleanUp(VulkanContext); descLayoutFrgStorage.CleanUp(VulkanContext); textDescriptorSetLayout.CleanUp(VulkanContext); @@ -394,7 +443,15 @@ public class ShadowRenderer { vkCmdDrawIndexed(cmdHandle, vulkanMesh.IndicesCount(), 1, 0, 0, 0); } } - VoxelWorldManager.RecordRender(cmdHandle,pipeline,materialsCache); + + descriptorSets = stack.mallocLong(4) + .put(0, descAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ, currentFrame).GetVkDescriptorSet()) + .put(1, descAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()) + .put(2, descAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet()) + .put(3, descAllocator.GetDescriptorSet(VoxelWorldManager.Resources().faceGraphicsDescriptorId()).GetVkDescriptorSet()); + vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinePacked.GetVulkanPipeline()); + vkCmdBindDescriptorSets(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinePacked.GetVulkanPipelineLayout(),0,descriptorSets,null); + VoxelWorldManager.RecordRender(cmdHandle,pipelinePacked,materialsCache,true); vkCmdEndRendering(cmdHandle); } }