diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index fe131b7e..77cd1a57 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -12,6 +12,7 @@ #include "../voxels/Chunk.h" #include "../typedefs.h" #include "../maths/voxmaths.h" +#include "../world/World.h" #include #include @@ -201,12 +202,12 @@ ubyte* WorldFiles::readChunkData(int x, int y, uint32_t& length){ return data; } -void WorldFiles::write(const WorldInfo info, const Content* content) { +void WorldFiles::write(const World* world, const Content* content) { path directory = getRegionsFolder(); if (!std::filesystem::is_directory(directory)) { std::filesystem::create_directories(directory); } - writeWorldInfo(info); + writeWorldInfo(world); if (generatorTestMode) return; writeIndices(content->indices); @@ -232,23 +233,23 @@ void WorldFiles::writeIndices(const ContentIndices* indices) { } } -void WorldFiles::writeWorldInfo(const WorldInfo& info) { +void WorldFiles::writeWorldInfo(const World* world) { BinaryWriter out; out.putCStr(WORLD_FORMAT_MAGIC); out.put(WORLD_FORMAT_VERSION); out.put(WORLD_SECTION_MAIN); - out.putInt64(info.seed); - out.put(info.name); + out.putInt64(world->seed); + out.put(world->name); out.put(WORLD_SECTION_DAYNIGHT); - out.putFloat32(info.daytime); - out.putFloat32(info.daytimeSpeed); + out.putFloat32(world->daytime); + out.putFloat32(world->daytimeSpeed); files::write_bytes(getWorldFile(), (const char*)out.data(), out.size()); } -bool WorldFiles::readWorldInfo(WorldInfo& info) { +bool WorldFiles::readWorldInfo(World* world) { size_t length = 0; ubyte* data = (ubyte*)files::read_bytes(getWorldFile(), length); if (data == nullptr){ @@ -262,12 +263,12 @@ bool WorldFiles::readWorldInfo(WorldInfo& info) { ubyte section = inp.get(); switch (section) { case WORLD_SECTION_MAIN: - info.seed = inp.getInt64(); - info.name = inp.getString(); + world->seed = inp.getInt64(); + world->name = inp.getString(); break; case WORLD_SECTION_DAYNIGHT: - info.daytime = inp.getFloat32(); - info.daytimeSpeed = inp.getFloat32(); + world->daytime = inp.getFloat32(); + world->daytimeSpeed = inp.getFloat32(); break; } } diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index c16ebb4a..92716e6e 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -25,6 +25,7 @@ class Player; class Chunk; class Content; class ContentIndices; +class World; struct WorldRegion { ubyte** chunksData; @@ -32,16 +33,8 @@ struct WorldRegion { bool unsaved; }; -struct WorldInfo { - std::string name; - std::filesystem::path directory; - uint64_t seed; - float daytime; - float daytimeSpeed; -}; - class WorldFiles { - void writeWorldInfo(const WorldInfo& info); + void writeWorldInfo(const World* world); std::filesystem::path getRegionsFolder() const; std::filesystem::path getRegionFile(int x, int y) const; std::filesystem::path getPlayerFile() const; @@ -58,13 +51,13 @@ public: void put(Chunk* chunk); - bool readWorldInfo(WorldInfo& info); + bool readWorldInfo(World* world); bool readPlayer(Player* player); ubyte* readChunkData(int x, int y, uint32_t& length); ubyte* getChunk(int x, int y); void writeRegion(int x, int y, WorldRegion& entry); void writePlayer(Player* player); - void write(const WorldInfo info, const Content* content); + void write(const World* world, const Content* content); void writeIndices(const ContentIndices* indices); }; diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index 915df23d..396cf623 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -30,6 +30,7 @@ toml::Wrapper create_wrapper(EngineSettings& settings) { toml::Section& graphics = wrapper.add("graphics"); graphics.add("fog-curve", &settings.graphics.fogCurve); graphics.add("backlight", &settings.graphics.backlight); + graphics.add("frustum-culling", &settings.graphics.frustumCulling); toml::Section& debug = wrapper.add("debug"); debug.add("generator-test-mode", &settings.debug.generatorTestMode); diff --git a/src/frontend/world_render.cpp b/src/frontend/WorldRenderer.cpp similarity index 54% rename from src/frontend/world_render.cpp rename to src/frontend/WorldRenderer.cpp index d49af2f8..18538123 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -1,4 +1,4 @@ -#include "world_render.h" +#include "WorldRenderer.h" #include #include @@ -22,7 +22,7 @@ #include "../world/LevelEvents.h" #include "../objects/Player.h" #include "../assets/Assets.h" -#include "../objects/player_control.h" +#include "../logic/PlayerController.h" #include "../maths/FrustumCulling.h" #include "../maths/voxmaths.h" #include "../settings.h" @@ -32,20 +32,26 @@ using glm::vec3; using glm::vec4; +using glm::mat4; using std::string; using std::shared_ptr; -WorldRenderer::WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache) - : engine(engine), level(level) { - EngineSettings& settings = engine->getSettings(); +WorldRenderer::WorldRenderer(Engine* engine, + Level* level, + const ContentGfxCache* cache) + : engine(engine), + level(level), + frustumCulling(new Frustum()), + lineBatch(new LineBatch()), + renderer( new ChunksRenderer(level, cache, engine->getSettings())) { - lineBatch = new LineBatch(4096); - renderer = new ChunksRenderer(level, cache, settings); - frustumCulling = new Frustum(); - level->events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) { - renderer->unload(chunk); - }); - skybox = new Skybox(64, engine->getAssets()->getShader("skybox_gen")); + level->events->listen(EVT_CHUNK_HIDDEN, + [this](lvl_event_type type, Chunk* chunk) { + renderer->unload(chunk); + } + ); + auto assets = engine->getAssets(); + skybox = new Skybox(64, assets->getShader("skybox_gen")); } WorldRenderer::~WorldRenderer() { @@ -55,22 +61,30 @@ WorldRenderer::~WorldRenderer() { delete frustumCulling; } -bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){ - shared_ptr chunk = level->chunks->chunks[index]; - if (!chunk->isLighted()) +bool WorldRenderer::drawChunk(size_t index, + Camera* camera, + Shader* shader, + bool culling){ + auto chunk = level->chunks->chunks[index]; + if (!chunk->isLighted()) { return false; + } shared_ptr mesh = renderer->getOrRender(chunk.get()); - if (mesh == nullptr) + if (mesh == nullptr) { return false; - - // Simple frustum culling - if (occlusion){ - vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); - vec3 max(chunk->x * CHUNK_W + CHUNK_W, chunk->top, chunk->z * CHUNK_D + CHUNK_D); + } + if (culling){ + vec3 min(chunk->x * CHUNK_W, + chunk->bottom, + chunk->z * CHUNK_D); + vec3 max(chunk->x * CHUNK_W + CHUNK_W, + chunk->top, + chunk->z * CHUNK_D + CHUNK_D); if (!frustumCulling->IsBoxVisible(min, max)) return false; } - mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1)); + vec3 coord = vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1); + mat4 model = glm::translate(mat4(1.0f), coord); shader->uniformMatrix("u_model", model); mesh->draw(); return true; @@ -78,8 +92,7 @@ bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, - Shader* shader, - bool occlusion) { + Shader* shader) { std::vector indices; for (size_t i = 0; i < chunks->volume; i++){ shared_ptr chunk = chunks->chunks[i]; @@ -87,25 +100,30 @@ void WorldRenderer::drawChunks(Chunks* chunks, continue; indices.push_back(i); } - float px = camera->position.x / (float)CHUNK_W; float pz = camera->position.z / (float)CHUNK_D; std::sort(indices.begin(), indices.end(), [this, chunks, px, pz](size_t i, size_t j) { shared_ptr a = chunks->chunks[i]; shared_ptr b = chunks->chunks[j]; - return ((a->x + 0.5f - px)*(a->x + 0.5f - px) + (a->z + 0.5f - pz)*(a->z + 0.5f - pz) > - (b->x + 0.5f - px)*(b->x + 0.5f - px) + (b->z + 0.5f - pz)*(b->z + 0.5f - pz)); + return ((a->x + 0.5f - px)*(a->x + 0.5f - px) + + (a->z + 0.5f - pz)*(a->z + 0.5f - pz) + > + (b->x + 0.5f - px)*(b->x + 0.5f - px) + + (b->z + 0.5f - pz)*(b->z + 0.5f - pz)); }); - if (occlusion) frustumCulling->update(camera->getProjView()); + bool culling = engine->getSettings().graphics.frustumCulling; + if (culling) { + frustumCulling->update(camera->getProjView()); + } chunks->visible = 0; for (size_t i = 0; i < indices.size(); i++){ - chunks->visible += drawChunk(indices[i], camera, shader, occlusion); + chunks->visible += drawChunk(indices[i], camera, shader, culling); } } -void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){ +void WorldRenderer::draw(const GfxContext& pctx, Camera* camera){ EngineSettings& settings = engine->getSettings(); skybox->refresh(level->world->daytime, fmax(1.0f, 18.0f/settings.chunks.loadDistance), 4); @@ -123,6 +141,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) Window::clearDepth(); Window::viewport(0, 0, displayWidth, displayHeight); + // Drawing background sky plane Shader* backShader = assets->getShader("background"); backShader->use(); backShader->uniformMatrix("u_view", camera->getView(false)); @@ -137,8 +156,8 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) float fogFactor = 18.0f / (float)settings.chunks.loadDistance; + // Setting up main shader shader->use(); - skybox->bind(); shader->uniformMatrix("u_proj", camera->getProjection()); shader->uniformMatrix("u_view", camera->getView()); shader->uniform1f("u_gamma", 1.0f); @@ -146,34 +165,37 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); shader->uniform3f("u_cameraPos", camera->position); shader->uniform1i("u_cubemap", 1); + { + blockid_t id = level->player->choosenBlock; + Block* block = contentIds->getBlockDef(id); + assert(block != nullptr); + float multiplier = 0.5f; + shader->uniform3f("u_torchlightColor", + block->emission[0] / 15.0f * multiplier, + block->emission[1] / 15.0f * multiplier, + block->emission[2] / 15.0f * multiplier); + shader->uniform1f("u_torchlightDistance", 6.0f); + } - Block* cblock = contentIds->getBlockDef(level->player->choosenBlock); - assert(cblock != nullptr); - float multiplier = 0.5f; - shader->uniform3f("u_torchlightColor", - cblock->emission[0] / 15.0f * multiplier, - cblock->emission[1] / 15.0f * multiplier, - cblock->emission[2] / 15.0f * multiplier); - shader->uniform1f("u_torchlightDistance", 6.0f); + // Binding main shader textures + skybox->bind(); atlas->getTexture()->bind(); - Chunks* chunks = level->chunks; - drawChunks(chunks, camera, shader, occlusion); + drawChunks(level->chunks, camera, shader); - shader->uniformMatrix("u_model", mat4(1.0f)); - - if (level->playerController->selectedBlockId != -1){ - Block* block = contentIds->getBlockDef(level->playerController->selectedBlockId); + // Selected block + if (PlayerController::selectedBlockId != -1){ + blockid_t id = PlayerController::selectedBlockId; + Block* block = contentIds->getBlockDef(id); assert(block != nullptr); - vec3 pos = level->playerController->selectedBlockPosition; - linesShader->use(); - linesShader->uniformMatrix("u_projview", camera->getProjView()); - lineBatch->lineWidth(2.0f); - + const vec3 pos = PlayerController::selectedBlockPosition; const AABB& hitbox = block->hitbox; const vec3 center = pos + hitbox.center(); const vec3 size = hitbox.size(); - lineBatch->box(center, size + vec3(0.02), vec4(0.0f, 0.0f, 0.0f, 0.5f)); + linesShader->use(); + linesShader->uniformMatrix("u_projview", camera->getProjView()); + lineBatch->lineWidth(2.0f); + lineBatch->box(center, size + vec3(0.02), vec4(0.f, 0.f, 0.f, 0.5f)); lineBatch->render(); } skybox->unbind(); @@ -191,44 +213,12 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) if (coord.z < 0) coord.z--; int cx = floordiv((int)coord.x, CHUNK_W); int cz = floordiv((int)coord.z, CHUNK_D); - /*corner*/ { - lineBatch->line( cx * CHUNK_W, 0, cz * CHUNK_D, - cx * CHUNK_W, CHUNK_H, cz * CHUNK_D, 0.8f, 0, 0.8f, 1); - lineBatch->line( cx * CHUNK_W, 0, (cz+1) * CHUNK_D, - cx * CHUNK_W, CHUNK_H, (cz+1) * CHUNK_D, 0.8f, 0, 0.8f, 1); - lineBatch->line((cx+1) * CHUNK_W, 0, cz * CHUNK_D, - (cx+1) * CHUNK_W, CHUNK_H, cz * CHUNK_D, 0.8f, 0, 0.8f, 1); - lineBatch->line((cx+1) * CHUNK_W, 0, (cz+1) * CHUNK_D, - (cx+1) * CHUNK_W, CHUNK_H, (cz+1) * CHUNK_D, 0.8f, 0, 0.8f, 1); - } - for (int i = 2; i < CHUNK_W; i+=2) { - lineBatch->line( cx * CHUNK_W + i, 0, cz * CHUNK_D, - cx * CHUNK_W + i, CHUNK_H, cz * CHUNK_D, 0, 0, 0.8f, 1); - lineBatch->line( cx * CHUNK_W + i, 0, (cz+1) * CHUNK_D, - cx * CHUNK_W + i, CHUNK_H, (cz+1) * CHUNK_D, 0, 0, 0.8f, 1); - } - for (int i = 2; i < CHUNK_D; i+=2) { - lineBatch->line( cx * CHUNK_W, 0, cz * CHUNK_D + i, - cx * CHUNK_W, CHUNK_H, cz * CHUNK_D + i, 0.8f, 0, 0, 1); - lineBatch->line((cx+1) * CHUNK_W, 0, cz * CHUNK_D + i, - (cx+1) * CHUNK_W, CHUNK_H, cz * CHUNK_D + i, 0.8f, 0, 0, 1); - } - for (int i=0; i < CHUNK_H; i+=2){ - lineBatch->line( cx * CHUNK_W, i, cz * CHUNK_D, - cx * CHUNK_W, i, (cz+1) * CHUNK_D, 0, 0.8f, 0, 1); - lineBatch->line( cx * CHUNK_W, i, (cz+1) * CHUNK_D, - (cx+1) * CHUNK_W, i, (cz+1) * CHUNK_D, 0, 0.8f, 0, 1); - lineBatch->line((cx+1) * CHUNK_W, i, (cz+1) * CHUNK_D, - (cx+1) * CHUNK_W, i, cz * CHUNK_D, 0, 0.8f, 0, 1); - lineBatch->line((cx+1) * CHUNK_W, i, cz * CHUNK_D, - cx * CHUNK_W, i, cz * CHUNK_D, 0, 0.8f, 0, 1); - } - lineBatch->render(); + drawBorders(cx * CHUNK_W, 0, cz * CHUNK_D, + (cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D); } float length = 40.f; - // top-right: vec3 tsl = vec3(displayWidth - length - 4, -length - 4, 0.f); vec3 tsl = vec3(displayWidth/2, displayHeight/2, 0.f); glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); linesShader->uniformMatrix("u_projview", glm::ortho( @@ -251,3 +241,41 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) lineBatch->render(); } } + +void WorldRenderer::drawBorders(int sx, int sy, int sz, int ex, int ey, int ez) { + int ww = ex-sx; + int dd = ez-sz; + /*corner*/ { + lineBatch->line(sx, sy, sz, + sx, ey, sz, 0.8f, 0, 0.8f, 1); + lineBatch->line(sx, sy, ez, + sx, ey, ez, 0.8f, 0, 0.8f, 1); + lineBatch->line(ex, sy, sz, + ex, ey, sz, 0.8f, 0, 0.8f, 1); + lineBatch->line(ex, sy, ez, + ex, ey, ez, 0.8f, 0, 0.8f, 1); + } + for (int i = 2; i < ww; i+=2) { + lineBatch->line(sx + i, sy, sz, + sx + i, ey, sz, 0, 0, 0.8f, 1); + lineBatch->line(sx + i, sy, ez, + sx + i, ey, ez, 0, 0, 0.8f, 1); + } + for (int i = 2; i < dd; i+=2) { + lineBatch->line(sx, sy, sz + i, + sx, ey, sz + i, 0.8f, 0, 0, 1); + lineBatch->line(ex, sy, sz + i, + ex, ey, sz + i, 0.8f, 0, 0, 1); + } + for (int i = sy; i < ey; i+=2){ + lineBatch->line(sx, i, sz, + sx, i, ez, 0, 0.8f, 0, 1); + lineBatch->line(sx, i, ez, + ex, i, ez, 0, 0.8f, 0, 1); + lineBatch->line(ex, i, ez, + ex, i, sz, 0, 0.8f, 0, 1); + lineBatch->line(ex, i, sz, + sx, i, sz, 0, 0.8f, 0, 1); + } + lineBatch->render(); +} \ No newline at end of file diff --git a/src/frontend/world_render.h b/src/frontend/WorldRenderer.h similarity index 80% rename from src/frontend/world_render.h rename to src/frontend/WorldRenderer.h index d039aee4..fc5c4b4e 100644 --- a/src/frontend/world_render.h +++ b/src/frontend/WorldRenderer.h @@ -31,14 +31,15 @@ class WorldRenderer { LineBatch* lineBatch; ChunksRenderer* renderer; Skybox* skybox; - bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion); - void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion); + bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling); + void drawChunks(Chunks* chunks, Camera* camera, Shader* shader); public: WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache); ~WorldRenderer(); - void draw(const GfxContext& context, Camera* camera, bool occlusion); + void draw(const GfxContext& context, Camera* camera); void drawDebug(const GfxContext& context, Camera* camera); + void drawBorders(int sx, int sy, int sz, int ex, int ey, int ez); }; diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index e701ee5d..475177af 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -35,7 +35,7 @@ #include "gui/GUI.h" #include "ContentGfxCache.h" #include "screens.h" -#include "world_render.h" +#include "WorldRenderer.h" #include "../engine.h" #include "../core_defs.h" @@ -81,8 +81,10 @@ HudRenderer::HudRenderer(Engine* engine, panel->add(shared_ptr