Skip to content

Commit

Permalink
Chunk mesh cleanup for Smooth Lightning
Browse files Browse the repository at this point in the history
  • Loading branch information
Jukitsu committed Nov 26, 2023
1 parent 8ac9b56 commit 25b7dea
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 57 deletions.
2 changes: 2 additions & 0 deletions Jukcraft/Jukcraft.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
<ClInclude Include="src\models\Model.h" />
<ClInclude Include="src\pch.h" />
<ClInclude Include="src\physics\constants.h" />
<ClInclude Include="src\renderer\chunk\Mesh.h" />
<ClInclude Include="src\renderer\Renderer.h" />
<ClInclude Include="src\renderer\gfx\buffers\DynamicBuffer.h" />
<ClInclude Include="src\renderer\gfx\buffers\StagingBuffer.h" />
Expand Down Expand Up @@ -193,6 +194,7 @@
<ClCompile Include="src\pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\renderer\chunk\Mesh.cpp" />
<ClCompile Include="src\renderer\gfx\buffers\DynamicBuffer.cpp" />
<ClCompile Include="src\vendor\stb\stb_build.cpp" />
<ClCompile Include="src\world\LightEngine.cpp" />
Expand Down
2 changes: 2 additions & 0 deletions Jukcraft/Jukcraft.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
<ClInclude Include="src\world\chunk\util.h">
<Filter>world\chunk</Filter>
</ClInclude>
<ClInclude Include="src\renderer\chunk\Mesh.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\core\App.cpp">
Expand Down Expand Up @@ -179,5 +180,6 @@
<ClCompile Include="src\world\chunk\ChunkManager.cpp">
<Filter>world\chunk</Filter>
</ClCompile>
<ClCompile Include="src\renderer\chunk\Mesh.cpp" />
</ItemGroup>
</Project>
90 changes: 90 additions & 0 deletions Jukcraft/src/renderer/chunk/Mesh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include "pch.h"
#include "renderer/chunk/Mesh.h"

namespace Jukcraft {
static constexpr float smooth(float a, float b, float c, float d) {
if (!(a && b && c && d)) {
std::array<float, 4> l = {
a,
std::numeric_limits<float>::infinity(),
std::numeric_limits<float>::infinity(),
std::numeric_limits<float>::infinity()
};
if (b)
l[1] = b;
if (c)
l[2] = c;
if (d)
l[3] = d;
float min_val = *std::min_element(l.begin(), l.end());
float a = std::max(a, min_val);
float b = std::max(b, min_val);
float c = std::max(c, min_val);
float d = std::max(d, min_val);
return a + b + c + d / 4.0f;
}

}

float ao(float s1, float s2, float c) {
if (s1 && s2)
return 0.25;

return 1.0f - (s1 + s2 + c) / 4.0f;
}

Mesh::Mesh(size_t size) :size(size) {
vbo.allocate(CHUNK_DIM * CHUNK_DIM * CHUNK_HEIGHT * 24, nullptr);

vao.bindLayout(gfx::VertexArrayLayout{
{
{ 1, false },
{ 1, false }
}
});
vao.bindVertexBuffer(vbo.getTargetBuffer(), 0, gfx::VertexBufferLayout{
{{ 0, 0 }, { 1, offsetof(VertexData, lightData)}},
0,
sizeof(VertexData)
});
vao.bindIndexBuffer(Renderer::GetChunkIbo());

icbo.allocate(sizeof(DrawIndirectCommand), nullptr);
}

Mesh::~Mesh() {

}

void Mesh::begin() {
vbo.beginEditRegion(0, size);
quadCount = 0;
}

void Mesh::pushQuad(const Quad& quad, const glm::uvec3& localPos, uint8_t textureID, uint8_t light) {
for (const Vertex& vertex : quad.vertices) {
uint32_t v = ((vertex.pos.y + localPos.y) << 22) | ((vertex.pos.x + localPos.x) << 17) | ((vertex.pos.z + localPos.z) << 12) | (vertex.texUV << 10) | (textureID << 2) | (vertex.shading);
vbo.push({ v, light });
}
quadCount++;
}

void Mesh::end() {
vbo.endEditRegion();
DrawIndirectCommand cmd;
cmd.count = quadCount * 6;
cmd.instanceCount = 1;
cmd.firstIndex = 0;
cmd.baseVertex = 0;
cmd.baseInstance = 0;
icbo.beginEditRegion(0, 1);
icbo.editRegion(0, 1, &cmd);
icbo.endEditRegion();
}

void Mesh::draw() {
Renderer::MultiDrawElementsIndirect(vao, icbo.getTargetBuffer());
}


}
25 changes: 25 additions & 0 deletions Jukcraft/src/renderer/chunk/Mesh.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include "renderer/gfx/buffers/DynamicBuffer.h"
#include "blocks/Block.h"

namespace Jukcraft {

class Mesh {
public:
Mesh(size_t size);
~Mesh();
void begin();
void pushQuad(const Quad& quad, const glm::uvec3& localPos, uint8_t textureID, uint8_t light);
void end();
void draw();
private:
size_t size;
size_t quadCount;
gfx::VertexArray vao;

gfx::DynamicBuffer<VertexData> vbo;
gfx::DynamicBuffer<DrawIndirectCommand> icbo;
std::vector<uint32_t> vertices;
std::vector<uint32_t> indices;
};
}
62 changes: 23 additions & 39 deletions Jukcraft/src/world/chunk/Chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
#include "renderer/Renderer.h"
#include "world/chunk/Chunk.h"


namespace Jukcraft {


Chunk::Chunk(const glm::ivec2& chunkPos, const std::vector<Block>& blockTypes)
:blockTypes(blockTypes), chunkPos(chunkPos)
:blockTypes(blockTypes), chunkPos(chunkPos), mesh(CHUNK_DIM * CHUNK_DIM * CHUNK_HEIGHT * 6 * 4)
{
blocks = new BlockID * *[CHUNK_HEIGHT];
for (size_t j = 0; j < CHUNK_HEIGHT; j++) {
Expand All @@ -15,6 +18,17 @@ namespace Jukcraft {
}
}

for (uint8_t ly = 0; ly < CHUNK_HEIGHT / 2; ly++)
for (uint8_t lx = 0; lx < CHUNK_DIM; lx++)
for (uint8_t lz = 0; lz < CHUNK_DIM; lz++) {
if (ly == CHUNK_HEIGHT / 2 - 1)
setBlock(glm::uvec3(lx, ly, lz), 2);
else if (ly >= CHUNK_HEIGHT / 2 - 3 && ly < CHUNK_HEIGHT / 2 - 1)
setBlock(glm::uvec3(lx, ly, lz), 3);
else
setBlock(glm::uvec3(lx, ly, lz), 1);
}

lightMap = new uint8_t * *[CHUNK_HEIGHT];
for (size_t j = 0; j < CHUNK_HEIGHT; j++) {
lightMap[j] = new uint8_t * [CHUNK_DIM];
Expand All @@ -24,22 +38,6 @@ namespace Jukcraft {
}
}

vbo.allocate(CHUNK_DIM * CHUNK_DIM * CHUNK_HEIGHT * 24, nullptr);

vao.bindLayout(gfx::VertexArrayLayout{
{
{ 1, false },
{ 1, false }
}
});
vao.bindVertexBuffer(vbo.getTargetBuffer(), 0, gfx::VertexBufferLayout{
{{ 0, 0 }, { 1, offsetof(VertexData, lightData)}},
0,
sizeof(VertexData)
});
vao.bindIndexBuffer(Renderer::GetChunkIbo());

icbo.allocate(sizeof(DrawIndirectCommand), nullptr);
}

Chunk::~Chunk() {
Expand Down Expand Up @@ -68,16 +66,10 @@ namespace Jukcraft {
}


void Chunk::pushQuad(const Quad& quad, const glm::uvec3& localPos, uint8_t textureID, uint8_t light) {
for (const Vertex& vertex : quad.vertices) {
uint32_t v = ((vertex.pos.y + localPos.y) << 22) | ((vertex.pos.x + localPos.x) << 17) | ((vertex.pos.z + localPos.z) << 12) | (vertex.texUV << 10) | (textureID << 2) | (vertex.shading);
vbo.push({ v, light });
}
}

void Chunk::buildCubeLayer() {
vbo.beginEditRegion(0, CHUNK_DIM * CHUNK_DIM * CHUNK_HEIGHT * 24);
uint32_t quad_count = 0;
mesh.begin();
uint32_t quadCount = 0;
for (uint8_t y = 0; y < CHUNK_HEIGHT; y++)
for (uint8_t x = 0; x < CHUNK_DIM; x++)
for (uint8_t z = 0; z < CHUNK_DIM; z++) {
Expand All @@ -96,24 +88,16 @@ namespace Jukcraft {
Chunk* neighbourChunk = getNeighbourChunk(localPos + IDIRECTIONS[i]);
if (neighbourChunk)
light = neighbourChunk->getRawLight(ToLocalPos(localPos + IDIRECTIONS[i]));
pushQuad(type.getModel().getQuads()[i], localPos, type.getTextureLayout()[i], light);
quad_count++;
mesh.pushQuad(type.getModel().getQuads()[i], localPos, type.getTextureLayout()[i], light);
quadCount++;
}
}
}

}
vbo.endEditRegion();

DrawIndirectCommand cmd;
cmd.count = quad_count * 6;
cmd.instanceCount = 1;
cmd.firstIndex = 0;
cmd.baseVertex = 0;
cmd.baseInstance = 0;
icbo.beginEditRegion(0, 1);
icbo.editRegion(0, 1, &cmd);
icbo.endEditRegion();
mesh.end();


drawable = true;
}

Expand Down Expand Up @@ -143,6 +127,6 @@ namespace Jukcraft {
void Chunk::drawCubeLayer() {
if (!drawable)
return;
Renderer::MultiDrawElementsIndirect(vao, icbo.getTargetBuffer());
mesh.draw();
}
}
11 changes: 3 additions & 8 deletions Jukcraft/src/world/chunk/Chunk.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once
#include "renderer/Renderer.h"
#include "renderer/gfx/buffers/DynamicBuffer.h"
#include "blocks/Block.h"
#include "renderer/chunk/Mesh.h"
#include <glm/gtc/integer.hpp>

namespace Jukcraft {
Expand Down Expand Up @@ -99,7 +98,6 @@ namespace Jukcraft {
lightMap[(uint8_t)localPos.y][(uint8_t)localPos.x][(uint8_t)localPos.z] = (lightMap[(uint8_t)localPos.y][(uint8_t)localPos.x][(uint8_t)localPos.z] & 0xF) | (value << 4);
}
private:
void pushQuad(const Quad& quad, const glm::uvec3& localPos, uint8_t textureID, uint8_t light);
struct {
std::weak_ptr<Chunk> east;
std::weak_ptr<Chunk> west;
Expand All @@ -111,13 +109,10 @@ namespace Jukcraft {

uint8_t*** lightMap;

Mesh mesh;

const std::vector<Block>& blockTypes;
gfx::VertexArray vao;

gfx::DynamicBuffer<VertexData> vbo;
gfx::DynamicBuffer<DrawIndirectCommand> icbo;
std::vector<uint32_t> vertices;
std::vector<uint32_t> indices;
bool drawable = false;
glm::ivec2 chunkPos;

Expand Down
10 changes: 0 additions & 10 deletions Jukcraft/src/world/chunk/ChunkManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@ namespace Jukcraft {
= std::make_shared<Chunk>(glm::ivec2(x, z), blocks);
chunksToUpdates.insert(chunk);
chunksToLight.insert(chunk);
for (uint8_t ly = 0; ly < CHUNK_HEIGHT / 2; ly++)
for (uint8_t lx = 0; lx < CHUNK_DIM; lx++)
for (uint8_t lz = 0; lz < CHUNK_DIM; lz++) {
if (ly == CHUNK_HEIGHT / 2 - 1)
chunk->setBlock(glm::uvec3(lx, ly, lz), std::rand() % 2 ? 2 : 0);
else if (ly >= CHUNK_HEIGHT / 2 - 3 && ly < CHUNK_HEIGHT / 2 - 1)
chunk->setBlock(glm::uvec3(lx, ly, lz), std::rand() % 2 ? 3 : 0);
else
chunk->setBlock(glm::uvec3(lx, ly, lz), std::rand() % 2 ? 1 : 0);
}
if (z > 0) {
std::shared_ptr<Chunk>& northernChunk = chunks[x][z - 1];
northernChunk->neighbourChunks.south = chunk;
Expand Down

0 comments on commit 25b7dea

Please sign in to comment.