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
This commit is contained in:
parent
bf9af81f38
commit
ce7051d8ca
21 changed files with 766 additions and 592 deletions
|
|
@ -7,6 +7,7 @@ const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
|
||||||
const int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
|
const int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
|
||||||
|
|
||||||
const uint FLOATS_PER_VERTEX = 14u;
|
const uint FLOATS_PER_VERTEX = 14u;
|
||||||
|
const uint INTEGERS_PER_VERTEX = 1u;
|
||||||
const uint VERTICES_PER_FACE = 4u;
|
const uint VERTICES_PER_FACE = 4u;
|
||||||
const uint INDICES_PER_FACE = 6u;
|
const uint INDICES_PER_FACE = 6u;
|
||||||
|
|
||||||
|
|
@ -89,13 +90,12 @@ void emitFace(ivec3 voxelPos, int faceIndex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 p = vec3(chunkPos * CHUNK_SIZE + voxelPos);
|
vec3 p = vec3(voxelPos);
|
||||||
|
|
||||||
vec3 normal;
|
vec3 normal;
|
||||||
vec3 tangent;
|
vec3 tangent;
|
||||||
vec3 bitangent;
|
vec3 bitangent;
|
||||||
|
|
||||||
|
|
||||||
vec3 v0;
|
vec3 v0;
|
||||||
vec3 v1;
|
vec3 v1;
|
||||||
vec3 v2;
|
vec3 v2;
|
||||||
|
|
|
||||||
|
|
@ -6,261 +6,72 @@ const int CHUNK_SIZE = 16;
|
||||||
const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
|
const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
|
||||||
const int VOXEL_COUNT = CHUNK_SIZE * 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 = 6u;
|
||||||
const uint VERTICES_PER_FACE = 4u;
|
const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 6);
|
||||||
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;
|
|
||||||
|
|
||||||
layout(std430, binding = 0) readonly buffer VoxelData {
|
layout(std430, binding = 0) readonly buffer VoxelData {
|
||||||
uint voxels[];
|
uint voxels[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 1) buffer VertexBuffer {
|
layout(std430, binding = 1) buffer FaceBuffer {
|
||||||
float vertices[];
|
uint faces[];
|
||||||
};
|
|
||||||
|
|
||||||
layout(std430, binding = 2) buffer IndexBuffer {
|
|
||||||
uint indices[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawCommand {
|
struct DrawCommand {
|
||||||
uint indexCount;
|
uint vertexCount;
|
||||||
uint instanceCount;
|
uint instanceCount;
|
||||||
uint firstIndex;
|
uint firstVertex;
|
||||||
int vertexOffset;
|
|
||||||
uint firstInstance;
|
uint firstInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 3) buffer DrawCommands {
|
layout(std430, binding = 2) buffer DrawCommands {
|
||||||
DrawCommand drawCmds[];
|
DrawCommand drawCmds[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 3) buffer Counters {
|
||||||
|
uint faceCount;
|
||||||
|
} counters;
|
||||||
|
|
||||||
layout(push_constant) uniform ChunkInfo {
|
layout(push_constant) uniform ChunkInfo {
|
||||||
ivec3 chunkPos;
|
ivec3 chunkPos;
|
||||||
int slot;
|
int slot;
|
||||||
uint vertexFloatOffset;
|
uint faceOffset;
|
||||||
uint indexOffset;
|
uint unused0;
|
||||||
uint indirectCommandIndex;
|
uint indirectCommandIndex;
|
||||||
uint padding0;
|
uint padding0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
layout(std430, binding = 4) buffer Counters {
|
|
||||||
uint vertexCount;
|
|
||||||
uint indexCount;
|
|
||||||
} counters;
|
|
||||||
|
|
||||||
|
|
||||||
uint flatten(ivec3 pos) {
|
uint flatten(ivec3 pos) {
|
||||||
return uint((pos.x * CHUNK_AREA) + (pos.y * CHUNK_SIZE) + pos.z);
|
return uint((pos.x * CHUNK_AREA) + (pos.y * CHUNK_SIZE) + pos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getVoxel(ivec3 pos) {
|
uint getVoxel(ivec3 pos) {
|
||||||
if (pos.x < 0 || pos.x >= CHUNK_SIZE) return 0;
|
if (pos.x < 0 || pos.x >= CHUNK_SIZE) return 0u;
|
||||||
if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0;
|
if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0u;
|
||||||
if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0;
|
if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0u;
|
||||||
|
|
||||||
return voxels[flatten(pos)];
|
return voxels[flatten(pos)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeVertex(uint vertexIndex, vec3 position, vec3 normal, vec3 tangent, vec3 bitangent, vec2 uv) {
|
uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId, uint ao) {
|
||||||
uint base = vertexFloatOffset + vertexIndex * FLOATS_PER_VERTEX;
|
return (voxelPos.x & 0x1Fu) |
|
||||||
|
((voxelPos.y & 0x1Fu) << 5u) |
|
||||||
vertices[base + 0u] = position.x;
|
((voxelPos.z & 0x1Fu) << 10u) |
|
||||||
vertices[base + 1u] = position.y;
|
((faceIndex & 0x7u) << 15u) |
|
||||||
vertices[base + 2u] = position.z;
|
((materialId & 0xFFu) << 18u) |
|
||||||
|
((ao & 0x3u) << 26u);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitFace(ivec3 voxelPos, int faceIndex, uint VoxelType) {
|
void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) {
|
||||||
uint localBaseVertex = atomicAdd(counters.vertexCount, VERTICES_PER_FACE);
|
uint localFace = atomicAdd(counters.faceCount, 1u);
|
||||||
uint localBaseIndex = atomicAdd(counters.indexCount, INDICES_PER_FACE);
|
|
||||||
|
|
||||||
if (localBaseVertex + VERTICES_PER_FACE > MAX_VERTICES ||
|
if (localFace >= MAX_VISIBLE_FACES_PER_CHUNK) {
|
||||||
localBaseIndex + INDICES_PER_FACE > MAX_INDICES) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint baseVertex = localBaseVertex;
|
faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType, 0u);
|
||||||
uint baseIndex = indexOffset + localBaseIndex;
|
|
||||||
|
|
||||||
vec3 p = vec3(chunkPos * CHUNK_SIZE + voxelPos);
|
atomicAdd(drawCmds[indirectCommandIndex].vertexCount, VERTICES_PER_FACE);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
@ -276,10 +87,10 @@ void main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0,current);
|
if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0u, current);
|
||||||
if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1,current);
|
if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1u, current);
|
||||||
if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2,current);
|
if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2u, current);
|
||||||
if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3,current);
|
if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3u, current);
|
||||||
if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4,current);
|
if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4u, current);
|
||||||
if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5,current);
|
if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5u, current);
|
||||||
}
|
}
|
||||||
|
|
@ -2,13 +2,10 @@
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
const uint FLOATS_PER_VERTEX = 14u;
|
|
||||||
|
|
||||||
struct DrawCommand {
|
struct DrawCommand {
|
||||||
uint indexCount;
|
uint vertexCount;
|
||||||
uint instanceCount;
|
uint instanceCount;
|
||||||
uint firstIndex;
|
uint firstVertex;
|
||||||
int vertexOffset;
|
|
||||||
uint firstInstance;
|
uint firstInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -17,26 +14,23 @@ layout(std430, binding = 0) buffer DrawCommands {
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 1) buffer Counters {
|
layout(std430, binding = 1) buffer Counters {
|
||||||
uint vertexCount;
|
uint faceCount;
|
||||||
uint indexCount;
|
|
||||||
} counters;
|
} counters;
|
||||||
|
|
||||||
layout(push_constant) uniform ChunkInfo {
|
layout(push_constant) uniform ChunkInfo {
|
||||||
ivec3 chunkPos;
|
ivec3 chunkPos;
|
||||||
int slot;
|
int slot;
|
||||||
uint vertexFloatOffset;
|
uint faceOffset;
|
||||||
uint indexOffset;
|
uint unused0;
|
||||||
uint indirectCommandIndex;
|
uint indirectCommandIndex;
|
||||||
uint padding0;
|
uint padding0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
drawCmds[indirectCommandIndex].indexCount = 0u;
|
drawCmds[indirectCommandIndex].vertexCount = 0u;
|
||||||
drawCmds[indirectCommandIndex].instanceCount = 1u;
|
drawCmds[indirectCommandIndex].instanceCount = 1u;
|
||||||
drawCmds[indirectCommandIndex].firstIndex = indexOffset;
|
drawCmds[indirectCommandIndex].firstVertex = faceOffset * 6u;
|
||||||
drawCmds[indirectCommandIndex].vertexOffset = int(vertexFloatOffset / FLOATS_PER_VERTEX);
|
|
||||||
drawCmds[indirectCommandIndex].firstInstance = 0u;
|
drawCmds[indirectCommandIndex].firstInstance = 0u;
|
||||||
|
|
||||||
counters.vertexCount = 0u;
|
counters.faceCount = 0u;
|
||||||
counters.indexCount = 0u;
|
|
||||||
}
|
}
|
||||||
|
|
@ -9,187 +9,70 @@ layout(std430, binding = 0) buffer VoxelData {
|
||||||
uint voxels[];
|
uint voxels[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(push_constant) uniform ChunkOffset {
|
layout(push_constant) uniform ChunkInfo {
|
||||||
ivec3 chunkPos;
|
ivec3 chunkPos;
|
||||||
int slot;
|
int slot;
|
||||||
uint vertexFloatOffset;
|
uint faceOffset;
|
||||||
uint indexOffset;
|
uint unused0;
|
||||||
uint indirectCommandIndex;
|
uint indirectCommandIndex;
|
||||||
uint padding0;
|
uint padding0;
|
||||||
};
|
};
|
||||||
// Description : Array and textureless GLSL 2D/3D/4D simplex
|
vec3 random3(vec3 st) {
|
||||||
// noise functions.
|
return fract(sin(vec3(
|
||||||
// Author : Ian McEwan, Ashima Arts.
|
dot(st, vec3(127.1, 311.7, 74.7)),
|
||||||
// Maintainer : stegu
|
dot(st, vec3(269.5, 183.3, 246.1)),
|
||||||
// Lastmod : 20110822 (ijm)
|
dot(st, vec3(113.5, 271.9, 124.6))
|
||||||
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
|
)) * 43758.5453123);
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float fbm(vec2 p, int octaves, float lacunarity, float gain) {
|
float random3to1(vec3 st) {
|
||||||
float value = 0.0;
|
return fract(sin(dot(st, vec3(127.1, 311.7, 74.7))) * 43758.5453123);
|
||||||
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 ridgedFbm(vec2 p, int octaves, float lacunarity, float gain) {
|
float interpolate(float a, float b, float c, float d, float x) {
|
||||||
float value = 0.0;
|
float p = (d - c) - (a - b);
|
||||||
float amplitude = 0.5;
|
|
||||||
float frequency = 1.0;
|
|
||||||
float amplitudeSum = 0.0;
|
|
||||||
|
|
||||||
for (int i = 0; i < octaves; i++) {
|
return x * (x * (x * p + ((a - b) - p)) + (c - a)) + b;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 domainWarp(vec2 p) {
|
float sampleX(vec3 at) {
|
||||||
float wx = fbm(p + vec2(17.31, 91.73), 3, 2.0, 0.5);
|
float floored = floor(at.x);
|
||||||
float wz = fbm(p + vec2(43.17, 12.89), 3, 2.0, 0.5);
|
|
||||||
|
|
||||||
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) {
|
float sampleY(vec3 at) {
|
||||||
vec2 p = worldXZ;
|
float floored = floor(at.y);
|
||||||
|
|
||||||
vec2 warped = domainWarp(p * 0.004);
|
return interpolate(
|
||||||
|
sampleX(vec3(at.x, floored - 1.0, at.z)),
|
||||||
float broad = fbm(warped * 0.45, 5, 2.0, 0.5);
|
sampleX(vec3(at.x, floored, at.z)),
|
||||||
broad = broad * 0.5 + 0.5;
|
sampleX(vec3(at.x, floored + 1.0, at.z)),
|
||||||
|
sampleX(vec3(at.x, floored + 2.0, at.z)),
|
||||||
float hills = fbm(p * 0.025, 4, 2.0, 0.48);
|
at.y - floored);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
float rand(vec2 co) {
|
||||||
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453123);
|
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) {
|
float valueNoise(vec2 st) {
|
||||||
vec2 i = floor(st);
|
vec2 i = floor(st);
|
||||||
vec2 f = fract(st);
|
vec2 f = fract(st);
|
||||||
|
|
@ -205,37 +88,29 @@ float valueNoise(vec2 st) {
|
||||||
(c - a) * u.y * (1.0 - u.x) +
|
(c - a) * u.y * (1.0 - u.x) +
|
||||||
(d - b) * u.x * u.y;
|
(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) {
|
return n > 0.5;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
void main() {
|
||||||
ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz);
|
ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz);
|
||||||
ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos;
|
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;
|
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;
|
||||||
//height = clamp(height, 4.0, 28.0);
|
|
||||||
|
|
||||||
|
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;
|
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);
|
float depthBelowSurface = height - float(worldPos.y);
|
||||||
|
|
||||||
if (depthBelowSurface < 1.5) {
|
if (depthBelowSurface < 1.5) {
|
||||||
|
|
@ -246,14 +121,23 @@ void main() {
|
||||||
voxelType = 3u; // Stone
|
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) {
|
if (depthBelowSurface < 1.5) {
|
||||||
// float cave = fbm3D(vec3(worldPos) * 0.045, 4, 2.0, 0.5);
|
voxelType = 1u; // Grass/topsoil
|
||||||
//
|
} else if (depthBelowSurface < 5.0) {
|
||||||
// if (cave > 0.42) {
|
voxelType = 2u; // Dirt
|
||||||
// voxelType = 0u;
|
} 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);
|
uint index = uint((localPos.x * CHUNK_AREA) + (localPos.y * CHUNK_SIZE) + localPos.z);
|
||||||
voxels[index] = voxelType;
|
voxels[index] = voxelType;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
149
resources/EngineResources/shaders/packed_scene_vertex.glsl
Normal file
149
resources/EngineResources/shaders/packed_scene_vertex.glsl
Normal file
|
|
@ -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];
|
||||||
|
}
|
||||||
84
resources/EngineResources/shaders/shadow_vertex_packed.glsl
Normal file
84
resources/EngineResources/shaders/shadow_vertex_packed.glsl
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -183,7 +183,7 @@ public class VulkanRenderer implements Renderer {
|
||||||
spriteRenderer.CompileSprites(RendererContext,modelsCache, textureCache);
|
spriteRenderer.CompileSprites(RendererContext,modelsCache, textureCache);
|
||||||
spriteRenderer.LoadMaterials(RendererContext,materialsCache,textureCache);
|
spriteRenderer.LoadMaterials(RendererContext,materialsCache,textureCache);
|
||||||
GuiRender.LoadTextures(RendererContext,initData.GuiTextures(),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));
|
// VoxelWorldManager.GenerateChunks(new Vector3i(0,0,0), new Vector3i(16,0,16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -660,13 +660,13 @@ public class GameCore implements GameLogic {
|
||||||
if(!PrimaryRuntime.IsServer && !RenderThread.Headless) {
|
if(!PrimaryRuntime.IsServer && !RenderThread.Headless) {
|
||||||
CamPos.set(engineInstance.scene().GetCamera().GetPosition());
|
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));
|
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) {
|
// 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.GenerateChunks(ChunkPos, new Vector3i(5, 5, 5));
|
||||||
VoxelWorldManager.UnloadFarChunks(ChunkPos, 10);
|
// VoxelWorldManager.UnloadFarChunks(ChunkPos, 10);
|
||||||
} else {
|
//} else {
|
||||||
VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(24,10,24));
|
VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(24,5,24));
|
||||||
VoxelWorldManager.UnloadFarChunks(ChunkPos, 48);
|
VoxelWorldManager.UnloadFarChunks(ChunkPos, 24);
|
||||||
}
|
//}
|
||||||
|
|
||||||
for (int i = 0; i < VisualisedCollisionActor3D.CollisionVisuals.size(); i++) {
|
for (int i = 0; i < VisualisedCollisionActor3D.CollisionVisuals.size(); i++) {
|
||||||
VisualisedCollisionActor3D.CollisionVisuals.get(i).Update();
|
VisualisedCollisionActor3D.CollisionVisuals.get(i).Update();
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,10 @@ public class CPUMonitor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output.toString().isEmpty() ? "Unknown CPU" : output.toString();
|
return output.toString().isEmpty() || output.toString().contains("cannot") ? "Unknown CPU" : output.toString();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return "Error reading CPU name: " + e.getMessage();
|
return "Couldn't read CPU name";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ public class ComputeVoxelTerrain {
|
||||||
|
|
||||||
private static final int FLOATS_PER_VERTEX = 14;
|
private static final int FLOATS_PER_VERTEX = 14;
|
||||||
private static final int VERTEX_SIZE_BYTES = FLOATS_PER_VERTEX * Float.BYTES;
|
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 static final int COUNTER_BUFFER_SIZE = 2 * Integer.BYTES;
|
||||||
|
|
||||||
private final String DESCRIPTOR_ID_MESH;
|
private final String DESCRIPTOR_ID_MESH;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration;
|
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration;
|
||||||
|
|
||||||
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Vector3i;
|
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) {
|
||||||
}
|
}
|
||||||
|
|
@ -17,31 +17,15 @@ public class SharedVoxelTerrainResources {
|
||||||
public static final int CHUNK_SIZE = 16;
|
public static final int CHUNK_SIZE = 16;
|
||||||
public static final int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
|
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 DRAW_INDIRECT_COMMAND_SIZE = 4 * Integer.BYTES;
|
||||||
public static final int COUNTER_BUFFER_SIZE = 2 * Integer.BYTES;
|
public static final int COUNTER_BUFFER_SIZE = Integer.BYTES;
|
||||||
|
|
||||||
|
|
||||||
public static final int TERRAIN_GENERATION_PUSH_CONSTANT_SIZE = Integer.BYTES * 8;
|
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_VOXEL_GENERATION = "VOXEL_SHARED_DESC_GENERATION";
|
||||||
private static final String DESC_ID_RESET = "VOXEL_SHARED_DESC_RESET";
|
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 DESC_ID_MESH = "VOXEL_SHARED_DESC_MESH";
|
||||||
|
private static final String DESC_ID_FACE_GRAPHICS = "VOXEL_SHARED_DESC_FACE_GRAPHICS";
|
||||||
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 VoxelMeshPool meshPool;
|
private final VoxelMeshPool meshPool;
|
||||||
|
|
||||||
|
|
@ -51,6 +35,15 @@ public class SharedVoxelTerrainResources {
|
||||||
private final DescriptorSetLayout voxelGenerationLayout;
|
private final DescriptorSetLayout voxelGenerationLayout;
|
||||||
private final DescriptorSetLayout resetLayout;
|
private final DescriptorSetLayout resetLayout;
|
||||||
private final DescriptorSetLayout meshGenerationLayout;
|
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 voxelGenerationPipeline;
|
||||||
private final Pipeline resetPipeline;
|
private final Pipeline resetPipeline;
|
||||||
|
|
@ -60,26 +53,29 @@ public class SharedVoxelTerrainResources {
|
||||||
meshPool = new VoxelMeshPool(VkCtx, maxResidentChunks);
|
meshPool = new VoxelMeshPool(VkCtx, maxResidentChunks);
|
||||||
|
|
||||||
voxelData = new VulkanBuffer(VkCtx, (long) VOXEL_COUNT * Integer.BYTES,
|
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,
|
counters = new VulkanBuffer(VkCtx, COUNTER_BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||||
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,0,0 );
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, 0);
|
||||||
|
|
||||||
voxelGenerationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{
|
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[]{
|
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, 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, 1, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||||
});
|
});
|
||||||
|
|
||||||
meshGenerationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{
|
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, 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, 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, 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, 3, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||||
new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,4,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);
|
createDescriptorSets(VkCtx);
|
||||||
|
|
@ -124,10 +120,20 @@ public class SharedVoxelTerrainResources {
|
||||||
|
|
||||||
DescriptorSet meshSet = allocator.AddDescriptorSet(device, DESC_ID_MESH, meshGenerationLayout);
|
DescriptorSet meshSet = allocator.AddDescriptorSet(device, DESC_ID_MESH, meshGenerationLayout);
|
||||||
meshSet.SetBuffer(device, voxelData, voxelData.GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
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.facePool(), meshPool.facePool().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(), 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(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||||
meshSet.SetBuffer(device, counters, counters.GetRequestedSize(), 4, 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() {
|
public VoxelMeshPool meshPool() {
|
||||||
|
|
@ -174,6 +180,7 @@ public class SharedVoxelTerrainResources {
|
||||||
resetLayout.CleanUp(VkCtx);
|
resetLayout.CleanUp(VkCtx);
|
||||||
voxelGenerationLayout.CleanUp(VkCtx);
|
voxelGenerationLayout.CleanUp(VkCtx);
|
||||||
meshGenerationLayout.CleanUp(VkCtx);
|
meshGenerationLayout.CleanUp(VkCtx);
|
||||||
|
faceGraphicsLayout.CleanUp(VkCtx);
|
||||||
|
|
||||||
voxelData.cleanup(VkCtx);
|
voxelData.cleanup(VkCtx);
|
||||||
counters.cleanup(VkCtx);
|
counters.cleanup(VkCtx);
|
||||||
|
|
|
||||||
|
|
@ -30,16 +30,15 @@ public class VoxelChunkGenerator {
|
||||||
|
|
||||||
ByteBuffer pushConstants = stack.malloc(SharedVoxelTerrainResources.TERRAIN_GENERATION_PUSH_CONSTANT_SIZE);
|
ByteBuffer pushConstants = stack.malloc(SharedVoxelTerrainResources.TERRAIN_GENERATION_PUSH_CONSTANT_SIZE);
|
||||||
|
|
||||||
int vertexFloatOffset = (int) (chunk.vertexOffsetBytes() / Float.BYTES);
|
int indirectCommandIndex = (int) (chunk.indirectCommandOffsetBytes() / VoxelMeshPool.DRAW_INDIRECT_COMMAND_SIZE);
|
||||||
int indexOffset = (int) (chunk.indexOffsetBytes() / Integer.BYTES);
|
int faceOffset = (int) (chunk.faceOffsetBytes() / VoxelMeshPool.FACE_RECORD_SIZE_BYTES);
|
||||||
int indirectCommandIndex = (int) (chunk.indirectCommandOffsetBytes() / VoxelMeshPool.DRAW_INDEXED_INDIRECT_COMMAND_SIZE);
|
|
||||||
|
|
||||||
pushConstants.putInt(0, chunk.position().x);
|
pushConstants.putInt(0, chunk.position().x);
|
||||||
pushConstants.putInt(4, chunk.position().y);
|
pushConstants.putInt(4, chunk.position().y);
|
||||||
pushConstants.putInt(8, chunk.position().z);
|
pushConstants.putInt(8, chunk.position().z);
|
||||||
pushConstants.putInt(12, chunk.slot());
|
pushConstants.putInt(12, chunk.slot());
|
||||||
pushConstants.putInt(16, vertexFloatOffset);
|
pushConstants.putInt(16, faceOffset);
|
||||||
pushConstants.putInt(20, indexOffset);
|
pushConstants.putInt(20, 0);
|
||||||
pushConstants.putInt(24, indirectCommandIndex);
|
pushConstants.putInt(24, indirectCommandIndex);
|
||||||
pushConstants.putInt(28, 0);
|
pushConstants.putInt(28, 0);
|
||||||
|
|
||||||
|
|
@ -101,19 +100,16 @@ public class VoxelChunkGenerator {
|
||||||
new long[]{
|
new long[]{
|
||||||
resources.voxelData().GetBuffer(),
|
resources.voxelData().GetBuffer(),
|
||||||
resources.counters().GetBuffer(),
|
resources.counters().GetBuffer(),
|
||||||
resources.meshPool().vertexPoolHandle(),
|
resources.meshPool().facePoolHandle(),
|
||||||
resources.meshPool().indexPoolHandle(),
|
|
||||||
resources.meshPool().indirectPoolHandle()
|
resources.meshPool().indirectPoolHandle()
|
||||||
},
|
},
|
||||||
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||||
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_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT,
|
||||||
VK_ACCESS_2_SHADER_WRITE_BIT,
|
VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||||
VK_ACCESS_2_SHADER_READ_BIT |
|
VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
|
||||||
VK_ACCESS_2_SHADER_WRITE_BIT |
|
VK_ACCESS_2_SHADER_READ_BIT |
|
||||||
VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT |
|
|
||||||
VK_ACCESS_2_INDEX_READ_BIT |
|
|
||||||
VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT
|
VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.Logic.Rendering.VulkanContext;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
import org.joml.Vector3i;
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
|
@ -13,24 +15,16 @@ import static org.lwjgl.vulkan.VK13.*;
|
||||||
public class VoxelMeshPool{
|
public class VoxelMeshPool{
|
||||||
public static final int CHUNK_SIZE = 16;
|
public static final int CHUNK_SIZE = 16;
|
||||||
|
|
||||||
public static final int FLOATS_PER_VERTEX = 14;
|
public static final int MAX_VISIBLE_FACES_PER_CHUNK = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 6;
|
||||||
public static final int VERTEX_SIZE_BYTES = FLOATS_PER_VERTEX * Float.BYTES;
|
public static final int FACE_RECORD_SIZE_BYTES = Integer.BYTES;
|
||||||
|
public static final int DRAW_INDIRECT_COMMAND_SIZE = 4 * Integer.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;
|
|
||||||
|
|
||||||
private final int maxChunks;
|
private final int maxChunks;
|
||||||
|
|
||||||
private final long vertexSlotSizeBytes;
|
private final long faceSlotSizeBytes;
|
||||||
private final long indexSlotSizeBytes;
|
|
||||||
private final long indirectSlotSizeBytes;
|
private final long indirectSlotSizeBytes;
|
||||||
|
|
||||||
private final VulkanBuffer vertexPool;
|
private final VulkanBuffer facePool;
|
||||||
private final VulkanBuffer indexPool;
|
|
||||||
private final VulkanBuffer indirectPool;
|
private final VulkanBuffer indirectPool;
|
||||||
|
|
||||||
private final Queue<Integer> freeSlots = new ArrayDeque<>();
|
private final Queue<Integer> freeSlots = new ArrayDeque<>();
|
||||||
|
|
@ -38,19 +32,14 @@ public class VoxelMeshPool{
|
||||||
public VoxelMeshPool(VulkanContext VkCtx, int maxChunks) {
|
public VoxelMeshPool(VulkanContext VkCtx, int maxChunks) {
|
||||||
this.maxChunks = maxChunks;
|
this.maxChunks = maxChunks;
|
||||||
|
|
||||||
this.vertexSlotSizeBytes = (long) MAX_VERTICES_PER_CHUNK * VERTEX_SIZE_BYTES;
|
this.faceSlotSizeBytes = (long) MAX_VISIBLE_FACES_PER_CHUNK * FACE_RECORD_SIZE_BYTES;
|
||||||
this.indexSlotSizeBytes = (long) MAX_INDICES_PER_CHUNK * INDEX_SIZE_BYTES;
|
this.indirectSlotSizeBytes = DRAW_INDIRECT_COMMAND_SIZE;
|
||||||
this.indirectSlotSizeBytes = DRAW_INDEXED_INDIRECT_COMMAND_SIZE;
|
|
||||||
|
|
||||||
long vertexPoolSize = vertexSlotSizeBytes * maxChunks;
|
long facePoolSize = faceSlotSizeBytes * maxChunks;
|
||||||
long indexPoolSize = indexSlotSizeBytes * maxChunks;
|
|
||||||
long indirectPoolSize = indirectSlotSizeBytes * maxChunks;
|
long indirectPoolSize = indirectSlotSizeBytes * maxChunks;
|
||||||
|
facePool = new VulkanBuffer(VkCtx,facePoolSize,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
vertexPool = new VulkanBuffer(VkCtx,vertexPoolSize,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);
|
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,
|
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);
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,0,0);
|
||||||
|
|
@ -66,44 +55,44 @@ public class VoxelMeshPool{
|
||||||
if (slot == null) {
|
if (slot == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return new RenderChunk(
|
||||||
return new RenderChunk(new Vector3i(position),slot, vertexOffsetBytes(slot),indexOffsetBytes(slot),MAX_INDICES_PER_CHUNK,indirectCommandOffsetBytes(slot));
|
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) {
|
public void free(RenderChunk chunk) {
|
||||||
freeSlots.add(chunk.slot());
|
freeSlots.add(chunk.slot());
|
||||||
}
|
}
|
||||||
|
|
||||||
public long vertexOffsetBytes(int slot) {
|
public long faceOffsetBytes(int slot) {
|
||||||
return vertexSlotSizeBytes * slot;
|
return faceSlotSizeBytes * slot;
|
||||||
}
|
|
||||||
|
|
||||||
public long indexOffsetBytes(int slot) {
|
|
||||||
return indexSlotSizeBytes * slot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long indirectCommandOffsetBytes(int slot) {
|
public long indirectCommandOffsetBytes(int slot) {
|
||||||
return indirectSlotSizeBytes * slot;
|
return indirectSlotSizeBytes * slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VulkanBuffer vertexPool() {
|
public VulkanBuffer facePool() {
|
||||||
return vertexPool;
|
return facePool;
|
||||||
}
|
|
||||||
|
|
||||||
public VulkanBuffer indexPool() {
|
|
||||||
return indexPool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public VulkanBuffer indirectPool() {
|
public VulkanBuffer indirectPool() {
|
||||||
return indirectPool;
|
return indirectPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long vertexPoolHandle() {
|
public long facePoolHandle() {
|
||||||
return vertexPool.GetBuffer();
|
return facePool.GetBuffer();
|
||||||
}
|
|
||||||
|
|
||||||
public long indexPoolHandle() {
|
|
||||||
return indexPool.GetBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long indirectPoolHandle() {
|
public long indirectPoolHandle() {
|
||||||
|
|
@ -119,8 +108,7 @@ public class VoxelMeshPool{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup(VulkanContext VkCtx) {
|
public void cleanup(VulkanContext VkCtx) {
|
||||||
vertexPool.cleanup(VkCtx);
|
facePool.cleanup(VkCtx);
|
||||||
indexPool.cleanup(VkCtx);
|
|
||||||
indirectPool.cleanup(VkCtx);
|
indirectPool.cleanup(VkCtx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ public final class VoxelTerrainHeightSampler {
|
||||||
double minHeight = minHeightForChunkXZ(chunkX, chunkZ, chunkSize);
|
double minHeight = minHeightForChunkXZ(chunkX, chunkZ, chunkSize);
|
||||||
double maxHeight = maxHeightForChunkXZ(chunkX, chunkZ, chunkSize);
|
double maxHeight = maxHeightForChunkXZ(chunkX, chunkZ, chunkSize);
|
||||||
|
|
||||||
double safetyPadding = 32.0;
|
double safetyPadding = 16.0;
|
||||||
|
|
||||||
if (chunkMinY > maxHeight + safetyPadding) {
|
if (chunkMinY > maxHeight + safetyPadding) {
|
||||||
return VoxelChunkVisibility.EMPTY_AIR;
|
return VoxelChunkVisibility.EMPTY_AIR;
|
||||||
|
|
|
||||||
|
|
@ -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.Pipeline.Pipeline;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.MaterialsCache;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.MaterialsCache;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer;
|
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.joml.Vector3i;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.joml.Vector4f;
|
||||||
import org.lwjgl.vulkan.VkCommandBuffer;
|
import org.lwjgl.vulkan.VkCommandBuffer;
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.LongBuffer;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
import static org.lwjgl.vulkan.VK13.*;
|
import static org.lwjgl.vulkan.VK13.*;
|
||||||
|
|
||||||
public class VoxelWorldManager {
|
public class VoxelWorldManager {
|
||||||
private static final int MAX_RESIDENT_CHUNKS = 512 * 24;
|
private static final int MAX_RESIDENT_CHUNKS = 8192 * 2;
|
||||||
private static final int MAX_CHUNK_GENERATIONS_PER_FRAME = 32;
|
private static final int MAX_CHUNK_GENERATIONS_PER_FRAME = 256;
|
||||||
|
|
||||||
private static final ConcurrentLinkedQueue<Vector3i> RequestedChunks = new ConcurrentLinkedQueue<>();
|
private static final ConcurrentLinkedQueue<Vector3i> RequestedChunks = new ConcurrentLinkedQueue<>();
|
||||||
private static final ConcurrentHashMap<Vector3i, RenderChunk> RenderChunks = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<Vector3i, RenderChunk> RenderChunks = new ConcurrentHashMap<>();
|
||||||
|
|
@ -41,8 +40,8 @@ public class VoxelWorldManager {
|
||||||
Generator = new VoxelChunkGenerator(Resources);
|
Generator = new VoxelChunkGenerator(Resources);
|
||||||
|
|
||||||
GraphicsPushConstants = org.lwjgl.system.MemoryUtil.memAlloc(
|
GraphicsPushConstants = org.lwjgl.system.MemoryUtil.memAlloc(
|
||||||
net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.MATRIX4X4_SIZE +
|
VulkanUtils.MATRIX4X4_SIZE +
|
||||||
net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.INT_SIZE
|
VulkanUtils.INT_SIZE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +115,7 @@ public class VoxelWorldManager {
|
||||||
// VoxelChunkGenerator.CHUNK_SIZE
|
// VoxelChunkGenerator.CHUNK_SIZE
|
||||||
// );
|
// );
|
||||||
//
|
//
|
||||||
// if (visibility != VoxelChunkVisibility.SURFACE) {
|
// if (visibility == VoxelChunkVisibility.EMPTY_AIR) {
|
||||||
// CulledChunks.put(new Vector3i(position), visibility);
|
// CulledChunks.put(new Vector3i(position), visibility);
|
||||||
// continue;
|
// 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) {
|
if (Resources == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int terrainMaterialIndex = materialsCache.GetPosition("VoxelTerrain");
|
int terrainMaterialIndex;
|
||||||
|
|
||||||
if (terrainMaterialIndex < 0) {
|
if (materialsCache.GetPosition("VoxelTerrain") < 0) {
|
||||||
terrainMaterialIndex = 0;
|
terrainMaterialIndex = 0;
|
||||||
|
} else {
|
||||||
|
terrainMaterialIndex = materialsCache.GetPosition("VoxelTerrain");
|
||||||
}
|
}
|
||||||
|
|
||||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
RenderChunks.forEach((position, chunk) -> {
|
||||||
Matrix4f identity = new Matrix4f().identity();
|
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);
|
private static void SetPushConstants(VkCommandBuffer CmdHandle, Vector4f ModelMatrix, Pipeline VkPipeline, int MaterialIndex, boolean shadowPass){
|
||||||
GraphicsPushConstants.putInt(
|
ModelMatrix.get(0,GraphicsPushConstants);
|
||||||
net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.MATRIX4X4_SIZE,
|
GraphicsPushConstants.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex);
|
||||||
terrainMaterialIndex
|
vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0,
|
||||||
);
|
GraphicsPushConstants.slice(0,VulkanUtils.MATRIX4X4_SIZE));
|
||||||
|
if(!shadowPass){
|
||||||
vkCmdPushConstants(CommandBuffer, graphicsPipeline.GetVulkanPipelineLayout(),VK_SHADER_STAGE_VERTEX_BIT,
|
vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE,
|
||||||
0,GraphicsPushConstants.slice(
|
GraphicsPushConstants.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void UnloadFarChunks(Vector3i centerChunk, int unloadRadius) {
|
public static void UnloadFarChunks(Vector3i centerChunk, int unloadRadius) {
|
||||||
int maxDistSq = unloadRadius * unloadRadius;
|
int maxDistSq = unloadRadius * unloadRadius;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 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_GLSL = "resources/EngineResources/shaders/scene_vertex.glsl";
|
||||||
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
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 final VulkanBuffer[] BufferViewMatrices;
|
||||||
private Pipeline VkPipeline;
|
private Pipeline VkPipeline;
|
||||||
private Pipeline VkPipelineOpaque;
|
private Pipeline VkPipelineOpaque;
|
||||||
|
|
@ -166,6 +169,19 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
|
||||||
shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,2);
|
shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,2);
|
||||||
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2);
|
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2);
|
||||||
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
|
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[]{
|
DescriptorSetLayout[] skyboxLayouts = new DescriptorSetLayout[]{
|
||||||
descriptorLayoutVertexUniform,
|
descriptorLayoutVertexUniform,
|
||||||
|
|
@ -229,11 +245,11 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
|
||||||
|
|
||||||
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){
|
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){
|
||||||
if(EngineConfig.getInstance().RecompileShaders()){
|
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);
|
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[]{
|
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)
|
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){
|
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 vertexBufferStructure = new VertexBufferStructure();
|
||||||
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{
|
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
|
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());
|
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipeline() : VkPipeline.GetVulkanPipeline());
|
||||||
|
|
||||||
DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator();
|
DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator();
|
||||||
|
|
@ -377,10 +416,20 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
|
||||||
.put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet())
|
.put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet())
|
||||||
.put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet());
|
.put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet());
|
||||||
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
|
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
|
||||||
|
|
||||||
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false);
|
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();
|
Matrix4f skyboxViewMatrix = new Matrix4f().identity();
|
||||||
skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix());
|
skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix());
|
||||||
|
|
@ -542,6 +591,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
|
||||||
public void cleanup(VulkanContext VkCtx){
|
public void cleanup(VulkanContext VkCtx){
|
||||||
VkPipeline.CleanUp(VkCtx);
|
VkPipeline.CleanUp(VkCtx);
|
||||||
// VkSkyboxPipeline.CleanUp(VkCtx);
|
// VkSkyboxPipeline.CleanUp(VkCtx);
|
||||||
|
VkVoxelPipeline.CleanUp(VkCtx);
|
||||||
VkPipelineOpaque.CleanUp(VkCtx);
|
VkPipelineOpaque.CleanUp(VkCtx);
|
||||||
VkPipelineTranslucent.CleanUp(VkCtx);
|
VkPipelineTranslucent.CleanUp(VkCtx);
|
||||||
Arrays.asList(BufferViewMatrices).forEach(b -> b.cleanup(VkCtx));
|
Arrays.asList(BufferViewMatrices).forEach(b -> b.cleanup(VkCtx));
|
||||||
|
|
|
||||||
|
|
@ -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.Actor3D;
|
||||||
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3DElement;
|
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3DElement;
|
||||||
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
|
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.Computing.VoxelTerrainGeneration.VoxelWorldManager;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.RenderPasses.DeferredRendering.DeferredSceneRender;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.RenderPasses.DeferredRendering.DeferredSceneRender;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
|
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";
|
public static String SkyBoxID = "SKYBOX_TEXTURE";
|
||||||
private static final int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE;
|
private static final int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE;
|
||||||
private final VulkanBuffer BufferProjectionMatrix;
|
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 descriptorLayoutFragStorage;
|
||||||
private final DescriptorSetLayout descriptorLayoutTexture;
|
private final DescriptorSetLayout descriptorLayoutTexture;
|
||||||
private final DescriptorSetLayout descriptorLayoutVertexUniform;
|
private final DescriptorSetLayout descriptorLayoutVertexUniform;
|
||||||
|
|
@ -169,6 +173,19 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
|
||||||
shaderModules = CreateShaderModules(vulkanContext,2);
|
shaderModules = CreateShaderModules(vulkanContext,2);
|
||||||
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2);
|
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2);
|
||||||
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
|
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[]{
|
DescriptorSetLayout[] skyboxLayouts = new DescriptorSetLayout[]{
|
||||||
descriptorLayoutVertexUniform,
|
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);
|
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){
|
private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue ClearValue){
|
||||||
return VkRenderingAttachmentInfo.calloc(1)
|
return VkRenderingAttachmentInfo.calloc(1)
|
||||||
|
|
@ -241,11 +292,11 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
|
||||||
|
|
||||||
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){
|
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){
|
||||||
if(EngineConfig.getInstance().RecompileShaders()){
|
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);
|
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[]{
|
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)
|
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());
|
.put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet());
|
||||||
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
|
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
|
||||||
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false);
|
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();
|
Matrix4f skyboxViewMatrix = new Matrix4f().identity();
|
||||||
skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix());
|
skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix());
|
||||||
|
|
@ -530,6 +593,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
|
||||||
VkPipeline.CleanUp(VkCtx);
|
VkPipeline.CleanUp(VkCtx);
|
||||||
VkPipelineTranslucent.CleanUp(VkCtx);
|
VkPipelineTranslucent.CleanUp(VkCtx);
|
||||||
VkPipelineOpaque.CleanUp(VkCtx);
|
VkPipelineOpaque.CleanUp(VkCtx);
|
||||||
|
VkVoxelPipeline.CleanUp(VkCtx);
|
||||||
Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx));
|
Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx));
|
||||||
RenderInfo.free();
|
RenderInfo.free();
|
||||||
AttachmentInfoColour.free();
|
AttachmentInfoColour.free();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public class AmbientOcclusionRenderer {
|
||||||
VulkanUtils.VEC4_SIZE + // screenSize.xy, radius, bias
|
VulkanUtils.VEC4_SIZE + // screenSize.xy, radius, bias
|
||||||
VulkanUtils.VEC4_SIZE; // kernelSize + padding
|
VulkanUtils.VEC4_SIZE; // kernelSize + padding
|
||||||
private static final int SSAO_KERNEL_SIZE = 64;
|
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 float SSAO_BIAS = 0.025f;
|
||||||
private static final long SSAO_KERNEL_BUFFER_SIZE = SSAO_KERNEL_SIZE * 4L * VulkanUtils.FLOAT_SIZE;
|
private static final long SSAO_KERNEL_BUFFER_SIZE = SSAO_KERNEL_SIZE * 4L * VulkanUtils.FLOAT_SIZE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.Pipeline;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
|
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.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.Shader.*;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VertexBufferStructure;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VertexBufferStructure;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*;
|
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 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_GLSL = "resources/EngineResources/shaders/shadow_vertex.glsl";
|
||||||
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
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 CascadeShadows[] cascadeShadows;
|
||||||
private final VkClearValue ClearValueColour;
|
private final VkClearValue ClearValueColour;
|
||||||
private final VkClearValue ClearValueDepth;
|
private final VkClearValue ClearValueDepth;
|
||||||
|
|
@ -90,6 +92,7 @@ public class ShadowRenderer {
|
||||||
private VkRenderingAttachmentInfo depthAttachmentInfo;
|
private VkRenderingAttachmentInfo depthAttachmentInfo;
|
||||||
private final DescriptorSetLayout descLayoutFrgStorage;
|
private final DescriptorSetLayout descLayoutFrgStorage;
|
||||||
private Pipeline pipeline;
|
private Pipeline pipeline;
|
||||||
|
private Pipeline pipelinePacked;
|
||||||
private final VulkanBuffer[] prjBuffers;
|
private final VulkanBuffer[] prjBuffers;
|
||||||
private final ByteBuffer pushConstBuff;
|
private final ByteBuffer pushConstBuff;
|
||||||
private VkRenderingInfo renderingInfo;
|
private VkRenderingInfo renderingInfo;
|
||||||
|
|
@ -180,6 +183,14 @@ public class ShadowRenderer {
|
||||||
pipeline = createPipeline(VulkanContext, shaderModules, new DescriptorSetLayout[]{uniformGeomDescriptorSetLayout, textDescriptorSetLayout,
|
pipeline = createPipeline(VulkanContext, shaderModules, new DescriptorSetLayout[]{uniformGeomDescriptorSetLayout, textDescriptorSetLayout,
|
||||||
descLayoutFrgStorage});
|
descLayoutFrgStorage});
|
||||||
Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VulkanContext));
|
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];
|
cascadeShadows = new CascadeShadows[VulkanUtils.MAX_IN_FLIGHT];
|
||||||
for (int i = 0; i < VulkanUtils.MAX_IN_FLIGHT; i++) {
|
for (int i = 0; i < VulkanUtils.MAX_IN_FLIGHT; i++) {
|
||||||
|
|
@ -238,6 +249,32 @@ public class ShadowRenderer {
|
||||||
return pipeline;
|
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,
|
private static VkRenderingInfo createRenderInfo(VkRenderingAttachmentInfo.Buffer colorAttachmentInfo,
|
||||||
VkRenderingAttachmentInfo depthAttachments) {
|
VkRenderingAttachmentInfo depthAttachments) {
|
||||||
var result = VkRenderingInfo.calloc().sType$Default();
|
var result = VkRenderingInfo.calloc().sType$Default();
|
||||||
|
|
@ -254,7 +291,18 @@ public class ShadowRenderer {
|
||||||
}
|
}
|
||||||
return result;
|
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) {
|
private static ShaderModule[] createShaderModules(VulkanContext VulkanContext) {
|
||||||
if (EngineConfig.getInstance().RecompileShaders()) {
|
if (EngineConfig.getInstance().RecompileShaders()) {
|
||||||
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
|
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
|
||||||
|
|
@ -271,6 +319,7 @@ public class ShadowRenderer {
|
||||||
public void cleanup(VulkanContext VulkanContext) {
|
public void cleanup(VulkanContext VulkanContext) {
|
||||||
AllowShadowRendering(false);
|
AllowShadowRendering(false);
|
||||||
pipeline.CleanUp(VulkanContext);
|
pipeline.CleanUp(VulkanContext);
|
||||||
|
pipelinePacked.CleanUp(VulkanContext);
|
||||||
uniformGeomDescriptorSetLayout.CleanUp(VulkanContext);
|
uniformGeomDescriptorSetLayout.CleanUp(VulkanContext);
|
||||||
descLayoutFrgStorage.CleanUp(VulkanContext);
|
descLayoutFrgStorage.CleanUp(VulkanContext);
|
||||||
textDescriptorSetLayout.CleanUp(VulkanContext);
|
textDescriptorSetLayout.CleanUp(VulkanContext);
|
||||||
|
|
@ -394,7 +443,15 @@ public class ShadowRenderer {
|
||||||
vkCmdDrawIndexed(cmdHandle, vulkanMesh.IndicesCount(), 1, 0, 0, 0);
|
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);
|
vkCmdEndRendering(cmdHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue