From 79693580e0dabd6ad616d175bd74e9f4396bca0e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 11 Nov 2024 20:30:10 +0300 Subject: [PATCH 01/38] refactor Font --- src/graphics/core/Font.cpp | 40 +++++++----------------------- src/graphics/core/Font.hpp | 8 +++--- src/graphics/ui/elements/Label.cpp | 4 +-- 3 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/graphics/core/Font.cpp b/src/graphics/core/Font.cpp index c12cd923..30db7d3e 100644 --- a/src/graphics/core/Font.cpp +++ b/src/graphics/core/Font.cpp @@ -40,45 +40,23 @@ int Font::calcWidth(const std::wstring& text, size_t length) { } int Font::calcWidth(const std::wstring& text, size_t offset, size_t length) { - return std::min(text.length()-offset, length) * 8; + return std::min(text.length()-offset, length) * glyphInterval; } -void Font::draw(Batch2D* batch, std::wstring text, int x, int y) { - draw(batch, std::move(text), x, y, FontStyle::none); +static inline void drawGlyph( + Batch2D* batch, int x, int y, uint c, int glyphSize +) { + batch->sprite(x, y, glyphSize, glyphSize, 16, c, batch->getColor()); } -static inline void drawGlyph(Batch2D* batch, int x, int y, uint c, FontStyle style) { - switch (style){ - case FontStyle::none: - break; - case FontStyle::shadow: - batch->sprite(x+1, y+1, GLYPH_SIZE, GLYPH_SIZE, 16, c, SHADOW_TINT); - break; - case FontStyle::outline: - for (int oy = -1; oy <= 1; oy++){ - for (int ox = -1; ox <= 1; ox++){ - if (ox || oy) { - batch->sprite(x+ox, y+oy, GLYPH_SIZE, GLYPH_SIZE, 16, c, SHADOW_TINT); - } - } - } - break; - } - batch->sprite(x, y, GLYPH_SIZE, GLYPH_SIZE, 16, c, batch->getColor()); -} - -void Font::draw(Batch2D* batch, const std::wstring& text, int x, int y, FontStyle style) { - draw(batch, std::wstring_view(text.c_str(), text.length()), x, y, style); -} - -void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y, FontStyle style) { +void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y) { uint page = 0; uint next = MAX_CODEPAGES; int init_x = x; do { for (uint c : text){ if (!isPrintableChar(c)) { - x += 8; + x += glyphInterval; continue; } uint charpage = c >> 8; @@ -91,12 +69,12 @@ void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y, FontStyle texture = pages[0].get(); } batch->texture(texture); - drawGlyph(batch, x, y, c, style); + drawGlyph(batch, x, y, c, lineHeight); } else if (charpage > page && charpage < next){ next = charpage; } - x += 8;//getGlyphWidth(c); + x += glyphInterval; } page = next; next = MAX_CODEPAGES; diff --git a/src/graphics/core/Font.hpp b/src/graphics/core/Font.hpp index ecda77a5..b5f0c533 100644 --- a/src/graphics/core/Font.hpp +++ b/src/graphics/core/Font.hpp @@ -17,8 +17,9 @@ enum class FontStyle { class Font { int lineHeight; int yoffset; -public: + int glyphInterval = 8; std::vector> pages; +public: Font(std::vector> pages, int lineHeight, int yoffset); ~Font(); @@ -41,7 +42,6 @@ public: /// @brief Check if character is visible (non-whitespace) /// @param codepoint character unicode codepoint bool isPrintableChar(uint codepoint) const; - void draw(Batch2D* batch, std::wstring text, int x, int y); - void draw(Batch2D* batch, const std::wstring& text, int x, int y, FontStyle style); - void draw(Batch2D* batch, std::wstring_view text, int x, int y, FontStyle style); + + void draw(Batch2D* batch, std::wstring_view text, int x, int y); }; diff --git a/src/graphics/ui/elements/Label.cpp b/src/graphics/ui/elements/Label.cpp index a0d356b3..5e02b31a 100644 --- a/src/graphics/ui/elements/Label.cpp +++ b/src/graphics/ui/elements/Label.cpp @@ -201,10 +201,10 @@ void Label::draw(const DrawContext* pctx, Assets* assets) { if (i < cache.lines.size()-1) { view = std::wstring_view(text.c_str()+offset, cache.lines.at(i+1).offset-offset); } - font->draw(batch, view, pos.x, pos.y + i * totalLineHeight, FontStyle::none); + font->draw(batch, view, pos.x, pos.y + i * totalLineHeight); } } else { - font->draw(batch, text, pos.x, pos.y, FontStyle::none); + font->draw(batch, text, pos.x, pos.y); } } From c5ca9128e9990e52090310da2a890892e9f4a2de Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 11 Nov 2024 22:30:42 +0300 Subject: [PATCH 02/38] move getVoxels from ChunksStorage to Chunks --- src/graphics/render/BlocksRenderer.cpp | 6 +- src/graphics/render/BlocksRenderer.hpp | 6 +- src/graphics/render/ChunksRenderer.cpp | 4 +- src/voxels/Chunks.cpp | 94 +++++++++++++++++++++++++- src/voxels/Chunks.hpp | 7 +- src/voxels/ChunksStorage.cpp | 91 ------------------------- src/voxels/ChunksStorage.hpp | 2 - src/world/generator/VoxelFragment.cpp | 4 +- 8 files changed, 107 insertions(+), 107 deletions(-) diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index b1d8d135..cd20249d 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -5,7 +5,7 @@ #include "maths/UVRegion.hpp" #include "constants.hpp" #include "content/Content.hpp" -#include "voxels/ChunksStorage.hpp" +#include "voxels/Chunks.hpp" #include "lighting/Lightmap.hpp" #include "frontend/ContentGfxCache.hpp" #include "settings.hpp" @@ -486,7 +486,7 @@ void BlocksRenderer::render(const voxel* voxels) { } } -void BlocksRenderer::build(const Chunk* chunk, const ChunksStorage* chunks) { +void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) { this->chunk = chunk; voxelsBuffer->setPosition( chunk->x * CHUNK_W - voxelBufferPadding, 0, @@ -515,7 +515,7 @@ MeshData BlocksRenderer::createMesh() { ); } -std::shared_ptr BlocksRenderer::render(const Chunk* chunk, const ChunksStorage* chunks) { +std::shared_ptr BlocksRenderer::render(const Chunk* chunk, const Chunks* chunks) { build(chunk, chunks); const vattr attrs[]{ {3}, {2}, {1}, {0} }; diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 3890349a..15d68905 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -19,7 +19,7 @@ class Block; class Chunk; class Chunks; class VoxelsVolume; -class ChunksStorage; +class Chunks; class ContentGfxCache; struct EngineSettings; struct UVRegion; @@ -140,8 +140,8 @@ public: BlocksRenderer(size_t capacity, const Content* content, const ContentGfxCache* cache, const EngineSettings* settings); virtual ~BlocksRenderer(); - void build(const Chunk* chunk, const ChunksStorage* chunks); - std::shared_ptr render(const Chunk* chunk, const ChunksStorage* chunks); + void build(const Chunk* chunk, const Chunks* chunks); + std::shared_ptr render(const Chunk* chunk, const Chunks* chunks); MeshData createMesh(); VoxelsVolume* getVoxelsBuffer() const; diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index f5fb7f89..656124da 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -26,7 +26,7 @@ public: {} RendererResult operator()(const std::shared_ptr& chunk) override { - renderer.build(chunk.get(), level->chunksStorage.get()); + renderer.build(chunk.get(), level->chunks.get()); if (renderer.isCancelled()) { return RendererResult { glm::ivec2(chunk->x, chunk->z), true, MeshData()}; @@ -66,7 +66,7 @@ ChunksRenderer::~ChunksRenderer() { std::shared_ptr ChunksRenderer::render(const std::shared_ptr& chunk, bool important) { chunk->flags.modified = false; if (important) { - auto mesh = renderer->render(chunk.get(), level->chunksStorage.get()); + auto mesh = renderer->render(chunk.get(), level->chunks.get()); meshes[glm::ivec2(chunk->x, chunk->z)] = mesh; return mesh; } diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 5937a38e..0ce0e5c1 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -20,6 +20,7 @@ #include "objects/Entities.hpp" #include "world/Level.hpp" #include "world/LevelEvents.hpp" +#include "VoxelsVolume.hpp" #include "Block.hpp" #include "Chunk.hpp" #include "voxel.hpp" @@ -161,7 +162,7 @@ light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) const { return chunk->lightmap.get(lx, y, lz); } -Chunk* Chunks::getChunkByVoxel(int32_t x, int32_t y, int32_t z) { +Chunk* Chunks::getChunkByVoxel(int32_t x, int32_t y, int32_t z) const { if (y < 0 || y >= CHUNK_H) { return nullptr; } @@ -173,7 +174,7 @@ Chunk* Chunks::getChunkByVoxel(int32_t x, int32_t y, int32_t z) { return nullptr; } -Chunk* Chunks::getChunk(int x, int z) { +Chunk* Chunks::getChunk(int x, int z) const { if (auto ptr = areaMap.getIf(x, z)) { return ptr->get(); } @@ -675,6 +676,95 @@ bool Chunks::putChunk(const std::shared_ptr& chunk) { return areaMap.set(chunk->x, chunk->z, chunk); } +// reduce nesting on next modification +// 25.06.2024: not now +// 11.11.2024: not now +void Chunks::getVoxels(VoxelsVolume* volume, bool backlight) const { + const Content* content = level->content; + auto indices = content->getIndices(); + voxel* voxels = volume->getVoxels(); + light_t* lights = volume->getLights(); + int x = volume->getX(); + int y = volume->getY(); + int z = volume->getZ(); + + int w = volume->getW(); + int h = volume->getH(); + int d = volume->getD(); + + int scx = floordiv(x, CHUNK_W); + int scz = floordiv(z, CHUNK_D); + + int ecx = floordiv(x + w, CHUNK_W); + int ecz = floordiv(z + d, CHUNK_D); + + int cw = ecx - scx + 1; + int cd = ecz - scz + 1; + + // cw*cd chunks will be scanned + for (int cz = scz; cz < scz + cd; cz++) { + for (int cx = scx; cx < scx + cw; cx++) { + const auto chunk = getChunk(cx, cz); + if (chunk == nullptr) { + // no chunk loaded -> filling with BLOCK_VOID + for (int ly = y; ly < y + h; ly++) { + for (int lz = std::max(z, cz * CHUNK_D); + lz < std::min(z + d, (cz + 1) * CHUNK_D); + lz++) { + for (int lx = std::max(x, cx * CHUNK_W); + lx < std::min(x + w, (cx + 1) * CHUNK_W); + lx++) { + uint idx = vox_index(lx - x, ly - y, lz - z, w, d); + voxels[idx].id = BLOCK_VOID; + lights[idx] = 0; + } + } + } + } else { + const voxel* cvoxels = chunk->voxels; + const light_t* clights = chunk->lightmap.getLights(); + for (int ly = y; ly < y + h; ly++) { + for (int lz = std::max(z, cz * CHUNK_D); + lz < std::min(z + d, (cz + 1) * CHUNK_D); + lz++) { + for (int lx = std::max(x, cx * CHUNK_W); + lx < std::min(x + w, (cx + 1) * CHUNK_W); + lx++) { + uint vidx = vox_index(lx - x, ly - y, lz - z, w, d); + uint cidx = vox_index( + lx - cx * CHUNK_W, + ly, + lz - cz * CHUNK_D, + CHUNK_W, + CHUNK_D + ); + voxels[vidx] = cvoxels[cidx]; + light_t light = clights[cidx]; + if (backlight) { + const auto block = + indices->blocks.get(voxels[vidx].id); + if (block && block->lightPassing) { + light = Lightmap::combine( + std::min(15, + Lightmap::extract(light, 0) + 1), + std::min(15, + Lightmap::extract(light, 1) + 1), + std::min(15, + Lightmap::extract(light, 2) + 1), + std::min(15, + static_cast(Lightmap::extract(light, 3))) + ); + } + } + lights[vidx] = light; + } + } + } + } + } + } +} + void Chunks::saveAndClear() { areaMap.clear(); } diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index fed09f1d..d2440210 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -21,6 +21,7 @@ class WorldFiles; class LevelEvents; class Block; class Level; +class VoxelsVolume; /// Player-centred chunks matrix class Chunks { @@ -55,8 +56,8 @@ public: bool putChunk(const std::shared_ptr& chunk); - Chunk* getChunk(int32_t x, int32_t z); - Chunk* getChunkByVoxel(int32_t x, int32_t y, int32_t z); + Chunk* getChunk(int32_t x, int32_t z) const; + Chunk* getChunkByVoxel(int32_t x, int32_t y, int32_t z) const; voxel* get(int32_t x, int32_t y, int32_t z) const; voxel& require(int32_t x, int32_t y, int32_t z) const; @@ -119,6 +120,8 @@ public: bool isReplaceableBlock(int32_t x, int32_t y, int32_t z); bool isObstacleBlock(int32_t x, int32_t y, int32_t z); + void getVoxels(VoxelsVolume* volume, bool backlight = false) const; + void setCenter(int32_t x, int32_t z); void resize(uint32_t newW, uint32_t newD); diff --git a/src/voxels/ChunksStorage.cpp b/src/voxels/ChunksStorage.cpp index 75b37b9e..596c4b78 100644 --- a/src/voxels/ChunksStorage.cpp +++ b/src/voxels/ChunksStorage.cpp @@ -14,7 +14,6 @@ #include "world/World.hpp" #include "Block.hpp" #include "Chunk.hpp" -#include "VoxelsVolume.hpp" static debug::Logger logger("chunks-storage"); @@ -84,93 +83,3 @@ std::shared_ptr ChunksStorage::create(int x, int z) { chunk->blocksMetadata = regions.getBlocksData(chunk->x, chunk->z); return chunk; } - -// reduce nesting on next modification -// 25.06.2024: not now -// TODO: move to Chunks for performance improvement -void ChunksStorage::getVoxels(VoxelsVolume* volume, bool backlight) const { - const Content* content = level->content; - auto indices = content->getIndices(); - voxel* voxels = volume->getVoxels(); - light_t* lights = volume->getLights(); - int x = volume->getX(); - int y = volume->getY(); - int z = volume->getZ(); - - int w = volume->getW(); - int h = volume->getH(); - int d = volume->getD(); - - int scx = floordiv(x, CHUNK_W); - int scz = floordiv(z, CHUNK_D); - - int ecx = floordiv(x + w, CHUNK_W); - int ecz = floordiv(z + d, CHUNK_D); - - int cw = ecx - scx + 1; - int cd = ecz - scz + 1; - - // cw*cd chunks will be scanned - for (int cz = scz; cz < scz + cd; cz++) { - for (int cx = scx; cx < scx + cw; cx++) { - const auto& found = chunksMap.find(glm::ivec2(cx, cz)); - if (found == chunksMap.end()) { - // no chunk loaded -> filling with BLOCK_VOID - for (int ly = y; ly < y + h; ly++) { - for (int lz = std::max(z, cz * CHUNK_D); - lz < std::min(z + d, (cz + 1) * CHUNK_D); - lz++) { - for (int lx = std::max(x, cx * CHUNK_W); - lx < std::min(x + w, (cx + 1) * CHUNK_W); - lx++) { - uint idx = vox_index(lx - x, ly - y, lz - z, w, d); - voxels[idx].id = BLOCK_VOID; - lights[idx] = 0; - } - } - } - } else { - auto& chunk = found->second; - const voxel* cvoxels = chunk->voxels; - const light_t* clights = chunk->lightmap.getLights(); - for (int ly = y; ly < y + h; ly++) { - for (int lz = std::max(z, cz * CHUNK_D); - lz < std::min(z + d, (cz + 1) * CHUNK_D); - lz++) { - for (int lx = std::max(x, cx * CHUNK_W); - lx < std::min(x + w, (cx + 1) * CHUNK_W); - lx++) { - uint vidx = vox_index(lx - x, ly - y, lz - z, w, d); - uint cidx = vox_index( - lx - cx * CHUNK_W, - ly, - lz - cz * CHUNK_D, - CHUNK_W, - CHUNK_D - ); - voxels[vidx] = cvoxels[cidx]; - light_t light = clights[cidx]; - if (backlight) { - const auto block = - indices->blocks.get(voxels[vidx].id); - if (block && block->lightPassing) { - light = Lightmap::combine( - std::min(15, - Lightmap::extract(light, 0) + 1), - std::min(15, - Lightmap::extract(light, 1) + 1), - std::min(15, - Lightmap::extract(light, 2) + 1), - std::min(15, - static_cast(Lightmap::extract(light, 3))) - ); - } - } - lights[vidx] = light; - } - } - } - } - } - } -} diff --git a/src/voxels/ChunksStorage.hpp b/src/voxels/ChunksStorage.hpp index 887af1ca..35fff6c1 100644 --- a/src/voxels/ChunksStorage.hpp +++ b/src/voxels/ChunksStorage.hpp @@ -11,7 +11,6 @@ class Chunk; class Level; -class VoxelsVolume; class ChunksStorage { Level* level; @@ -23,6 +22,5 @@ public: std::shared_ptr get(int x, int z) const; void store(const std::shared_ptr& chunk); void remove(int x, int y); - void getVoxels(VoxelsVolume* volume, bool backlight = false) const; std::shared_ptr create(int x, int z); }; diff --git a/src/world/generator/VoxelFragment.cpp b/src/world/generator/VoxelFragment.cpp index 2d287b0b..f36824b0 100644 --- a/src/world/generator/VoxelFragment.cpp +++ b/src/world/generator/VoxelFragment.cpp @@ -26,7 +26,7 @@ std::unique_ptr VoxelFragment::create( if (crop) { VoxelsVolume volume(size.x, size.y, size.z); volume.setPosition(start.x, start.y, start.z); - level->chunksStorage->getVoxels(&volume); + level->chunks->getVoxels(&volume); auto end = start + size; @@ -51,7 +51,7 @@ std::unique_ptr VoxelFragment::create( VoxelsVolume volume(size.x, size.y, size.z); volume.setPosition(start.x, start.y, start.z); - level->chunksStorage->getVoxels(&volume); + level->chunks->getVoxels(&volume); auto volVoxels = volume.getVoxels(); std::vector voxels(size.x * size.y * size.z); From b3ab0371155163a98a2564259d99ed5ef6dde18f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 12 Nov 2024 03:14:59 +0300 Subject: [PATCH 03/38] add 3D text render (WIP) --- src/graphics/core/Batch3D.cpp | 16 +++ src/graphics/core/Batch3D.hpp | 10 ++ src/graphics/core/Font.cpp | 114 ++++++++++++++++++--- src/graphics/core/Font.hpp | 19 +++- src/graphics/render/WorldRenderer.cpp | 25 +++++ src/graphics/render/WorldRenderer.hpp | 7 ++ src/graphics/ui/elements/InventoryView.cpp | 4 +- src/graphics/ui/elements/Label.cpp | 4 +- src/graphics/ui/elements/Plotter.cpp | 2 +- 9 files changed, 176 insertions(+), 25 deletions(-) diff --git a/src/graphics/core/Batch3D.cpp b/src/graphics/core/Batch3D.cpp index 41db4294..c2db0eee 100644 --- a/src/graphics/core/Batch3D.cpp +++ b/src/graphics/core/Batch3D.cpp @@ -117,6 +117,22 @@ void Batch3D::texture(const Texture* new_texture){ new_texture->bind(); } +void Batch3D::sprite( + const glm::vec3& pos, + const glm::vec3& up, + const glm::vec3& right, + float w, + float h, + int atlasRes, + int index, + glm::vec4 tint +) { + float scale = 1.0f / static_cast(atlasRes); + float u = (index % atlasRes) * scale; + float v = 1.0f - ((index / atlasRes) * scale) - scale; + sprite(pos, up, right, w, h, UVRegion(u, v, u+scale, v+scale), tint); +} + void Batch3D::sprite( const glm::vec3& pos, const glm::vec3& up, diff --git a/src/graphics/core/Batch3D.hpp b/src/graphics/core/Batch3D.hpp index 672021fd..cf787935 100644 --- a/src/graphics/core/Batch3D.hpp +++ b/src/graphics/core/Batch3D.hpp @@ -57,6 +57,16 @@ public: const UVRegion& uv, const glm::vec4& tint ); + void sprite( + const glm::vec3& pos, + const glm::vec3& up, + const glm::vec3& right, + float w, + float h, + int atlasRes, + int index, + glm::vec4 tint + ); void xSprite( float w, float h, diff --git a/src/graphics/core/Font.cpp b/src/graphics/core/Font.cpp index 30db7d3e..db3b3593 100644 --- a/src/graphics/core/Font.cpp +++ b/src/graphics/core/Font.cpp @@ -3,6 +3,8 @@ #include #include "Texture.hpp" #include "Batch2D.hpp" +#include "Batch3D.hpp" +#include "window/Camera.hpp" inline constexpr uint GLYPH_SIZE = 16; inline constexpr uint MAX_CODEPAGES = 10000; // idk ho many codepages unicode has @@ -35,41 +37,76 @@ bool Font::isPrintableChar(uint codepoint) const { } } -int Font::calcWidth(const std::wstring& text, size_t length) { +int Font::calcWidth(const std::wstring& text, size_t length) const { return calcWidth(text, 0, length); } -int Font::calcWidth(const std::wstring& text, size_t offset, size_t length) { +int Font::calcWidth(const std::wstring& text, size_t offset, size_t length) const { return std::min(text.length()-offset, length) * glyphInterval; } static inline void drawGlyph( - Batch2D* batch, int x, int y, uint c, int glyphSize + Batch2D& batch, + const glm::vec3& pos, + const glm::vec2& offset, + uint c, + int glyphSize, + const Camera* ) { - batch->sprite(x, y, glyphSize, glyphSize, 16, c, batch->getColor()); + batch.sprite( + pos.x + offset.x, + pos.y + offset.y, + glyphSize, + glyphSize, + 16, + c, + batch.getColor() + ); } -void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y) { +static inline void drawGlyph( + Batch3D& batch, + const glm::vec3& pos, + const glm::vec2& offset, + uint c, + int glyphSize, + const Camera* camera +) { + batch.sprite( + pos + camera->right * offset.x + camera->up * offset.y, + camera->up, camera->right, + glyphSize * 0.5f, + glyphSize * 0.5f, + 16, + c, + glm::vec4(1.0f) + ); +} + +template +static inline void draw_text( + const Font& font, + Batch& batch, + std::wstring_view text, + const glm::vec3& pos, + float glyphInterval, + float lineHeight, + const Camera* camera +) { uint page = 0; uint next = MAX_CODEPAGES; - int init_x = x; + float x = 0; + float y = 0; do { for (uint c : text){ - if (!isPrintableChar(c)) { + if (!font.isPrintableChar(c)) { x += glyphInterval; continue; } uint charpage = c >> 8; if (charpage == page){ - Texture* texture = nullptr; - if (charpage < pages.size()) { - texture = pages[charpage].get(); - } - if (texture == nullptr){ - texture = pages[0].get(); - } - batch->texture(texture); - drawGlyph(batch, x, y, c, lineHeight); + batch.texture(font.getPage(charpage)); + drawGlyph(batch, pos, glm::vec2(x, y), c, lineHeight, camera); } else if (charpage > page && charpage < next){ next = charpage; @@ -78,6 +115,49 @@ void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y) { } page = next; next = MAX_CODEPAGES; - x = init_x; + x = 0.0f; } while (page < MAX_CODEPAGES); } + +const Texture* Font::getPage(int charpage) const { + Texture* texture = nullptr; + if (charpage < pages.size()) { + texture = pages[charpage].get(); + } + if (texture == nullptr){ + texture = pages[0].get(); + } + return texture; +} + +void Font::draw( + Batch2D& batch, std::wstring_view text, int x, int y, float scale +) const { + draw_text( + *this, + batch, + text, + glm::vec3(x, y, 0), + glyphInterval * scale, + lineHeight * scale, + nullptr + ); +} + +void Font::draw( + Batch3D& batch, + const Camera& camera, + std::wstring_view text, + const glm::vec3& pos, + float scale +) const { + draw_text( + *this, + batch, + text, + pos, + glyphInterval * scale, + lineHeight * scale, + &camera + ); +} diff --git a/src/graphics/core/Font.hpp b/src/graphics/core/Font.hpp index b5f0c533..1a778cfc 100644 --- a/src/graphics/core/Font.hpp +++ b/src/graphics/core/Font.hpp @@ -3,10 +3,13 @@ #include #include #include +#include #include "typedefs.hpp" class Texture; class Batch2D; +class Batch3D; +class Camera; enum class FontStyle { none, @@ -30,18 +33,28 @@ public: /// @param text selected text /// @param length max substring length (default: no limit) /// @return pixel width of the substring - int calcWidth(const std::wstring& text, size_t length=-1); + int calcWidth(const std::wstring& text, size_t length=-1) const; /// @brief Calculate text width in pixels /// @param text selected text /// @param offset start of the substring /// @param length max substring length /// @return pixel width of the substring - int calcWidth(const std::wstring& text, size_t offset, size_t length); + int calcWidth(const std::wstring& text, size_t offset, size_t length) const; /// @brief Check if character is visible (non-whitespace) /// @param codepoint character unicode codepoint bool isPrintableChar(uint codepoint) const; - void draw(Batch2D* batch, std::wstring_view text, int x, int y); + void draw(Batch2D& batch, std::wstring_view text, int x, int y, float scale=1) const; + + void draw( + Batch3D& batch, + const Camera& camera, + std::wstring_view text, + const glm::vec3& pos, + float scale = 1 + ) const; + + const Texture* getPage(int page) const; }; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 033b8124..cfbb8373 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -40,6 +40,7 @@ #include "graphics/core/PostProcessing.hpp" #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" +#include "graphics/core/Font.hpp" #include "ParticlesRenderer.hpp" #include "ChunksRenderer.hpp" #include "ModelBatch.hpp" @@ -405,6 +406,29 @@ void WorldRenderer::renderHands( skybox->unbind(); } +void WorldRenderer::renderTexts( + const DrawContext& context, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible +) { + const auto& assets = *engine->getAssets(); + auto& shader = assets.require("ui3d"); + auto& font = assets.require("normal"); + shader.uniformMatrix("u_projview", camera.getProjView()); + shader.uniformMatrix("u_apply", glm::mat4(1.0f)); + batch3d->begin(); + std::wstring string = L"Segmentation fault (core dumped)"; + font.draw( + *batch3d, + camera, + string, + glm::vec3(0, 100, 0) - + camera.right * (font.calcWidth(string, string.length()) * 0.5f) + ); + batch3d->flush(); +} + void WorldRenderer::draw( const DrawContext& pctx, Camera& camera, @@ -441,6 +465,7 @@ void WorldRenderer::draw( DrawContext ctx = wctx.sub(); ctx.setDepthTest(true); ctx.setCullFace(true); + renderTexts(ctx, camera, settings, hudVisible); renderLevel(ctx, camera, settings, delta, pause); // Debug lines if (hudVisible) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index a1023b2d..f30acf83 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -80,6 +80,13 @@ class WorldRenderer { const EngineSettings& settings, float fogFactor ); + + void renderTexts( + const DrawContext& context, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible + ); public: std::unique_ptr particles; diff --git a/src/graphics/ui/elements/InventoryView.cpp b/src/graphics/ui/elements/InventoryView.cpp index fa3d836c..9d07441d 100644 --- a/src/graphics/ui/elements/InventoryView.cpp +++ b/src/graphics/ui/elements/InventoryView.cpp @@ -194,9 +194,9 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) { int y = pos.y+slotSize-16; batch->setColor({0, 0, 0, 1.0f}); - font->draw(batch, text, x+1, y+1); + font->draw(*batch, text, x+1, y+1); batch->setColor(glm::vec4(1.0f)); - font->draw(batch, text, x, y); + font->draw(*batch, text, x, y); } } diff --git a/src/graphics/ui/elements/Label.cpp b/src/graphics/ui/elements/Label.cpp index 5e02b31a..c356f13b 100644 --- a/src/graphics/ui/elements/Label.cpp +++ b/src/graphics/ui/elements/Label.cpp @@ -201,10 +201,10 @@ void Label::draw(const DrawContext* pctx, Assets* assets) { if (i < cache.lines.size()-1) { view = std::wstring_view(text.c_str()+offset, cache.lines.at(i+1).offset-offset); } - font->draw(batch, view, pos.x, pos.y + i * totalLineHeight); + font->draw(*batch, view, pos.x, pos.y + i * totalLineHeight); } } else { - font->draw(batch, text, pos.x, pos.y); + font->draw(*batch, text, pos.x, pos.y); } } diff --git a/src/graphics/ui/elements/Plotter.cpp b/src/graphics/ui/elements/Plotter.cpp index 86e159bf..293d84b5 100644 --- a/src/graphics/ui/elements/Plotter.cpp +++ b/src/graphics/ui/elements/Plotter.cpp @@ -47,6 +47,6 @@ void Plotter::draw(const DrawContext* pctx, Assets* assets) { batch->setColor({1,1,1,0.2f}); string = util::to_wstring(y / multiplier, 3); } - font->draw(batch, string, pos.x+dmwidth+2, pos.y+dmheight-y-labelsInterval); + font->draw(*batch, string, pos.x+dmwidth+2, pos.y+dmheight-y-labelsInterval); } } From edbd851d11665e0e19700d21d226a89a0cee5983 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 12 Nov 2024 05:58:16 +0300 Subject: [PATCH 04/38] update font rendering --- src/graphics/core/Font.cpp | 76 ++++++++++++++++----------- src/graphics/core/Font.hpp | 4 +- src/graphics/render/WorldRenderer.cpp | 13 +++-- 3 files changed, 58 insertions(+), 35 deletions(-) diff --git a/src/graphics/core/Font.cpp b/src/graphics/core/Font.cpp index db3b3593..3f63065e 100644 --- a/src/graphics/core/Font.cpp +++ b/src/graphics/core/Font.cpp @@ -45,38 +45,42 @@ int Font::calcWidth(const std::wstring& text, size_t offset, size_t length) cons return std::min(text.length()-offset, length) * glyphInterval; } -static inline void drawGlyph( +static inline void draw_glyph( Batch2D& batch, const glm::vec3& pos, const glm::vec2& offset, uint c, - int glyphSize, - const Camera* + const glm::vec3& right, + const glm::vec3& up, + float glyphInterval, + float lineHeight ) { batch.sprite( - pos.x + offset.x, - pos.y + offset.y, - glyphSize, - glyphSize, + pos.x + offset.x * right.x, + pos.y + offset.y * right.y, + right.x / glyphInterval, + up.y, 16, c, batch.getColor() ); } -static inline void drawGlyph( +static inline void draw_glyph( Batch3D& batch, const glm::vec3& pos, const glm::vec2& offset, uint c, - int glyphSize, - const Camera* camera + const glm::vec3& right, + const glm::vec3& up, + float glyphInterval, + float lineHeight ) { batch.sprite( - pos + camera->right * offset.x + camera->up * offset.y, - camera->up, camera->right, - glyphSize * 0.5f, - glyphSize * 0.5f, + pos + right * offset.x + up * offset.y, + up, right / glyphInterval, + 0.5f, + 0.5f, 16, c, glm::vec4(1.0f) @@ -89,33 +93,43 @@ static inline void draw_text( Batch& batch, std::wstring_view text, const glm::vec3& pos, + const glm::vec3& right, + const glm::vec3& up, float glyphInterval, - float lineHeight, - const Camera* camera + float lineHeight ) { uint page = 0; uint next = MAX_CODEPAGES; - float x = 0; - float y = 0; + int x = 0; + int y = 0; do { for (uint c : text){ if (!font.isPrintableChar(c)) { - x += glyphInterval; + x++; continue; } uint charpage = c >> 8; if (charpage == page){ batch.texture(font.getPage(charpage)); - drawGlyph(batch, pos, glm::vec2(x, y), c, lineHeight, camera); + draw_glyph( + batch, + pos, + glm::vec2(x, y), + c, + right, + up, + glyphInterval, + lineHeight + ); } else if (charpage > page && charpage < next){ next = charpage; } - x += glyphInterval; + x++; } page = next; next = MAX_CODEPAGES; - x = 0.0f; + x = 0; } while (page < MAX_CODEPAGES); } @@ -138,26 +152,28 @@ void Font::draw( batch, text, glm::vec3(x, y, 0), - glyphInterval * scale, - lineHeight * scale, - nullptr + glm::vec3(glyphInterval*scale, 0, 0), + glm::vec3(0, lineHeight*scale, 0), + glyphInterval/static_cast(lineHeight), + lineHeight ); } void Font::draw( Batch3D& batch, - const Camera& camera, std::wstring_view text, const glm::vec3& pos, - float scale + const glm::vec3& right, + const glm::vec3& up ) const { draw_text( *this, batch, text, pos, - glyphInterval * scale, - lineHeight * scale, - &camera + right * static_cast(glyphInterval), + up * static_cast(lineHeight), + glyphInterval/static_cast(lineHeight), + lineHeight ); } diff --git a/src/graphics/core/Font.hpp b/src/graphics/core/Font.hpp index 1a778cfc..deb07534 100644 --- a/src/graphics/core/Font.hpp +++ b/src/graphics/core/Font.hpp @@ -50,10 +50,10 @@ public: void draw( Batch3D& batch, - const Camera& camera, std::wstring_view text, const glm::vec3& pos, - float scale = 1 + const glm::vec3& right={1, 0, 0}, + const glm::vec3& up={0, 1, 0} ) const; const Texture* getPage(int page) const; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index cfbb8373..41e368a6 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -419,12 +419,19 @@ void WorldRenderer::renderTexts( shader.uniformMatrix("u_apply", glm::mat4(1.0f)); batch3d->begin(); std::wstring string = L"Segmentation fault (core dumped)"; + glm::vec3 pos(0, 100, 0); + auto zvec = camera.position - pos; + zvec.y = 0; + std::swap(zvec.x, zvec.z); + zvec.z *= -1; + zvec = glm::normalize(zvec); + font.draw( *batch3d, - camera, string, - glm::vec3(0, 100, 0) - - camera.right * (font.calcWidth(string, string.length()) * 0.5f) + pos - zvec * (font.calcWidth(string, string.length()) * 0.5f), + zvec, + camera.up ); batch3d->flush(); } From 7734d403ea8145e88804c0490bab8e67743c023e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 12 Nov 2024 06:01:53 +0300 Subject: [PATCH 05/38] cleanup --- src/graphics/core/Font.cpp | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/src/graphics/core/Font.cpp b/src/graphics/core/Font.cpp index 3f63065e..31fe60c0 100644 --- a/src/graphics/core/Font.cpp +++ b/src/graphics/core/Font.cpp @@ -52,8 +52,7 @@ static inline void draw_glyph( uint c, const glm::vec3& right, const glm::vec3& up, - float glyphInterval, - float lineHeight + float glyphInterval ) { batch.sprite( pos.x + offset.x * right.x, @@ -73,8 +72,7 @@ static inline void draw_glyph( uint c, const glm::vec3& right, const glm::vec3& up, - float glyphInterval, - float lineHeight + float glyphInterval ) { batch.sprite( pos + right * offset.x + up * offset.y, @@ -95,8 +93,7 @@ static inline void draw_text( const glm::vec3& pos, const glm::vec3& right, const glm::vec3& up, - float glyphInterval, - float lineHeight + float glyphInterval ) { uint page = 0; uint next = MAX_CODEPAGES; @@ -112,14 +109,7 @@ static inline void draw_text( if (charpage == page){ batch.texture(font.getPage(charpage)); draw_glyph( - batch, - pos, - glm::vec2(x, y), - c, - right, - up, - glyphInterval, - lineHeight + batch, pos, glm::vec2(x, y), c, right, up, glyphInterval ); } else if (charpage > page && charpage < next){ @@ -148,14 +138,11 @@ void Font::draw( Batch2D& batch, std::wstring_view text, int x, int y, float scale ) const { draw_text( - *this, - batch, - text, + *this, batch, text, glm::vec3(x, y, 0), glm::vec3(glyphInterval*scale, 0, 0), glm::vec3(0, lineHeight*scale, 0), - glyphInterval/static_cast(lineHeight), - lineHeight + glyphInterval/static_cast(lineHeight) ); } @@ -167,13 +154,9 @@ void Font::draw( const glm::vec3& up ) const { draw_text( - *this, - batch, - text, - pos, + *this, batch, text, pos, right * static_cast(glyphInterval), up * static_cast(lineHeight), - glyphInterval/static_cast(lineHeight), - lineHeight + glyphInterval/static_cast(lineHeight) ); } From aadb04c41eb4caae8f611da3cf1a895d38550403 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 12 Nov 2024 20:07:45 +0300 Subject: [PATCH 06/38] minor optimize BlocksRenderer --- src/graphics/render/BlocksRenderer.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index cd20249d..745e96ec 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -434,10 +434,27 @@ glm::vec4 BlocksRenderer::pickSoftLight( } void BlocksRenderer::render(const voxel* voxels) { - int begin = chunk->bottom * (CHUNK_W * CHUNK_D); - int end = chunk->top * (CHUNK_W * CHUNK_D); + int totalBegin = chunk->bottom * (CHUNK_W * CHUNK_D); + int totalEnd = chunk->top * (CHUNK_W * CHUNK_D); + + int beginEnds[256][2] {}; + for (int i = totalBegin; i < totalEnd; i++) { + const voxel& vox = voxels[i]; + blockid_t id = vox.id; + const auto& def = *blockDefsCache[id]; + + if (beginEnds[def.drawGroup][0] == 0) { + beginEnds[def.drawGroup][0] = i+1; + } + beginEnds[def.drawGroup][1] = i; + } for (const auto drawGroup : *content->drawGroups) { - for (int i = begin; i < end; i++) { + int begin = beginEnds[drawGroup][0]; + if (begin == 0) { + continue; + } + int end = beginEnds[drawGroup][1]; + for (int i = begin-1; i <= end; i++) { const voxel& vox = voxels[i]; blockid_t id = vox.id; blockstate state = vox.state; From 866f6e99517904c97da6655b1723b14ba2ba7c2d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 12 Nov 2024 22:53:45 +0300 Subject: [PATCH 07/38] add NotePreset --- src/graphics/render/WorldRenderer.cpp | 8 ++++-- src/presets/NotePreset.cpp | 40 +++++++++++++++++++++++++++ src/presets/NotePreset.hpp | 23 +++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/presets/NotePreset.cpp create mode 100644 src/presets/NotePreset.hpp diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 41e368a6..54f2d447 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -426,12 +426,14 @@ void WorldRenderer::renderTexts( zvec.z *= -1; zvec = glm::normalize(zvec); + float ppbx = 100; + float ppby = 100; font.draw( *batch3d, string, - pos - zvec * (font.calcWidth(string, string.length()) * 0.5f), - zvec, - camera.up + pos - zvec * (font.calcWidth(string, string.length()) * 0.5f) / ppbx, + zvec / ppbx, + camera.up / ppby ); batch3d->flush(); } diff --git a/src/presets/NotePreset.cpp b/src/presets/NotePreset.cpp new file mode 100644 index 00000000..e8601ab7 --- /dev/null +++ b/src/presets/NotePreset.cpp @@ -0,0 +1,40 @@ +#include "NotePreset.hpp" + +#include +#include + +std::string to_string(NoteDisplayMode mode) { + static std::vector names = { + "static_billboard", + "y_free_billboard", + "xy_free_billboard", + "projected" + }; + return names.at(static_cast(mode)); +} + +std::optional NoteDisplayMode_from(std::string_view s) { + static std::map> map { + {"static_billboard", NoteDisplayMode::STATIC_BILLBOARD}, + {"y_free_billboard", NoteDisplayMode::Y_FREE_BILLBOARD}, + {"xy_free_billboard", NoteDisplayMode::XY_FREE_BILLBOARD}, + {"projected", NoteDisplayMode::PROJECTED} + }; + const auto& found = map.find(s); + if (found == map.end()) { + return std::nullopt; + } + return found->second; +} + +dv::value NotePreset::serialize() const { + return dv::object({ + {"display", to_string(displayMode)} + }); +} + +void NotePreset::deserialize(const dv::value& src) { + if (src.has("display")) { + displayMode = NoteDisplayMode_from(src["display"].asString()).value(); + } +} diff --git a/src/presets/NotePreset.hpp b/src/presets/NotePreset.hpp new file mode 100644 index 00000000..cf8aa15f --- /dev/null +++ b/src/presets/NotePreset.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#include "interfaces/Serializable.hpp" + +enum class NoteDisplayMode { + STATIC_BILLBOARD, + Y_FREE_BILLBOARD, + XY_FREE_BILLBOARD, + PROJECTED +}; + +std::string to_string(NoteDisplayMode mode); +std::optional NoteDisplayMode_from(std::string_view s); + +struct NotePreset : public Serializable { + NoteDisplayMode displayMode = NoteDisplayMode::STATIC_BILLBOARD; + + dv::value serialize() const override; + void deserialize(const dv::value& src) override; +}; From a5c9125084197e0516a50017ac3577a6891ea9fa Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 01:24:34 +0300 Subject: [PATCH 08/38] fix clang-format what --- src/assets/assetload_funcs.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index a7d258ec..c688a58a 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -102,8 +102,13 @@ static bool append_atlas(AtlasBuilder& atlas, const fs::path& file) { return true; } -assetload::postfunc assetload:: - atlas(AssetsLoader*, const ResPaths* paths, const std::string& directory, const std::string& name, const std::shared_ptr&) { +assetload::postfunc assetload::atlas( + AssetsLoader*, + const ResPaths* paths, + const std::string& directory, + const std::string& name, + const std::shared_ptr& +) { AtlasBuilder builder; for (const auto& file : paths->listdir(directory)) { if (!imageio::is_read_supported(file.extension().u8string())) continue; @@ -120,8 +125,13 @@ assetload::postfunc assetload:: }; } -assetload::postfunc assetload:: - font(AssetsLoader*, const ResPaths* paths, const std::string& filename, const std::string& name, const std::shared_ptr&) { +assetload::postfunc assetload::font( + AssetsLoader*, + const ResPaths* paths, + const std::string& filename, + const std::string& name, + const std::shared_ptr& +) { auto pages = std::make_shared>>(); for (size_t i = 0; i <= 4; i++) { std::string pagefile = filename + "_" + std::to_string(i) + ".png"; From 60aa0fbcfcf00d5915fca299c6d385020d185251 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 02:01:51 +0300 Subject: [PATCH 09/38] increase max font codepages to 1024 --- src/assets/assetload_funcs.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index c688a58a..ed4f076f 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -32,7 +32,7 @@ static debug::Logger logger("assetload-funcs"); namespace fs = std::filesystem; -static bool animation( +static bool load_animation( Assets* assets, const ResPaths* paths, const std::string& atlasName, @@ -120,7 +120,7 @@ assetload::postfunc assetload::atlas( atlas->prepare(); assets->store(std::unique_ptr(atlas), name); for (const auto& file : names) { - animation(assets, paths, name, directory, file, atlas); + load_animation(assets, paths, name, directory, file, atlas); } }; } @@ -133,16 +133,26 @@ assetload::postfunc assetload::font( const std::shared_ptr& ) { auto pages = std::make_shared>>(); - for (size_t i = 0; i <= 4; i++) { + for (size_t i = 0; i <= 1024; i++) { std::string pagefile = filename + "_" + std::to_string(i) + ".png"; - pagefile = paths->find(pagefile).string(); - pages->push_back(imageio::read(pagefile)); + auto file = paths->find(pagefile); + if (fs::exists(file)) { + pages->push_back(imageio::read(file.u8string())); + } else if (i == 0) { + throw std::runtime_error("font must have page 0"); + } else { + pages->push_back(nullptr); + } } return [=](auto assets) { int res = pages->at(0)->getHeight() / 16; std::vector> textures; for (auto& page : *pages) { - textures.emplace_back(Texture::from(page.get())); + if (page == nullptr) { + textures.emplace_back(nullptr); + } else { + textures.emplace_back(Texture::from(page.get())); + } } assets->store( std::make_unique(std::move(textures), res, 4), name @@ -326,11 +336,9 @@ static TextureAnimation create_animation( if (elem.second > 0) { frame.duration = static_cast(elem.second) / 1000.0f; } - frame.srcPos = - glm::ivec2( - region.u1 * srcWidth, srcHeight - region.v2 * srcHeight - ) - - extension; + frame.srcPos = glm::ivec2( + region.u1 * srcWidth, srcHeight - region.v2 * srcHeight + ) - extension; animation.addFrame(frame); } return animation; @@ -348,7 +356,7 @@ inline bool contains( return false; } -static bool animation( +static bool load_animation( Assets* assets, const ResPaths* paths, const std::string& atlasName, From d8fe2f1531c6d94bd641b8182307eeb9cab27fbc Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 02:50:27 +0300 Subject: [PATCH 10/38] fix debug chunk borders render --- src/graphics/render/WorldRenderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 54f2d447..e4b2d985 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -477,6 +477,9 @@ void WorldRenderer::draw( renderTexts(ctx, camera, settings, hudVisible); renderLevel(ctx, camera, settings, delta, pause); // Debug lines + if (hudVisible && player->debug) { + renderDebugLines(ctx, camera, linesShader); + } if (hudVisible) { renderLines(camera, linesShader, ctx); if (player->currentCamera == player->fpCamera) { @@ -484,9 +487,6 @@ void WorldRenderer::draw( } } } - if (hudVisible && player->debug) { - renderDebugLines(wctx, camera, linesShader); - } renderBlockOverlay(wctx, assets); } From a7833a780d6b3f92017ba1c8f771940f40a79aba Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 03:35:49 +0300 Subject: [PATCH 11/38] refactor WorldRenderer --- src/graphics/render/WorldRenderer.cpp | 67 ++++++++++++++------------- src/graphics/render/WorldRenderer.hpp | 10 ++-- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e4b2d985..a9e14dab 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -89,7 +89,7 @@ WorldRenderer::WorldRenderer( WorldRenderer::~WorldRenderer() = default; bool WorldRenderer::drawChunk( - size_t index, const Camera& camera, Shader* shader, bool culling + size_t index, const Camera& camera, Shader& shader, bool culling ) { auto chunk = level->chunks->getChunks()[index]; if (!chunk->flags.lighted) { @@ -119,13 +119,13 @@ bool WorldRenderer::drawChunk( } glm::vec3 coord(chunk->x * CHUNK_W + 0.5f, 0.5f, chunk->z * CHUNK_D + 0.5f); glm::mat4 model = glm::translate(glm::mat4(1.0f), coord); - shader->uniformMatrix("u_model", model); + shader.uniformMatrix("u_model", model); mesh->draw(); return true; } void WorldRenderer::drawChunks( - Chunks* chunks, const Camera& camera, Shader* shader + Chunks* chunks, const Camera& camera, Shader& shader ) { auto assets = engine->getAssets(); auto atlas = assets->get("blocks"); @@ -163,23 +163,23 @@ void WorldRenderer::drawChunks( } void WorldRenderer::setupWorldShader( - Shader* shader, + Shader& shader, const Camera& camera, const EngineSettings& settings, float fogFactor ) { - shader->use(); - shader->uniformMatrix("u_model", glm::mat4(1.0f)); - shader->uniformMatrix("u_proj", camera.getProjection()); - shader->uniformMatrix("u_view", camera.getView()); - shader->uniform1f("u_timer", timer); - shader->uniform1f("u_gamma", settings.graphics.gamma.get()); - shader->uniform1f("u_fogFactor", fogFactor); - shader->uniform1f("u_fogCurve", settings.graphics.fogCurve.get()); - shader->uniform1f("u_dayTime", level->getWorld()->getInfo().daytime); - shader->uniform2f("u_lightDir", skybox->getLightDir()); - shader->uniform3f("u_cameraPos", camera.position); - shader->uniform1i("u_cubemap", 1); + shader.use(); + shader.uniformMatrix("u_model", glm::mat4(1.0f)); + shader.uniformMatrix("u_proj", camera.getProjection()); + shader.uniformMatrix("u_view", camera.getView()); + shader.uniform1f("u_timer", timer); + shader.uniform1f("u_gamma", settings.graphics.gamma.get()); + shader.uniform1f("u_fogFactor", fogFactor); + shader.uniform1f("u_fogCurve", settings.graphics.fogCurve.get()); + shader.uniform1f("u_dayTime", level->getWorld()->getInfo().daytime); + shader.uniform2f("u_lightDir", skybox->getLightDir()); + shader.uniform3f("u_cameraPos", camera.position); + shader.uniform1i("u_cubemap", 1); auto indices = level->content->getIndices(); // Light emission when an emissive item is chosen @@ -188,13 +188,13 @@ void WorldRenderer::setupWorldShader( ItemStack& stack = inventory->getSlot(player->getChosenSlot()); auto& item = indices->items.require(stack.getItemId()); float multiplier = 0.5f; - shader->uniform3f( + shader.uniform3f( "u_torchlightColor", item.emission[0] / 15.0f * multiplier, item.emission[1] / 15.0f * multiplier, item.emission[2] / 15.0f * multiplier ); - shader->uniform1f("u_torchlightDistance", 6.0f); + shader.uniform1f("u_torchlightDistance", 6.0f); } } @@ -211,7 +211,7 @@ void WorldRenderer::renderLevel( float fogFactor = 15.0f / static_cast(settings.chunks.loadDistance.get() - 2); - auto entityShader = assets->get("entity"); + auto& entityShader = assets->require("entity"); setupWorldShader(entityShader, camera, settings, fogFactor); skybox->bind(); @@ -225,7 +225,7 @@ void WorldRenderer::renderLevel( particles->render(camera, delta * !pause); modelBatch->render(); - auto shader = assets->get("main"); + auto& shader = assets->require("main"); setupWorldShader(shader, camera, settings, fogFactor); drawChunks(level->chunks.get(), camera, shader); @@ -255,7 +255,7 @@ void WorldRenderer::renderBlockSelection() { const glm::vec3 center = glm::vec3(pos) + hitbox.center(); const glm::vec3 size = hitbox.size(); lineBatch->box( - center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f) + center, size + glm::vec3(0.01), glm::vec4(0.f, 0.f, 0.f, 0.5f) ); if (player->debug) { lineBatch->line( @@ -267,10 +267,10 @@ void WorldRenderer::renderBlockSelection() { } void WorldRenderer::renderLines( - const Camera& camera, Shader* linesShader, const DrawContext& pctx + const Camera& camera, Shader& linesShader, const DrawContext& pctx ) { - linesShader->use(); - linesShader->uniformMatrix("u_projview", camera.getProjView()); + linesShader.use(); + linesShader.uniformMatrix("u_projview", camera.getProjView()); if (player->selection.vox.id != BLOCK_VOID) { renderBlockSelection(); } @@ -284,7 +284,7 @@ void WorldRenderer::renderLines( } void WorldRenderer::renderDebugLines( - const DrawContext& pctx, const Camera& camera, Shader* linesShader + const DrawContext& pctx, const Camera& camera, Shader& linesShader ) { DrawContext ctx = pctx.sub(lineBatch.get()); const auto& viewport = ctx.getViewport(); @@ -293,10 +293,10 @@ void WorldRenderer::renderDebugLines( ctx.setDepthTest(true); - linesShader->use(); + linesShader.use(); if (showChunkBorders) { - linesShader->uniformMatrix("u_projview", camera.getProjView()); + linesShader.uniformMatrix("u_projview", camera.getProjView()); glm::vec3 coord = player->fpCamera->position; if (coord.x < 0) coord.x--; if (coord.z < 0) coord.z--; @@ -316,7 +316,7 @@ void WorldRenderer::renderDebugLines( float length = 40.f; glm::vec3 tsl(displayWidth / 2, displayHeight / 2, 0.f); glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); - linesShader->uniformMatrix( + linesShader.uniformMatrix( "u_projview", glm::ortho( 0.f, @@ -346,7 +346,7 @@ void WorldRenderer::renderDebugLines( void WorldRenderer::renderHands( const Camera& camera, const Assets& assets, float delta ) { - auto entityShader = assets.get("entity"); + auto& entityShader = assets.require("entity"); auto indices = level->content->getIndices(); // get current chosen item @@ -415,6 +415,7 @@ void WorldRenderer::renderTexts( const auto& assets = *engine->getAssets(); auto& shader = assets.require("ui3d"); auto& font = assets.require("normal"); + shader.use(); shader.uniformMatrix("u_projview", camera.getProjView()); shader.uniformMatrix("u_apply", glm::mat4(1.0f)); batch3d->begin(); @@ -457,7 +458,7 @@ void WorldRenderer::draw( skybox->refresh(pctx, worldInfo.daytime, 1.0f + worldInfo.fog * 2.0f, 4); const auto& assets = *engine->getAssets(); - auto linesShader = assets.get("lines"); + auto& linesShader = assets.require("lines"); // World render scope with diegetic HUD included { @@ -477,10 +478,10 @@ void WorldRenderer::draw( renderTexts(ctx, camera, settings, hudVisible); renderLevel(ctx, camera, settings, delta, pause); // Debug lines - if (hudVisible && player->debug) { - renderDebugLines(ctx, camera, linesShader); - } if (hudVisible) { + if (player->debug) { + renderDebugLines(ctx, camera, linesShader); + } renderLines(camera, linesShader, ctx); if (player->currentCamera == player->fpCamera) { renderHands(camera, assets, delta * !pause); diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index f30acf83..28a4320b 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -47,8 +47,8 @@ class WorldRenderer { float timer = 0.0f; - bool drawChunk(size_t index, const Camera& camera, Shader* shader, bool culling); - void drawChunks(Chunks* chunks, const Camera& camera, Shader* shader); + bool drawChunk(size_t index, const Camera& camera, Shader& shader, bool culling); + void drawChunks(Chunks* chunks, const Camera& camera, Shader& shader); /// @brief Render block selection lines void renderBlockSelection(); @@ -59,7 +59,7 @@ class WorldRenderer { /// @param camera active camera /// @param linesShader shader used void renderLines( - const Camera& camera, Shader* linesShader, const DrawContext& pctx + const Camera& camera, Shader& linesShader, const DrawContext& pctx ); /// @brief Render all debug lines (chunks borders, coord system guides) @@ -69,13 +69,13 @@ class WorldRenderer { void renderDebugLines( const DrawContext& context, const Camera& camera, - Shader* linesShader + Shader& linesShader ); void renderBlockOverlay(const DrawContext& context, const Assets& assets); void setupWorldShader( - Shader* shader, + Shader& shader, const Camera& camera, const EngineSettings& settings, float fogFactor From b23d31a321826c5a75db7fff61d90987bcfaa3b2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 03:40:20 +0300 Subject: [PATCH 12/38] add 'translucent' block property --- res/content/base/blocks/water.json | 3 ++- src/content/ContentLoader.cpp | 1 + src/voxels/Block.cpp | 1 + src/voxels/Block.hpp | 3 +++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/content/base/blocks/water.json b/res/content/base/blocks/water.json index 943640e8..f7785044 100644 --- a/res/content/base/blocks/water.json +++ b/res/content/base/blocks/water.json @@ -6,5 +6,6 @@ "sky-light-passing": false, "obstacle": false, "selectable": false, - "replaceable": true + "replaceable": true, + "translucent": true } diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index a801500e..4414999d 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -333,6 +333,7 @@ void ContentLoader::loadBlock( root.at("inventory-size").get(def.inventorySize); root.at("tick-interval").get(def.tickInterval); root.at("overlay-texture").get(def.overlayTexture); + root.at("translucent").get(def.translucent); if (root.has("fields")) { def.dataStruct = std::make_unique(); diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index 51d9662b..6d4ff761 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -140,6 +140,7 @@ void Block::cloneTo(Block& dst) { dst.inventorySize = inventorySize; dst.tickInterval = tickInterval; dst.overlayTexture = overlayTexture; + dst.translucent = translucent; if (particles) { dst.particles = std::make_unique(*particles); } diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 26b38469..84835534 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -172,6 +172,9 @@ public: /// @brief Turns off block item generation bool hidden = false; + /// @brief Block has semi-transparent texture + bool translucent = false; + /// @brief Set of block physical hitboxes std::vector hitboxes; From a21d87717e987adf2a57eeeb8a307819f116b5ee Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 04:29:37 +0300 Subject: [PATCH 13/38] optimize WorldRenderer chunks sort --- src/graphics/render/WorldRenderer.cpp | 36 ++++++++++++++++++--------- src/graphics/render/WorldRenderer.hpp | 2 ++ src/util/listutil.hpp | 9 +++++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index a9e14dab..fed5c1fb 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -22,6 +22,7 @@ #include "maths/voxmaths.hpp" #include "objects/Entities.hpp" #include "objects/Player.hpp" +#include "util/listutil.hpp" #include "settings.hpp" #include "voxels/Block.hpp" #include "voxels/Chunk.hpp" @@ -92,6 +93,9 @@ bool WorldRenderer::drawChunk( size_t index, const Camera& camera, Shader& shader, bool culling ) { auto chunk = level->chunks->getChunks()[index]; + if (chunk == nullptr) { + return false; + } if (!chunk->flags.lighted) { return false; } @@ -135,21 +139,29 @@ void WorldRenderer::drawChunks( // [warning] this whole method is not thread-safe for chunks - std::vector indices; - for (size_t i = 0; i < chunks->getVolume(); i++) { - if (chunks->getChunks()[i] == nullptr) continue; - indices.emplace_back(i); + if (indices.size() != chunks->getVolume()) { + indices.clear(); + for (size_t i = 0; i < chunks->getVolume(); i++) { + indices.emplace_back(i); + } } float px = camera.position.x / static_cast(CHUNK_W) - 0.5f; float pz = camera.position.z / static_cast(CHUNK_D) - 0.5f; - std::sort(indices.begin(), indices.end(), [chunks, px, pz](auto i, auto j) { - const auto& chunksBuffer = chunks->getChunks(); - const auto a = chunksBuffer[i].get(); - const auto b = chunksBuffer[j].get(); - auto adx = (a->x - px); - auto adz = (a->z - pz); - auto bdx = (b->x - px); - auto bdz = (b->z - pz); + int chunksWidth = chunks->getWidth(); + int chunksOffsetX = chunks->getOffsetX(); + int chunksOffsetY = chunks->getOffsetY(); + util::insertion_sort(indices.begin(), indices.end(), + [chunks, px, pz, chunksWidth, chunksOffsetX, chunksOffsetY] + (auto i, auto j) + { + int ax = i % chunksWidth + chunksOffsetX; + int az = i / chunksWidth + chunksOffsetY; + int bx = j % chunksWidth + chunksOffsetX; + int bz = j / chunksWidth + chunksOffsetY; + auto adx = (ax - px); + auto adz = (az - pz); + auto bdx = (bx - px); + auto bdz = (bz - pz); return (adx * adx + adz * adz > bdx * bdx + bdz * bdz); }); bool culling = engine->getSettings().graphics.frustumCulling.get(); diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 28a4320b..65893c14 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -44,6 +44,8 @@ class WorldRenderer { std::unique_ptr skybox; std::unique_ptr batch3d; std::unique_ptr modelBatch; + + std::vector indices; float timer = 0.0f; diff --git a/src/util/listutil.hpp b/src/util/listutil.hpp index b3df6deb..4618921d 100644 --- a/src/util/listutil.hpp +++ b/src/util/listutil.hpp @@ -5,6 +5,15 @@ #include namespace util { + template + inline void insertion_sort(Iter first, Iter last, Compare compare) { + for (Iter it = first; it != last; ++it) { + std::rotate( + std::upper_bound(first, it, *it, compare), it, std::next(it) + ); + } + } + template inline bool contains(const std::vector& vec, const T& value) { return std::find(vec.begin(), vec.end(), value) != vec.end(); From fc3d5c54848e5a2c2cf7546f9de88b87b0bb5b29 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 04:46:21 +0300 Subject: [PATCH 14/38] optimize it even more --- src/graphics/render/WorldRenderer.cpp | 34 +++++++++++---------------- src/graphics/render/WorldRenderer.hpp | 11 ++++++++- src/util/listutil.hpp | 9 +++++++ 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index fed5c1fb..d27811a9 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -139,38 +139,32 @@ void WorldRenderer::drawChunks( // [warning] this whole method is not thread-safe for chunks + int chunksWidth = chunks->getWidth(); + int chunksOffsetX = chunks->getOffsetX(); + int chunksOffsetY = chunks->getOffsetY(); + if (indices.size() != chunks->getVolume()) { indices.clear(); - for (size_t i = 0; i < chunks->getVolume(); i++) { - indices.emplace_back(i); + for (int i = 0; i < chunks->getVolume(); i++) { + indices.push_back(ChunksSortEntry {i, 0}); } } float px = camera.position.x / static_cast(CHUNK_W) - 0.5f; float pz = camera.position.z / static_cast(CHUNK_D) - 0.5f; - int chunksWidth = chunks->getWidth(); - int chunksOffsetX = chunks->getOffsetX(); - int chunksOffsetY = chunks->getOffsetY(); - util::insertion_sort(indices.begin(), indices.end(), - [chunks, px, pz, chunksWidth, chunksOffsetX, chunksOffsetY] - (auto i, auto j) - { - int ax = i % chunksWidth + chunksOffsetX; - int az = i / chunksWidth + chunksOffsetY; - int bx = j % chunksWidth + chunksOffsetX; - int bz = j / chunksWidth + chunksOffsetY; - auto adx = (ax - px); - auto adz = (az - pz); - auto bdx = (bx - px); - auto bdz = (bz - pz); - return (adx * adx + adz * adz > bdx * bdx + bdz * bdz); - }); + for (auto& index : indices) { + int x = index.index % chunksWidth + chunksOffsetX - px; + int z = index.index / chunksWidth + chunksOffsetY - pz; + index.d = x * x + z * z; + } + util::insertion_sort(indices.begin(), indices.end()); + bool culling = engine->getSettings().graphics.frustumCulling.get(); 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, culling); + chunks->visible += drawChunk(indices[i].index, camera, shader, culling); } } diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 65893c14..7799e457 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -34,6 +34,15 @@ namespace model { struct Model; } +struct ChunksSortEntry { + int index; + int d; + + inline bool operator<(const ChunksSortEntry& o) const noexcept { + return d > o.d; + } +}; + class WorldRenderer { Engine* engine; Level* level; @@ -45,7 +54,7 @@ class WorldRenderer { std::unique_ptr batch3d; std::unique_ptr modelBatch; - std::vector indices; + std::vector indices; float timer = 0.0f; diff --git a/src/util/listutil.hpp b/src/util/listutil.hpp index 4618921d..9f2afe0c 100644 --- a/src/util/listutil.hpp +++ b/src/util/listutil.hpp @@ -5,6 +5,15 @@ #include namespace util { + template + inline void insertion_sort(Iter first, Iter last) { + for (Iter it = first; it != last; ++it) { + std::rotate( + std::upper_bound(first, it, *it), it, std::next(it) + ); + } + } + template inline void insertion_sort(Iter first, Iter last, Compare compare) { for (Iter it = first; it != last; ++it) { From f50b87e674956be46655feee4dab72070845408b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 05:17:02 +0300 Subject: [PATCH 15/38] fix --- src/graphics/render/WorldRenderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index d27811a9..36c879a5 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -152,9 +152,9 @@ void WorldRenderer::drawChunks( float px = camera.position.x / static_cast(CHUNK_W) - 0.5f; float pz = camera.position.z / static_cast(CHUNK_D) - 0.5f; for (auto& index : indices) { - int x = index.index % chunksWidth + chunksOffsetX - px; - int z = index.index / chunksWidth + chunksOffsetY - pz; - index.d = x * x + z * z; + float x = index.index % chunksWidth + chunksOffsetX - px; + float z = index.index / chunksWidth + chunksOffsetY - pz; + index.d = (x * x + z * z) * 16; } util::insertion_sort(indices.begin(), indices.end()); From 7b4ddfd2781962cbf2b045c9a9e7bd0c5806dea4 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 06:59:14 +0300 Subject: [PATCH 16/38] another fix --- src/graphics/render/WorldRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 36c879a5..1f5864bc 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -154,7 +154,7 @@ void WorldRenderer::drawChunks( for (auto& index : indices) { float x = index.index % chunksWidth + chunksOffsetX - px; float z = index.index / chunksWidth + chunksOffsetY - pz; - index.d = (x * x + z * z) * 16; + index.d = (x * x + z * z) * 1024; } util::insertion_sort(indices.begin(), indices.end()); From db565d23a799814df2f0df786660342ec9a99d63 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 11:46:39 +0300 Subject: [PATCH 17/38] add TextNote --- src/graphics/render/TextNote.cpp | 19 +++++++ src/graphics/render/TextNote.hpp | 18 ++++++ src/graphics/render/WorldRenderer.cpp | 80 ++++++++++++++++++++------- src/graphics/render/WorldRenderer.hpp | 10 ++++ 4 files changed, 108 insertions(+), 19 deletions(-) create mode 100644 src/graphics/render/TextNote.cpp create mode 100644 src/graphics/render/TextNote.hpp diff --git a/src/graphics/render/TextNote.cpp b/src/graphics/render/TextNote.cpp new file mode 100644 index 00000000..f8f424cf --- /dev/null +++ b/src/graphics/render/TextNote.cpp @@ -0,0 +1,19 @@ +#include "TextNote.hpp" + +TextNote::TextNote(std::wstring text, NotePreset preset, glm::vec3 position) + : text(std::move(text)), + preset(std::move(preset)), + position(std::move(position)) { +} + +const std::wstring& TextNote::getText() const { + return text; +} + +const NotePreset& TextNote::getPreset() const { + return preset; +} + +const glm::vec3& TextNote::getPosition() const { + return position; +} diff --git a/src/graphics/render/TextNote.hpp b/src/graphics/render/TextNote.hpp new file mode 100644 index 00000000..a5822005 --- /dev/null +++ b/src/graphics/render/TextNote.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "presets/NotePreset.hpp" + +/// @brief 3D text instance +class TextNote { + std::wstring text; + NotePreset preset; + glm::vec3 position; +public: + TextNote(std::wstring text, NotePreset preset, glm::vec3 position); + + const std::wstring& getText() const; + + const NotePreset& getPreset() const; + + const glm::vec3& getPosition() const; +}; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 1f5864bc..76df02d6 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -32,6 +32,7 @@ #include "world/Level.hpp" #include "world/LevelEvents.hpp" #include "world/World.hpp" +#include "presets/NotePreset.hpp" #include "graphics/commons/Model.hpp" #include "graphics/core/Atlas.hpp" #include "graphics/core/Batch3D.hpp" @@ -47,6 +48,7 @@ #include "ModelBatch.hpp" #include "Skybox.hpp" #include "Emitter.hpp" +#include "TextNote.hpp" bool WorldRenderer::showChunkBorders = false; bool WorldRenderer::showEntitiesDebug = false; @@ -162,9 +164,14 @@ void WorldRenderer::drawChunks( if (culling) { frustumCulling->update(camera.getProjView()); } + chunks->visible = 0; - for (size_t i = 0; i < indices.size(); i++) { - chunks->visible += drawChunk(indices[i].index, camera, shader, culling); + if (GLEW_ARB_multi_draw_indirect && false) { + // TODO: implement Multi Draw Indirect chunks draw + } else { + for (size_t i = 0; i < indices.size(); i++) { + chunks->visible += drawChunk(indices[i].index, camera, shader, culling); + } } } @@ -412,36 +419,71 @@ void WorldRenderer::renderHands( skybox->unbind(); } +void WorldRenderer::renderText( + const TextNote& note, + const DrawContext& context, + const Assets& assets, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible +) { + auto& font = assets.require("normal"); + + const auto& text = note.getText(); + const auto& preset = note.getPreset(); + const auto& pos = note.getPosition(); + + glm::vec3 xvec {1, 0, 0}; + glm::vec3 yvec {0, 1, 0}; + + if (preset.displayMode == NoteDisplayMode::Y_FREE_BILLBOARD || + preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { + xvec = camera.position - pos; + xvec.y = 0; + std::swap(xvec.x, xvec.z); + xvec.z *= -1; + xvec = glm::normalize(xvec); + if (preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { + yvec = camera.up; + } + } + + float ppbx = 100; + float ppby = 100; + font.draw( + *batch3d, + text, + pos - xvec * (font.calcWidth(text, text.length()) * 0.5f) / ppbx, + xvec / ppbx, + yvec / ppby + ); +} + void WorldRenderer::renderTexts( const DrawContext& context, const Camera& camera, const EngineSettings& settings, bool hudVisible ) { + NotePreset preset; + preset.displayMode = NoteDisplayMode::Y_FREE_BILLBOARD; + + TextNote note( + L"Segmentation fault (core dumped)", + std::move(preset), + glm::vec3(0, 100, 0) + ); + const auto& assets = *engine->getAssets(); auto& shader = assets.require("ui3d"); - auto& font = assets.require("normal"); + shader.use(); shader.uniformMatrix("u_projview", camera.getProjView()); shader.uniformMatrix("u_apply", glm::mat4(1.0f)); batch3d->begin(); - std::wstring string = L"Segmentation fault (core dumped)"; - glm::vec3 pos(0, 100, 0); - auto zvec = camera.position - pos; - zvec.y = 0; - std::swap(zvec.x, zvec.z); - zvec.z *= -1; - zvec = glm::normalize(zvec); + + renderText(note, context, assets, camera, settings, hudVisible); - float ppbx = 100; - float ppby = 100; - font.draw( - *batch3d, - string, - pos - zvec * (font.calcWidth(string, string.length()) * 0.5f) / ppbx, - zvec / ppbx, - camera.up / ppby - ); batch3d->flush(); } diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 7799e457..0b0eb171 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -28,6 +28,7 @@ class DrawContext; class ModelBatch; class Assets; class Emitter; +class TextNote; struct EngineSettings; namespace model { @@ -92,6 +93,15 @@ class WorldRenderer { float fogFactor ); + void renderText( + const TextNote& note, + const DrawContext& context, + const Assets& assets, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible + ); + void renderTexts( const DrawContext& context, const Camera& camera, From 0a8ea7e597fac904ed7fd8da4d9370a9f0711e7a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 13 Nov 2024 12:00:55 +0300 Subject: [PATCH 18/38] disable mip-mapping in fonts --- src/assets/assetload_funcs.cpp | 4 +++- src/graphics/core/GLTexture.cpp | 16 +++++++++++++++- src/graphics/core/GLTexture.hpp | 2 ++ src/graphics/core/Texture.hpp | 2 ++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index ed4f076f..b73a3882 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -151,7 +151,9 @@ assetload::postfunc assetload::font( if (page == nullptr) { textures.emplace_back(nullptr); } else { - textures.emplace_back(Texture::from(page.get())); + auto texture = Texture::from(page.get()); + texture->setMipMapping(false); + textures.emplace_back(std::move(texture)); } } assets->store( diff --git a/src/graphics/core/GLTexture.cpp b/src/graphics/core/GLTexture.cpp index 4781536e..3756d758 100644 --- a/src/graphics/core/GLTexture.cpp +++ b/src/graphics/core/GLTexture.cpp @@ -59,7 +59,9 @@ std::unique_ptr GLTexture::readData() { glBindTexture(GL_TEXTURE_2D, id); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.get()); glBindTexture(GL_TEXTURE_2D, 0); - return std::make_unique(ImageFormat::rgba8888, width, height, data.release()); + return std::make_unique( + ImageFormat::rgba8888, width, height, data.release() + ); } void GLTexture::setNearestFilter() { @@ -69,6 +71,18 @@ void GLTexture::setNearestFilter() { glBindTexture(GL_TEXTURE_2D, 0); } +void GLTexture::setMipMapping(bool flag) { + bind(); + if (flag) { + glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST + ); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + glBindTexture(GL_TEXTURE_2D, 0); +} + std::unique_ptr GLTexture::from(const ImageData* image) { uint width = image->getWidth(); uint height = image->getHeight(); diff --git a/src/graphics/core/GLTexture.hpp b/src/graphics/core/GLTexture.hpp index b5f82384..85d7f85d 100644 --- a/src/graphics/core/GLTexture.hpp +++ b/src/graphics/core/GLTexture.hpp @@ -18,6 +18,8 @@ public: virtual void reload(const ImageData& image) override; + virtual void setMipMapping(bool flag) override; + virtual std::unique_ptr readData() override; virtual uint getId() const override; diff --git a/src/graphics/core/Texture.hpp b/src/graphics/core/Texture.hpp index ba5b066e..bc7b73f0 100644 --- a/src/graphics/core/Texture.hpp +++ b/src/graphics/core/Texture.hpp @@ -34,5 +34,7 @@ public: virtual uint getId() const = 0; + virtual void setMipMapping(bool flag) = 0; + static std::unique_ptr from(const ImageData* image); }; From 78d5ab02c2ba8a3d05cf5639eb10a49c9ca14ec3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 14 Nov 2024 01:04:32 +0300 Subject: [PATCH 19/38] fix: fatal error on pack removal when no world open --- src/logic/EngineController.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/logic/EngineController.cpp b/src/logic/EngineController.cpp index f6b58a0d..4c38fc78 100644 --- a/src/logic/EngineController.cpp +++ b/src/logic/EngineController.cpp @@ -253,14 +253,16 @@ void EngineController::reconfigPacks( bool hasIndices = false; std::stringstream ss; - for (const auto& id : packsToRemove) { - auto runtime = content->getPackRuntime(id); - if (runtime && runtime->getStats().hasSavingContent()) { - if (hasIndices) { - ss << ", "; + if (content) { + for (const auto& id : packsToRemove) { + auto runtime = content->getPackRuntime(id); + if (runtime && runtime->getStats().hasSavingContent()) { + if (hasIndices) { + ss << ", "; + } + hasIndices = true; + ss << id; } - hasIndices = true; - ss << id; } } From 5b6ada6e5dc6cee503139327981240e51212953f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 14 Nov 2024 02:21:15 +0300 Subject: [PATCH 20/38] add more NotePreset properties --- src/graphics/core/Batch3D.cpp | 10 +++++- src/graphics/core/Batch3D.hpp | 6 +++- src/graphics/core/Font.cpp | 2 +- src/graphics/render/WorldRenderer.cpp | 50 ++++++++++++++++++++------- src/graphics/render/WorldRenderer.hpp | 3 +- src/maths/util.hpp | 5 +++ src/presets/NotePreset.cpp | 12 ++++++- src/presets/NotePreset.hpp | 4 +++ 8 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/graphics/core/Batch3D.cpp b/src/graphics/core/Batch3D.cpp index c2db0eee..1770fc21 100644 --- a/src/graphics/core/Batch3D.cpp +++ b/src/graphics/core/Batch3D.cpp @@ -125,7 +125,7 @@ void Batch3D::sprite( float h, int atlasRes, int index, - glm::vec4 tint + const glm::vec4& tint ) { float scale = 1.0f / static_cast(atlasRes); float u = (index % atlasRes) * scale; @@ -288,3 +288,11 @@ void Batch3D::flushPoints() { mesh->draw(GL_POINTS); index = 0; } + +void Batch3D::setColor(const glm::vec4& color) { + tint = color; +} + +const glm::vec4& Batch3D::getColor() const { + return tint; +} diff --git a/src/graphics/core/Batch3D.hpp b/src/graphics/core/Batch3D.hpp index cf787935..020f03bd 100644 --- a/src/graphics/core/Batch3D.hpp +++ b/src/graphics/core/Batch3D.hpp @@ -17,6 +17,7 @@ class Batch3D : public Flushable { std::unique_ptr mesh; std::unique_ptr blank; size_t index; + glm::vec4 tint {1.0f}; const Texture* currentTexture; @@ -65,7 +66,7 @@ public: float h, int atlasRes, int index, - glm::vec4 tint + const glm::vec4& tint ); void xSprite( float w, @@ -91,4 +92,7 @@ public: void point(const glm::vec3& pos, const glm::vec4& tint); void flush() override; void flushPoints(); + + void setColor(const glm::vec4& color); + const glm::vec4& getColor() const; }; diff --git a/src/graphics/core/Font.cpp b/src/graphics/core/Font.cpp index 31fe60c0..9c40809f 100644 --- a/src/graphics/core/Font.cpp +++ b/src/graphics/core/Font.cpp @@ -81,7 +81,7 @@ static inline void draw_glyph( 0.5f, 16, c, - glm::vec4(1.0f) + batch.getColor() ); } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 76df02d6..e272040d 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -427,15 +427,25 @@ void WorldRenderer::renderText( const EngineSettings& settings, bool hudVisible ) { - auto& font = assets.require("normal"); - const auto& text = note.getText(); const auto& preset = note.getPreset(); const auto& pos = note.getPosition(); + if (util::distance2(pos, camera.position) > + util::sqr(preset.renderDistance / camera.zoom)) { + return; + } + + // Projected notes are displayed on the front layer only + if (preset.displayMode == NoteDisplayMode::PROJECTED) { + return; + } + auto& font = assets.require("normal"); + glm::vec3 xvec {1, 0, 0}; glm::vec3 yvec {0, 1, 0}; + int width = font.calcWidth(text, text.length()); if (preset.displayMode == NoteDisplayMode::Y_FREE_BILLBOARD || preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { xvec = camera.position - pos; @@ -447,13 +457,22 @@ void WorldRenderer::renderText( yvec = camera.up; } } + + if (preset.displayMode != NoteDisplayMode::PROJECTED) { + if (!frustumCulling->isBoxVisible(pos - xvec * (width * 0.5f), + pos + xvec * (width * 0.5f))) { + return; + } + } - float ppbx = 100; - float ppby = 100; + float ppbx = 1.0f / preset.scale; + float ppby = 1.0f / preset.scale; + + batch3d->setColor(preset.color); font.draw( *batch3d, text, - pos - xvec * (font.calcWidth(text, text.length()) * 0.5f) / ppbx, + pos - xvec * (width * 0.5f) / ppbx, xvec / ppbx, yvec / ppby ); @@ -463,15 +482,19 @@ void WorldRenderer::renderTexts( const DrawContext& context, const Camera& camera, const EngineSettings& settings, - bool hudVisible + bool hudVisible, + bool frontLayer ) { + std::vector notes; NotePreset preset; - preset.displayMode = NoteDisplayMode::Y_FREE_BILLBOARD; + preset.displayMode = NoteDisplayMode::STATIC_BILLBOARD; + preset.color = glm::vec4(0, 0, 0, 1); + preset.scale = 0.005f; - TextNote note( - L"Segmentation fault (core dumped)", + notes.emplace_back( + L"Segmentation fault", std::move(preset), - glm::vec3(0, 100, 0) + glm::vec3(0.5f, 99.5f, 0.0015f) ); const auto& assets = *engine->getAssets(); @@ -482,8 +505,9 @@ void WorldRenderer::renderTexts( shader.uniformMatrix("u_apply", glm::mat4(1.0f)); batch3d->begin(); - renderText(note, context, assets, camera, settings, hudVisible); - + for (const auto& note : notes) { + renderText(note, context, assets, camera, settings, hudVisible); + } batch3d->flush(); } @@ -523,7 +547,7 @@ void WorldRenderer::draw( DrawContext ctx = wctx.sub(); ctx.setDepthTest(true); ctx.setCullFace(true); - renderTexts(ctx, camera, settings, hudVisible); + renderTexts(ctx, camera, settings, hudVisible, false); renderLevel(ctx, camera, settings, delta, pause); // Debug lines if (hudVisible) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 0b0eb171..a9adde21 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -106,7 +106,8 @@ class WorldRenderer { const DrawContext& context, const Camera& camera, const EngineSettings& settings, - bool hudVisible + bool hudVisible, + bool frontLayer ); public: std::unique_ptr particles; diff --git a/src/maths/util.hpp b/src/maths/util.hpp index 7500bf2a..ec128917 100644 --- a/src/maths/util.hpp +++ b/src/maths/util.hpp @@ -70,6 +70,11 @@ namespace util { } }; + template + inline T sqr(T value) { + return value * value; + } + /// @return integer square of distance between two points /// @note glm::distance2 does not support integer vectors inline int distance2(const glm::ivec3& a, const glm::ivec3& b) { diff --git a/src/presets/NotePreset.cpp b/src/presets/NotePreset.cpp index e8601ab7..58cffcd1 100644 --- a/src/presets/NotePreset.cpp +++ b/src/presets/NotePreset.cpp @@ -3,6 +3,8 @@ #include #include +#include "data/dv_util.hpp" + std::string to_string(NoteDisplayMode mode) { static std::vector names = { "static_billboard", @@ -29,7 +31,10 @@ std::optional NoteDisplayMode_from(std::string_view s) { dv::value NotePreset::serialize() const { return dv::object({ - {"display", to_string(displayMode)} + {"display", to_string(displayMode)}, + {"color", dv::to_value(color)}, + {"scale", scale}, + {"render_distance", renderDistance} }); } @@ -37,4 +42,9 @@ void NotePreset::deserialize(const dv::value& src) { if (src.has("display")) { displayMode = NoteDisplayMode_from(src["display"].asString()).value(); } + if (src.has("color")) { + dv::get_vec(src["color"], color); + } + src.at("scale").get(scale); + src.at("render_distance").get(renderDistance); } diff --git a/src/presets/NotePreset.hpp b/src/presets/NotePreset.hpp index cf8aa15f..4ae78b5c 100644 --- a/src/presets/NotePreset.hpp +++ b/src/presets/NotePreset.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "interfaces/Serializable.hpp" @@ -17,6 +18,9 @@ std::optional NoteDisplayMode_from(std::string_view s); struct NotePreset : public Serializable { NoteDisplayMode displayMode = NoteDisplayMode::STATIC_BILLBOARD; + glm::vec4 color {1.0f}; + float scale = 1.0f; + float renderDistance = 10.0f; dv::value serialize() const override; void deserialize(const dv::value& src) override; From 42b26707cbd74fdeb9cc4d5d219afcd9af850476 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 14 Nov 2024 05:43:01 +0300 Subject: [PATCH 21/38] move 3d texts rendering code to TextsRenderer --- src/graphics/render/TextsRenderer.cpp | 104 ++++++++++++++++++++++++++ src/graphics/render/TextsRenderer.hpp | 35 +++++++++ src/graphics/render/WorldRenderer.cpp | 101 ++----------------------- src/graphics/render/WorldRenderer.hpp | 20 +---- 4 files changed, 147 insertions(+), 113 deletions(-) create mode 100644 src/graphics/render/TextsRenderer.cpp create mode 100644 src/graphics/render/TextsRenderer.hpp diff --git a/src/graphics/render/TextsRenderer.cpp b/src/graphics/render/TextsRenderer.cpp new file mode 100644 index 00000000..7fd6c214 --- /dev/null +++ b/src/graphics/render/TextsRenderer.cpp @@ -0,0 +1,104 @@ +#include "TextsRenderer.hpp" + +#include "TextNote.hpp" +#include "maths/util.hpp" +#include "assets/Assets.hpp" +#include "window/Camera.hpp" +#include "maths/FrustumCulling.hpp" +#include "graphics/core/Font.hpp" +#include "graphics/core/Batch3D.hpp" +#include "graphics/core/Shader.hpp" +#include "presets/NotePreset.hpp" + +TextsRenderer::TextsRenderer(const Frustum* frustum) : frustum(frustum) { +} + +void TextsRenderer::renderText( + Batch3D& batch, + const TextNote& note, + const DrawContext& context, + const Assets& assets, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible +) { + const auto& text = note.getText(); + const auto& preset = note.getPreset(); + const auto& pos = note.getPosition(); + + if (util::distance2(pos, camera.position) > + util::sqr(preset.renderDistance / camera.zoom)) { + return; + } + + // Projected notes are displayed on the front layer only + if (preset.displayMode == NoteDisplayMode::PROJECTED) { + return; + } + auto& font = assets.require("normal"); + + glm::vec3 xvec {1, 0, 0}; + glm::vec3 yvec {0, 1, 0}; + + int width = font.calcWidth(text, text.length()); + if (preset.displayMode == NoteDisplayMode::Y_FREE_BILLBOARD || + preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { + xvec = camera.position - pos; + xvec.y = 0; + std::swap(xvec.x, xvec.z); + xvec.z *= -1; + xvec = glm::normalize(xvec); + if (preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { + yvec = camera.up; + } + } + + if (preset.displayMode != NoteDisplayMode::PROJECTED) { + if (!frustum->isBoxVisible(pos - xvec * (width * 0.5f), + pos + xvec * (width * 0.5f))) { + return; + } + } + + batch.setColor(preset.color); + font.draw( + batch, + text, + pos - xvec * (width * 0.5f) * preset.scale, + xvec * preset.scale, + yvec * preset.scale + ); +} + +void TextsRenderer::renderTexts( + Batch3D& batch, + const DrawContext& context, + const Assets& assets, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible, + bool frontLayer +) { + std::vector notes; + NotePreset preset; + preset.displayMode = NoteDisplayMode::STATIC_BILLBOARD; + preset.color = glm::vec4(0, 0, 0, 1); + preset.scale = 0.005f; + + notes.emplace_back( + L"Segmentation fault", + std::move(preset), + glm::vec3(0.5f, 99.5f, 0.0015f) + ); + auto& shader = assets.require("ui3d"); + + shader.use(); + shader.uniformMatrix("u_projview", camera.getProjView()); + shader.uniformMatrix("u_apply", glm::mat4(1.0f)); + batch.begin(); + + for (const auto& note : notes) { + renderText(batch, note, context, assets, camera, settings, hudVisible); + } + batch.flush(); +} diff --git a/src/graphics/render/TextsRenderer.hpp b/src/graphics/render/TextsRenderer.hpp new file mode 100644 index 00000000..df0de386 --- /dev/null +++ b/src/graphics/render/TextsRenderer.hpp @@ -0,0 +1,35 @@ +#pragma once + +class DrawContext; +class Camera; +class Assets; +class Batch3D; +class Frustum; +class TextNote; +struct EngineSettings; + +class TextsRenderer { + const Frustum* frustum; + + void renderText( + Batch3D& batch, + const TextNote& note, + const DrawContext& context, + const Assets& assets, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible + ); +public: + TextsRenderer(const Frustum* frustum); + + void renderTexts( + Batch3D& batch, + const DrawContext& context, + const Assets& assets, + const Camera& camera, + const EngineSettings& settings, + bool hudVisible, + bool frontLayer + ); +}; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e272040d..b63569d5 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -32,7 +32,6 @@ #include "world/Level.hpp" #include "world/LevelEvents.hpp" #include "world/World.hpp" -#include "presets/NotePreset.hpp" #include "graphics/commons/Model.hpp" #include "graphics/core/Atlas.hpp" #include "graphics/core/Batch3D.hpp" @@ -44,6 +43,7 @@ #include "graphics/core/Texture.hpp" #include "graphics/core/Font.hpp" #include "ParticlesRenderer.hpp" +#include "TextsRenderer.hpp" #include "ChunksRenderer.hpp" #include "ModelBatch.hpp" #include "Skybox.hpp" @@ -71,7 +71,8 @@ WorldRenderer::WorldRenderer( *engine->getAssets(), *frontend->getLevel(), &engine->getSettings().graphics - )) { + )), + texts(std::make_unique(frustumCulling.get())) { renderer = std::make_unique( level, frontend->getContentGfxCache(), &engine->getSettings() ); @@ -419,98 +420,6 @@ void WorldRenderer::renderHands( skybox->unbind(); } -void WorldRenderer::renderText( - const TextNote& note, - const DrawContext& context, - const Assets& assets, - const Camera& camera, - const EngineSettings& settings, - bool hudVisible -) { - const auto& text = note.getText(); - const auto& preset = note.getPreset(); - const auto& pos = note.getPosition(); - - if (util::distance2(pos, camera.position) > - util::sqr(preset.renderDistance / camera.zoom)) { - return; - } - - // Projected notes are displayed on the front layer only - if (preset.displayMode == NoteDisplayMode::PROJECTED) { - return; - } - auto& font = assets.require("normal"); - - glm::vec3 xvec {1, 0, 0}; - glm::vec3 yvec {0, 1, 0}; - - int width = font.calcWidth(text, text.length()); - if (preset.displayMode == NoteDisplayMode::Y_FREE_BILLBOARD || - preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { - xvec = camera.position - pos; - xvec.y = 0; - std::swap(xvec.x, xvec.z); - xvec.z *= -1; - xvec = glm::normalize(xvec); - if (preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { - yvec = camera.up; - } - } - - if (preset.displayMode != NoteDisplayMode::PROJECTED) { - if (!frustumCulling->isBoxVisible(pos - xvec * (width * 0.5f), - pos + xvec * (width * 0.5f))) { - return; - } - } - - float ppbx = 1.0f / preset.scale; - float ppby = 1.0f / preset.scale; - - batch3d->setColor(preset.color); - font.draw( - *batch3d, - text, - pos - xvec * (width * 0.5f) / ppbx, - xvec / ppbx, - yvec / ppby - ); -} - -void WorldRenderer::renderTexts( - const DrawContext& context, - const Camera& camera, - const EngineSettings& settings, - bool hudVisible, - bool frontLayer -) { - std::vector notes; - NotePreset preset; - preset.displayMode = NoteDisplayMode::STATIC_BILLBOARD; - preset.color = glm::vec4(0, 0, 0, 1); - preset.scale = 0.005f; - - notes.emplace_back( - L"Segmentation fault", - std::move(preset), - glm::vec3(0.5f, 99.5f, 0.0015f) - ); - - const auto& assets = *engine->getAssets(); - auto& shader = assets.require("ui3d"); - - shader.use(); - shader.uniformMatrix("u_projview", camera.getProjView()); - shader.uniformMatrix("u_apply", glm::mat4(1.0f)); - batch3d->begin(); - - for (const auto& note : notes) { - renderText(note, context, assets, camera, settings, hudVisible); - } - batch3d->flush(); -} - void WorldRenderer::draw( const DrawContext& pctx, Camera& camera, @@ -547,7 +456,9 @@ void WorldRenderer::draw( DrawContext ctx = wctx.sub(); ctx.setDepthTest(true); ctx.setCullFace(true); - renderTexts(ctx, camera, settings, hudVisible, false); + texts->renderTexts( + *batch3d, ctx, assets, camera, settings, hudVisible, false + ); renderLevel(ctx, camera, settings, delta, pause); // Debug lines if (hudVisible) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index a9adde21..3c8dc884 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -17,6 +17,7 @@ class Batch3D; class LineBatch; class ChunksRenderer; class ParticlesRenderer; +class TextsRenderer; class Shader; class Frustum; class Engine; @@ -28,7 +29,6 @@ class DrawContext; class ModelBatch; class Assets; class Emitter; -class TextNote; struct EngineSettings; namespace model { @@ -51,6 +51,7 @@ class WorldRenderer { std::unique_ptr frustumCulling; std::unique_ptr lineBatch; std::unique_ptr renderer; + std::unique_ptr texts; std::unique_ptr skybox; std::unique_ptr batch3d; std::unique_ptr modelBatch; @@ -92,23 +93,6 @@ class WorldRenderer { const EngineSettings& settings, float fogFactor ); - - void renderText( - const TextNote& note, - const DrawContext& context, - const Assets& assets, - const Camera& camera, - const EngineSettings& settings, - bool hudVisible - ); - - void renderTexts( - const DrawContext& context, - const Camera& camera, - const EngineSettings& settings, - bool hudVisible, - bool frontLayer - ); public: std::unique_ptr particles; From f9f4d2037f266d81320df4664660dbb2ad0b763d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 14 Nov 2024 06:04:26 +0300 Subject: [PATCH 22/38] refactor WorldRenderer --- src/graphics/render/GuidesRenderer.cpp | 109 ++++++++++++++++++++++ src/graphics/render/GuidesRenderer.hpp | 28 ++++++ src/graphics/render/ParticlesRenderer.cpp | 2 +- src/graphics/render/WorldRenderer.cpp | 108 ++------------------- src/graphics/render/WorldRenderer.hpp | 13 +-- 5 files changed, 150 insertions(+), 110 deletions(-) create mode 100644 src/graphics/render/GuidesRenderer.cpp create mode 100644 src/graphics/render/GuidesRenderer.hpp diff --git a/src/graphics/render/GuidesRenderer.cpp b/src/graphics/render/GuidesRenderer.cpp new file mode 100644 index 00000000..9476cf41 --- /dev/null +++ b/src/graphics/render/GuidesRenderer.cpp @@ -0,0 +1,109 @@ +#include "GuidesRenderer.hpp" + +#include + +#include "graphics/core/Shader.hpp" +#include "graphics/core/LineBatch.hpp" +#include "graphics/core/DrawContext.hpp" +#include "maths/voxmaths.hpp" +#include "window/Camera.hpp" +#include "constants.hpp" + +void GuidesRenderer::drawBorders( + LineBatch& batch, int sx, int sy, int sz, int ex, int ey, int ez +) { + int ww = ex - sx; + int dd = ez - sz; + /*corner*/ { + batch.line(sx, sy, sz, sx, ey, sz, 0.8f, 0, 0.8f, 1); + batch.line(sx, sy, ez, sx, ey, ez, 0.8f, 0, 0.8f, 1); + batch.line(ex, sy, sz, ex, ey, sz, 0.8f, 0, 0.8f, 1); + batch.line(ex, sy, ez, ex, ey, ez, 0.8f, 0, 0.8f, 1); + } + for (int i = 2; i < ww; i += 2) { + batch.line(sx + i, sy, sz, sx + i, ey, sz, 0, 0, 0.8f, 1); + batch.line(sx + i, sy, ez, sx + i, ey, ez, 0, 0, 0.8f, 1); + } + for (int i = 2; i < dd; i += 2) { + batch.line(sx, sy, sz + i, sx, ey, sz + i, 0.8f, 0, 0, 1); + batch.line(ex, sy, sz + i, ex, ey, sz + i, 0.8f, 0, 0, 1); + } + for (int i = sy; i < ey; i += 2) { + batch.line(sx, i, sz, sx, i, ez, 0, 0.8f, 0, 1); + batch.line(sx, i, ez, ex, i, ez, 0, 0.8f, 0, 1); + batch.line(ex, i, ez, ex, i, sz, 0, 0.8f, 0, 1); + batch.line(ex, i, sz, sx, i, sz, 0, 0.8f, 0, 1); + } + batch.flush(); +} + +void GuidesRenderer::drawCoordSystem( + LineBatch& batch, const DrawContext& pctx, float length +) { + auto ctx = pctx.sub(); + ctx.setDepthTest(false); + batch.lineWidth(4.0f); + batch.line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); + batch.line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); + batch.line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); + batch.flush(); + + ctx.setDepthTest(true); + batch.lineWidth(2.0f); + batch.line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); + batch.line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); + batch.line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f); +} + +void GuidesRenderer::renderDebugLines( + const DrawContext& pctx, + const Camera& camera, + LineBatch& batch, + Shader& linesShader, + bool showChunkBorders +) { + DrawContext ctx = pctx.sub(&batch); + const auto& viewport = ctx.getViewport(); + uint displayWidth = viewport.getWidth(); + uint displayHeight = viewport.getHeight(); + + ctx.setDepthTest(true); + + linesShader.use(); + + if (showChunkBorders) { + linesShader.uniformMatrix("u_projview", camera.getProjView()); + glm::vec3 coord = camera.position; + if (coord.x < 0) coord.x--; + if (coord.z < 0) coord.z--; + int cx = floordiv(static_cast(coord.x), CHUNK_W); + int cz = floordiv(static_cast(coord.z), CHUNK_D); + + drawBorders( + batch, + cx * CHUNK_W, + 0, + cz * CHUNK_D, + (cx + 1) * CHUNK_W, + CHUNK_H, + (cz + 1) * CHUNK_D + ); + } + + float length = 40.f; + glm::vec3 tsl(displayWidth / 2, displayHeight / 2, 0.f); + glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); + linesShader.uniformMatrix( + "u_projview", + glm::ortho( + 0.f, + static_cast(displayWidth), + 0.f, + static_cast(displayHeight), + -length, + length + ) * model * + glm::inverse(camera.rotation) + ); + drawCoordSystem(batch, ctx, length); +} diff --git a/src/graphics/render/GuidesRenderer.hpp b/src/graphics/render/GuidesRenderer.hpp new file mode 100644 index 00000000..36daad82 --- /dev/null +++ b/src/graphics/render/GuidesRenderer.hpp @@ -0,0 +1,28 @@ +#pragma once + +class LineBatch; +class DrawContext; +class Camera; +class Shader; + +class GuidesRenderer { +public: + void drawBorders( + LineBatch& batch, int sx, int sy, int sz, int ex, int ey, int ez + ); + void drawCoordSystem( + LineBatch& batch, const DrawContext& pctx, float length + ); + + /// @brief Render all debug lines (chunks borders, coord system guides) + /// @param context graphics context + /// @param camera active camera + /// @param linesShader shader used + void renderDebugLines( + const DrawContext& context, + const Camera& camera, + LineBatch& batch, + Shader& linesShader, + bool showChunkBorders + ); +}; diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 0e030dbc..1fd8e860 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -18,7 +18,7 @@ size_t ParticlesRenderer::aliveEmitters = 0; ParticlesRenderer::ParticlesRenderer( const Assets& assets, const Level& level, const GraphicsSettings* settings ) - : batch(std::make_unique(1024)), + : batch(std::make_unique(4096)), level(level), assets(assets), settings(settings) {} diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index b63569d5..ac9f763f 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -45,6 +45,7 @@ #include "ParticlesRenderer.hpp" #include "TextsRenderer.hpp" #include "ChunksRenderer.hpp" +#include "GuidesRenderer.hpp" #include "ModelBatch.hpp" #include "Skybox.hpp" #include "Emitter.hpp" @@ -72,7 +73,8 @@ WorldRenderer::WorldRenderer( *frontend->getLevel(), &engine->getSettings().graphics )), - texts(std::make_unique(frustumCulling.get())) { + texts(std::make_unique(frustumCulling.get())), + guides(std::make_unique()) { renderer = std::make_unique( level, frontend->getContentGfxCache(), &engine->getSettings() ); @@ -96,10 +98,7 @@ bool WorldRenderer::drawChunk( size_t index, const Camera& camera, Shader& shader, bool culling ) { auto chunk = level->chunks->getChunks()[index]; - if (chunk == nullptr) { - return false; - } - if (!chunk->flags.lighted) { + if (chunk == nullptr || !chunk->flags.lighted) { return false; } float distance = glm::distance( @@ -297,66 +296,6 @@ void WorldRenderer::renderLines( } } -void WorldRenderer::renderDebugLines( - const DrawContext& pctx, const Camera& camera, Shader& linesShader -) { - DrawContext ctx = pctx.sub(lineBatch.get()); - const auto& viewport = ctx.getViewport(); - uint displayWidth = viewport.getWidth(); - uint displayHeight = viewport.getHeight(); - - ctx.setDepthTest(true); - - linesShader.use(); - - if (showChunkBorders) { - linesShader.uniformMatrix("u_projview", camera.getProjView()); - glm::vec3 coord = player->fpCamera->position; - if (coord.x < 0) coord.x--; - if (coord.z < 0) coord.z--; - int cx = floordiv(static_cast(coord.x), CHUNK_W); - int cz = floordiv(static_cast(coord.z), CHUNK_D); - - drawBorders( - cx * CHUNK_W, - 0, - cz * CHUNK_D, - (cx + 1) * CHUNK_W, - CHUNK_H, - (cz + 1) * CHUNK_D - ); - } - - float length = 40.f; - glm::vec3 tsl(displayWidth / 2, displayHeight / 2, 0.f); - glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); - linesShader.uniformMatrix( - "u_projview", - glm::ortho( - 0.f, - static_cast(displayWidth), - 0.f, - static_cast(displayHeight), - -length, - length - ) * model * - glm::inverse(camera.rotation) - ); - - ctx.setDepthTest(false); - lineBatch->lineWidth(4.0f); - lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); - lineBatch->flush(); - - ctx.setDepthTest(true); - lineBatch->lineWidth(2.0f); - lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f); -} - void WorldRenderer::renderHands( const Camera& camera, const Assets& assets, float delta ) { @@ -441,8 +380,7 @@ void WorldRenderer::draw( const auto& assets = *engine->getAssets(); auto& linesShader = assets.require("lines"); - // World render scope with diegetic HUD included - { + /* World render scope with diegetic HUD included */ { DrawContext wctx = pctx.sub(); postProcessing->use(wctx); @@ -451,8 +389,8 @@ void WorldRenderer::draw( // Drawing background sky plane skybox->draw(pctx, camera, assets, worldInfo.daytime, worldInfo.fog); - // Actually world render with depth buffer on - { + + /* Actually world render with depth buffer on */ { DrawContext ctx = wctx.sub(); ctx.setDepthTest(true); ctx.setCullFace(true); @@ -463,7 +401,9 @@ void WorldRenderer::draw( // Debug lines if (hudVisible) { if (player->debug) { - renderDebugLines(ctx, camera, linesShader); + guides->renderDebugLines( + ctx, camera, *lineBatch, linesShader, showChunkBorders + ); } renderLines(camera, linesShader, ctx); if (player->currentCamera == player->fpCamera) { @@ -527,34 +467,6 @@ void WorldRenderer::renderBlockOverlay(const DrawContext& wctx, const Assets& as } } -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->flush(); -} - void WorldRenderer::clear() { renderer->clear(); } diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 3c8dc884..976f467e 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -17,6 +17,7 @@ class Batch3D; class LineBatch; class ChunksRenderer; class ParticlesRenderer; +class GuidesRenderer; class TextsRenderer; class Shader; class Frustum; @@ -52,6 +53,7 @@ class WorldRenderer { std::unique_ptr lineBatch; std::unique_ptr renderer; std::unique_ptr texts; + std::unique_ptr guides; std::unique_ptr skybox; std::unique_ptr batch3d; std::unique_ptr modelBatch; @@ -75,16 +77,6 @@ class WorldRenderer { const Camera& camera, Shader& linesShader, const DrawContext& pctx ); - /// @brief Render all debug lines (chunks borders, coord system guides) - /// @param context graphics context - /// @param camera active camera - /// @param linesShader shader used - void renderDebugLines( - const DrawContext& context, - const Camera& camera, - Shader& linesShader - ); - void renderBlockOverlay(const DrawContext& context, const Assets& assets); void setupWorldShader( @@ -110,7 +102,6 @@ public: float delta, PostProcessing* postProcessing ); - void drawBorders(int sx, int sy, int sz, int ex, int ey, int ez); /// @brief Render level without diegetic interface /// @param context graphics context From e9163f4228cd2536d594a0d723a310c437391cd6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 14 Nov 2024 06:13:53 +0300 Subject: [PATCH 23/38] refactor WorldRenderer --- src/graphics/render/WorldRenderer.cpp | 19 ++++++++++--------- src/graphics/render/WorldRenderer.hpp | 3 ++- src/objects/Entities.cpp | 2 +- src/objects/Entities.hpp | 2 +- src/objects/rigging.cpp | 6 +++--- src/objects/rigging.hpp | 4 ++-- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index ac9f763f..ed3985d7 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -216,15 +216,20 @@ void WorldRenderer::renderLevel( const Camera& camera, const EngineSettings& settings, float delta, - bool pause + bool pause, + bool hudVisible ) { - auto assets = engine->getAssets(); + const auto& assets = *engine->getAssets(); + + texts->renderTexts( + *batch3d, ctx, assets, camera, settings, hudVisible, false + ); bool culling = engine->getSettings().graphics.frustumCulling.get(); float fogFactor = 15.0f / static_cast(settings.chunks.loadDistance.get() - 2); - auto& entityShader = assets->require("entity"); + auto& entityShader = assets.require("entity"); setupWorldShader(entityShader, camera, settings, fogFactor); skybox->bind(); @@ -238,7 +243,7 @@ void WorldRenderer::renderLevel( particles->render(camera, delta * !pause); modelBatch->render(); - auto& shader = assets->require("main"); + auto& shader = assets.require("main"); setupWorldShader(shader, camera, settings, fogFactor); drawChunks(level->chunks.get(), camera, shader); @@ -388,16 +393,12 @@ void WorldRenderer::draw( // Drawing background sky plane skybox->draw(pctx, camera, assets, worldInfo.daytime, worldInfo.fog); - /* Actually world render with depth buffer on */ { DrawContext ctx = wctx.sub(); ctx.setDepthTest(true); ctx.setCullFace(true); - texts->renderTexts( - *batch3d, ctx, assets, camera, settings, hudVisible, false - ); - renderLevel(ctx, camera, settings, delta, pause); + renderLevel(ctx, camera, settings, delta, pause, hudVisible); // Debug lines if (hudVisible) { if (player->debug) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 976f467e..6dd61fca 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -112,7 +112,8 @@ public: const Camera& camera, const EngineSettings& settings, float delta, - bool pause + bool pause, + bool hudVisible ); void clear(); diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index ba7b0eec..614adf41 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -550,7 +550,7 @@ void Entities::renderDebug( } void Entities::render( - Assets* assets, + const Assets& assets, ModelBatch& batch, const Frustum* frustum, float delta, diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index 099fc99b..0026d15e 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -194,7 +194,7 @@ public: LineBatch& batch, const Frustum* frustum, const DrawContext& ctx ); void render( - Assets* assets, + const Assets& assets, ModelBatch& batch, const Frustum* frustum, float delta, diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index 8a31aeb8..b08b8441 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -12,9 +12,9 @@ using namespace rigging; -void ModelReference::refresh(const Assets* assets) { +void ModelReference::refresh(const Assets& assets) { if (updateFlag) { - model = assets->get(name); + model = assets.get(name); updateFlag = false; } } @@ -95,7 +95,7 @@ void SkeletonConfig::update(Skeleton& skeleton, glm::mat4 matrix) const { } void SkeletonConfig::render( - Assets* assets, + const Assets& assets, ModelBatch& batch, Skeleton& skeleton, const glm::mat4& matrix diff --git a/src/objects/rigging.hpp b/src/objects/rigging.hpp index ca9ec5de..de083f9b 100644 --- a/src/objects/rigging.hpp +++ b/src/objects/rigging.hpp @@ -32,7 +32,7 @@ namespace rigging { model::Model* model; bool updateFlag; - void refresh(const Assets* assets); + void refresh(const Assets& assets); }; class Bone { @@ -111,7 +111,7 @@ namespace rigging { void update(Skeleton& skeleton, glm::mat4 matrix) const; void render( - Assets* assets, + const Assets& assets, ModelBatch& batch, Skeleton& skeleton, const glm::mat4& matrix From f0b6521c76cf28618ca5a7e5ad7c39fca7250270 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 14 Nov 2024 08:09:10 +0300 Subject: [PATCH 24/38] refactor --- src/frontend/debug_panel.cpp | 3 +- src/graphics/render/ChunksRenderer.cpp | 101 ++++++++++++++++-- src/graphics/render/ChunksRenderer.hpp | 38 ++++++- src/graphics/render/ModelBatch.cpp | 12 +-- src/graphics/render/ModelBatch.hpp | 13 +-- src/graphics/render/TextsRenderer.cpp | 16 ++- src/graphics/render/TextsRenderer.hpp | 10 +- src/graphics/render/WorldRenderer.cpp | 135 +++++-------------------- src/graphics/render/WorldRenderer.hpp | 24 +---- src/voxels/Chunks.hpp | 4 +- 10 files changed, 186 insertions(+), 170 deletions(-) diff --git a/src/frontend/debug_panel.cpp b/src/frontend/debug_panel.cpp index b3d6aca0..a8d205b3 100644 --- a/src/frontend/debug_panel.cpp +++ b/src/frontend/debug_panel.cpp @@ -11,6 +11,7 @@ #include "graphics/ui/elements/InputBindBox.hpp" #include "graphics/render/WorldRenderer.hpp" #include "graphics/render/ParticlesRenderer.hpp" +#include "graphics/render/ChunksRenderer.hpp" #include "logic/scripting/scripting.hpp" #include "objects/Player.hpp" #include "objects/Entities.hpp" @@ -95,7 +96,7 @@ std::shared_ptr create_debug_panel( })); panel->add(create_label([=]() { return L"chunks: "+std::to_wstring(level->chunks->getChunksCount())+ - L" visible: "+std::to_wstring(level->chunks->visible); + L" visible: "+std::to_wstring(ChunksRenderer::visibleChunks); })); panel->add(create_label([=]() { return L"entities: "+std::to_wstring(level->entities->size())+L" next: "+ diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 656124da..565978f6 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -1,9 +1,17 @@ #include "ChunksRenderer.hpp" #include "BlocksRenderer.hpp" #include "debug/Logger.hpp" +#include "assets/Assets.hpp" #include "graphics/core/Mesh.hpp" +#include "graphics/core/Shader.hpp" +#include "graphics/core/Texture.hpp" +#include "graphics/core/Atlas.hpp" #include "voxels/Chunk.hpp" +#include "voxels/Chunks.hpp" #include "world/Level.hpp" +#include "window/Camera.hpp" +#include "maths/FrustumCulling.hpp" +#include "util/listutil.hpp" #include "settings.hpp" #include @@ -12,6 +20,8 @@ static debug::Logger logger("chunks-render"); +size_t ChunksRenderer::visibleChunks = 0; + class RendererWorker : public util::Worker, RendererResult> { Level* level; BlocksRenderer renderer; @@ -39,9 +49,14 @@ public: ChunksRenderer::ChunksRenderer( Level* level, + const Assets& assets, + const Frustum& frustum, const ContentGfxCache* cache, const EngineSettings* settings ) : level(level), + assets(assets), + frustum(frustum), + settings(settings), threadPool( "chunks-render-pool", [=](){return std::make_shared(level, cache, settings);}, @@ -103,14 +118,84 @@ std::shared_ptr ChunksRenderer::getOrRender(const std::shared_ptr& return found->second; } -std::shared_ptr ChunksRenderer::get(Chunk* chunk) { - auto found = meshes.find(glm::ivec2(chunk->x, chunk->z)); - if (found != meshes.end()) { - return found->second; - } - return nullptr; -} - void ChunksRenderer::update() { threadPool.update(); } + +bool ChunksRenderer::drawChunk( + size_t index, const Camera& camera, Shader& shader, bool culling +) { + auto chunk = level->chunks->getChunks()[index]; + if (chunk == nullptr || !chunk->flags.lighted) { + return false; + } + float distance = glm::distance( + camera.position, + glm::vec3( + (chunk->x + 0.5f) * CHUNK_W, + camera.position.y, + (chunk->z + 0.5f) * CHUNK_D + ) + ); + auto mesh = getOrRender(chunk, distance < CHUNK_W * 1.5f); + if (mesh == nullptr) { + return false; + } + if (culling) { + glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); + glm::vec3 max( + chunk->x * CHUNK_W + CHUNK_W, + chunk->top, + chunk->z * CHUNK_D + CHUNK_D + ); + + if (!frustum.isBoxVisible(min, max)) return false; + } + glm::vec3 coord(chunk->x * CHUNK_W + 0.5f, 0.5f, chunk->z * CHUNK_D + 0.5f); + glm::mat4 model = glm::translate(glm::mat4(1.0f), coord); + shader.uniformMatrix("u_model", model); + mesh->draw(); + return true; +} + +void ChunksRenderer::drawChunks( + const Camera& camera, Shader& shader +) { + const auto& chunks = *level->chunks; + const auto& atlas = assets.require("blocks"); + + atlas.getTexture()->bind(); + update(); + + // [warning] this whole method is not thread-safe for chunks + + int chunksWidth = chunks.getWidth(); + int chunksOffsetX = chunks.getOffsetX(); + int chunksOffsetY = chunks.getOffsetY(); + + if (indices.size() != chunks.getVolume()) { + indices.clear(); + for (int i = 0; i < chunks.getVolume(); i++) { + indices.push_back(ChunksSortEntry {i, 0}); + } + } + float px = camera.position.x / static_cast(CHUNK_W) - 0.5f; + float pz = camera.position.z / static_cast(CHUNK_D) - 0.5f; + for (auto& index : indices) { + float x = index.index % chunksWidth + chunksOffsetX - px; + float z = index.index / chunksWidth + chunksOffsetY - pz; + index.d = (x * x + z * z) * 1024; + } + util::insertion_sort(indices.begin(), indices.end()); + + bool culling = settings->graphics.frustumCulling.get(); + + visibleChunks = 0; + //if (GLEW_ARB_multi_draw_indirect && false) { + // TODO: implement Multi Draw Indirect chunks draw + //} else { + for (size_t i = 0; i < indices.size(); i++) { + visibleChunks += drawChunk(indices[i].index, camera, shader, culling); + } + //} +} diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index 62d07280..4cfa34d4 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -14,10 +14,24 @@ class Mesh; class Chunk; class Level; +class Camera; +class Shader; +class Chunks; +class Assets; +class Frustum; class BlocksRenderer; class ContentGfxCache; struct EngineSettings; +struct ChunksSortEntry { + int index; + int d; + + inline bool operator<(const ChunksSortEntry& o) const noexcept { + return d > o.d; + } +}; + struct RendererResult { glm::ivec2 key; bool cancelled; @@ -26,25 +40,41 @@ struct RendererResult { class ChunksRenderer { Level* level; + const Assets& assets; + const Frustum& frustum; + const EngineSettings* settings; std::unique_ptr renderer; std::unordered_map> meshes; std::unordered_map inwork; + std::vector indices; util::ThreadPool, RendererResult> threadPool; + + bool drawChunk( + size_t index, const Camera& camera, Shader& shader, bool culling + ); public: ChunksRenderer( - Level* level, + Level* level, + const Assets& assets, + const Frustum& frustum, const ContentGfxCache* cache, const EngineSettings* settings ); virtual ~ChunksRenderer(); - std::shared_ptr render(const std::shared_ptr& chunk, bool important); + std::shared_ptr render( + const std::shared_ptr& chunk, bool important + ); void unload(const Chunk* chunk); void clear(); - std::shared_ptr getOrRender(const std::shared_ptr& chunk, bool important); - std::shared_ptr get(Chunk* chunk); + std::shared_ptr getOrRender( + const std::shared_ptr& chunk, bool important + ); + void drawChunks(const Camera& camera, Shader& shader); void update(); + + static size_t visibleChunks; }; diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index 48133ef9..51c2fe9f 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -47,9 +47,9 @@ static glm::mat4 extract_rotation(glm::mat4 matrix) { ModelBatch::ModelBatch( size_t capacity, - Assets* assets, - Chunks* chunks, - const EngineSettings* settings + const Assets& assets, + const Chunks& chunks, + const EngineSettings& settings ) : batch(std::make_unique(capacity)), assets(assets), @@ -73,7 +73,7 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix, if (mesh.lighting) { glm::vec3 gpos = matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); gpos += lightsOffset; - lights = MainBatch::sampleLight(gpos, *chunks, backlight); + lights = MainBatch::sampleLight(gpos, chunks, backlight); } for (size_t i = 0; i < vcount / 3; i++) { batch->prepare(3); @@ -107,7 +107,7 @@ void ModelBatch::render() { return a.mesh->texture < b.mesh->texture; } ); - bool backlight = settings->graphics.backlight.get(); + bool backlight = settings.graphics.backlight.get(); for (auto& entry : entries) { draw( *entry.mesh, @@ -136,6 +136,6 @@ void ModelBatch::setTexture(const std::string& name, return setTexture(found->second, varTextures); } } - auto region = util::get_texture_region(*assets, name, "blocks:notfound"); + auto region = util::get_texture_region(assets, name, "blocks:notfound"); batch->setTexture(region.texture, region.region); } diff --git a/src/graphics/render/ModelBatch.hpp b/src/graphics/render/ModelBatch.hpp index 5781baa1..4faf0ea8 100644 --- a/src/graphics/render/ModelBatch.hpp +++ b/src/graphics/render/ModelBatch.hpp @@ -23,10 +23,10 @@ namespace model { using texture_names_map = std::unordered_map; class ModelBatch { - Assets* assets; - Chunks* chunks; + const Assets& assets; + const Chunks& chunks; - const EngineSettings* settings; + const EngineSettings& settings; glm::vec3 lightsOffset {}; static inline glm::vec3 SUN_VECTOR {0.411934f, 0.863868f, -0.279161f}; @@ -39,6 +39,7 @@ class ModelBatch { glm::vec3 tint, const texture_names_map* varTextures, bool backlight); + void setTexture(const std::string& name, const texture_names_map* varTextures); @@ -53,9 +54,9 @@ class ModelBatch { public: ModelBatch( size_t capacity, - Assets* assets, - Chunks* chunks, - const EngineSettings* settings + const Assets& assets, + const Chunks& chunks, + const EngineSettings& settings ); ~ModelBatch(); diff --git a/src/graphics/render/TextsRenderer.cpp b/src/graphics/render/TextsRenderer.cpp index 7fd6c214..349c4a39 100644 --- a/src/graphics/render/TextsRenderer.cpp +++ b/src/graphics/render/TextsRenderer.cpp @@ -10,14 +10,15 @@ #include "graphics/core/Shader.hpp" #include "presets/NotePreset.hpp" -TextsRenderer::TextsRenderer(const Frustum* frustum) : frustum(frustum) { +TextsRenderer::TextsRenderer( + Batch3D& batch, const Assets& assets, const Frustum& frustum +) + : batch(batch), assets(assets), frustum(frustum) { } void TextsRenderer::renderText( - Batch3D& batch, const TextNote& note, const DrawContext& context, - const Assets& assets, const Camera& camera, const EngineSettings& settings, bool hudVisible @@ -54,8 +55,8 @@ void TextsRenderer::renderText( } if (preset.displayMode != NoteDisplayMode::PROJECTED) { - if (!frustum->isBoxVisible(pos - xvec * (width * 0.5f), - pos + xvec * (width * 0.5f))) { + if (!frustum.isBoxVisible(pos - xvec * (width * 0.5f), + pos + xvec * (width * 0.5f))) { return; } } @@ -71,9 +72,7 @@ void TextsRenderer::renderText( } void TextsRenderer::renderTexts( - Batch3D& batch, const DrawContext& context, - const Assets& assets, const Camera& camera, const EngineSettings& settings, bool hudVisible, @@ -96,9 +95,8 @@ void TextsRenderer::renderTexts( shader.uniformMatrix("u_projview", camera.getProjView()); shader.uniformMatrix("u_apply", glm::mat4(1.0f)); batch.begin(); - for (const auto& note : notes) { - renderText(batch, note, context, assets, camera, settings, hudVisible); + renderText(note, context, camera, settings, hudVisible); } batch.flush(); } diff --git a/src/graphics/render/TextsRenderer.hpp b/src/graphics/render/TextsRenderer.hpp index df0de386..57dfa24b 100644 --- a/src/graphics/render/TextsRenderer.hpp +++ b/src/graphics/render/TextsRenderer.hpp @@ -9,24 +9,22 @@ class TextNote; struct EngineSettings; class TextsRenderer { - const Frustum* frustum; + Batch3D& batch; + const Assets& assets; + const Frustum& frustum; void renderText( - Batch3D& batch, const TextNote& note, const DrawContext& context, - const Assets& assets, const Camera& camera, const EngineSettings& settings, bool hudVisible ); public: - TextsRenderer(const Frustum* frustum); + TextsRenderer(Batch3D& batch, const Assets& assets, const Frustum& frustum); void renderTexts( - Batch3D& batch, const DrawContext& context, - const Assets& assets, const Camera& camera, const EngineSettings& settings, bool hudVisible, diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index ed3985d7..31abb248 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -22,7 +22,6 @@ #include "maths/voxmaths.hpp" #include "objects/Entities.hpp" #include "objects/Player.hpp" -#include "util/listutil.hpp" #include "settings.hpp" #include "voxels/Block.hpp" #include "voxels/Chunk.hpp" @@ -51,6 +50,9 @@ #include "Emitter.hpp" #include "TextNote.hpp" +inline constexpr size_t BATCH3D_CAPACITY = 4096; +inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000; + bool WorldRenderer::showChunkBorders = false; bool WorldRenderer::showEntitiesDebug = false; @@ -60,30 +62,28 @@ WorldRenderer::WorldRenderer( : engine(engine), level(frontend->getLevel()), player(player), + assets(*engine->getAssets()), frustumCulling(std::make_unique()), lineBatch(std::make_unique()), + batch3d(std::make_unique(BATCH3D_CAPACITY)), modelBatch(std::make_unique( - 20'000, - engine->getAssets(), - level->chunks.get(), - &engine->getSettings() + MODEL_BATCH_CAPACITY, assets, *level->chunks, engine->getSettings() )), particles(std::make_unique( - *engine->getAssets(), - *frontend->getLevel(), - &engine->getSettings().graphics + assets, *level, &engine->getSettings().graphics )), - texts(std::make_unique(frustumCulling.get())), - guides(std::make_unique()) { - renderer = std::make_unique( - level, frontend->getContentGfxCache(), &engine->getSettings() - ); - batch3d = std::make_unique(4096); - + texts(std::make_unique( + *batch3d, assets, *frustumCulling + )), + guides(std::make_unique()), + chunks(std::make_unique( + level, assets, *frustumCulling, frontend->getContentGfxCache(), &engine->getSettings() + )) +{ auto& settings = engine->getSettings(); level->events->listen( EVT_CHUNK_HIDDEN, - [this](lvl_event_type, Chunk* chunk) { renderer->unload(chunk); } + [this](lvl_event_type, Chunk* chunk) { chunks->unload(chunk); } ); auto assets = engine->getAssets(); skybox = std::make_unique( @@ -94,87 +94,6 @@ WorldRenderer::WorldRenderer( WorldRenderer::~WorldRenderer() = default; -bool WorldRenderer::drawChunk( - size_t index, const Camera& camera, Shader& shader, bool culling -) { - auto chunk = level->chunks->getChunks()[index]; - if (chunk == nullptr || !chunk->flags.lighted) { - return false; - } - float distance = glm::distance( - camera.position, - glm::vec3( - (chunk->x + 0.5f) * CHUNK_W, - camera.position.y, - (chunk->z + 0.5f) * CHUNK_D - ) - ); - auto mesh = renderer->getOrRender(chunk, distance < CHUNK_W * 1.5f); - if (mesh == nullptr) { - return false; - } - if (culling) { - glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); - glm::vec3 max( - chunk->x * CHUNK_W + CHUNK_W, - chunk->top, - chunk->z * CHUNK_D + CHUNK_D - ); - - if (!frustumCulling->isBoxVisible(min, max)) return false; - } - glm::vec3 coord(chunk->x * CHUNK_W + 0.5f, 0.5f, chunk->z * CHUNK_D + 0.5f); - glm::mat4 model = glm::translate(glm::mat4(1.0f), coord); - shader.uniformMatrix("u_model", model); - mesh->draw(); - return true; -} - -void WorldRenderer::drawChunks( - Chunks* chunks, const Camera& camera, Shader& shader -) { - auto assets = engine->getAssets(); - auto atlas = assets->get("blocks"); - - atlas->getTexture()->bind(); - renderer->update(); - - // [warning] this whole method is not thread-safe for chunks - - int chunksWidth = chunks->getWidth(); - int chunksOffsetX = chunks->getOffsetX(); - int chunksOffsetY = chunks->getOffsetY(); - - if (indices.size() != chunks->getVolume()) { - indices.clear(); - for (int i = 0; i < chunks->getVolume(); i++) { - indices.push_back(ChunksSortEntry {i, 0}); - } - } - float px = camera.position.x / static_cast(CHUNK_W) - 0.5f; - float pz = camera.position.z / static_cast(CHUNK_D) - 0.5f; - for (auto& index : indices) { - float x = index.index % chunksWidth + chunksOffsetX - px; - float z = index.index / chunksWidth + chunksOffsetY - pz; - index.d = (x * x + z * z) * 1024; - } - util::insertion_sort(indices.begin(), indices.end()); - - bool culling = engine->getSettings().graphics.frustumCulling.get(); - if (culling) { - frustumCulling->update(camera.getProjView()); - } - - chunks->visible = 0; - if (GLEW_ARB_multi_draw_indirect && false) { - // TODO: implement Multi Draw Indirect chunks draw - } else { - for (size_t i = 0; i < indices.size(); i++) { - chunks->visible += drawChunk(indices[i].index, camera, shader, culling); - } - } -} - void WorldRenderer::setupWorldShader( Shader& shader, const Camera& camera, @@ -219,11 +138,7 @@ void WorldRenderer::renderLevel( bool pause, bool hudVisible ) { - const auto& assets = *engine->getAssets(); - - texts->renderTexts( - *batch3d, ctx, assets, camera, settings, hudVisible, false - ); + texts->renderTexts(ctx, camera, settings, hudVisible, false); bool culling = engine->getSettings().graphics.frustumCulling.get(); float fogFactor = @@ -233,6 +148,10 @@ void WorldRenderer::renderLevel( setupWorldShader(entityShader, camera, settings, fogFactor); skybox->bind(); + if (culling) { + frustumCulling->update(camera.getProjView()); + } + level->entities->render( assets, *modelBatch, @@ -246,7 +165,7 @@ void WorldRenderer::renderLevel( auto& shader = assets.require("main"); setupWorldShader(shader, camera, settings, fogFactor); - drawChunks(level->chunks.get(), camera, shader); + chunks->drawChunks(camera, shader); if (!pause) { scripting::on_frontend_render(); @@ -302,7 +221,7 @@ void WorldRenderer::renderLines( } void WorldRenderer::renderHands( - const Camera& camera, const Assets& assets, float delta + const Camera& camera, float delta ) { auto& entityShader = assets.require("entity"); auto indices = level->content->getIndices(); @@ -408,11 +327,11 @@ void WorldRenderer::draw( } renderLines(camera, linesShader, ctx); if (player->currentCamera == player->fpCamera) { - renderHands(camera, assets, delta * !pause); + renderHands(camera, delta * !pause); } } } - renderBlockOverlay(wctx, assets); + renderBlockOverlay(wctx); } // Rendering fullscreen quad with @@ -423,7 +342,7 @@ void WorldRenderer::draw( postProcessing->render(pctx, screenShader); } -void WorldRenderer::renderBlockOverlay(const DrawContext& wctx, const Assets& assets) { +void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) { int x = std::floor(player->currentCamera->position.x); int y = std::floor(player->currentCamera->position.y); int z = std::floor(player->currentCamera->position.z); @@ -469,5 +388,5 @@ void WorldRenderer::renderBlockOverlay(const DrawContext& wctx, const Assets& as } void WorldRenderer::clear() { - renderer->clear(); + chunks->clear(); } diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 6dd61fca..974c626c 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -22,7 +22,6 @@ class TextsRenderer; class Shader; class Frustum; class Engine; -class Chunks; class LevelFrontend; class Skybox; class PostProcessing; @@ -36,39 +35,26 @@ namespace model { struct Model; } -struct ChunksSortEntry { - int index; - int d; - - inline bool operator<(const ChunksSortEntry& o) const noexcept { - return d > o.d; - } -}; - class WorldRenderer { Engine* engine; Level* level; Player* player; + const Assets& assets; std::unique_ptr frustumCulling; std::unique_ptr lineBatch; - std::unique_ptr renderer; + std::unique_ptr batch3d; + std::unique_ptr chunks; std::unique_ptr texts; std::unique_ptr guides; std::unique_ptr skybox; - std::unique_ptr batch3d; std::unique_ptr modelBatch; - - std::vector indices; float timer = 0.0f; - bool drawChunk(size_t index, const Camera& camera, Shader& shader, bool culling); - void drawChunks(Chunks* chunks, const Camera& camera, Shader& shader); - /// @brief Render block selection lines void renderBlockSelection(); - void renderHands(const Camera& camera, const Assets& assets, float delta); + void renderHands(const Camera& camera, float delta); /// @brief Render lines (selection and debug) /// @param camera active camera @@ -77,7 +63,7 @@ class WorldRenderer { const Camera& camera, Shader& linesShader, const DrawContext& pctx ); - void renderBlockOverlay(const DrawContext& context, const Assets& assets); + void renderBlockOverlay(const DrawContext& context); void setupWorldShader( Shader& shader, diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index d2440210..38a5be8c 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -40,10 +40,8 @@ class Chunks { ); util::AreaMap2D, int32_t> areaMap; -public: - size_t visible = 0; WorldFiles* worldFiles; - +public: Chunks( int32_t w, int32_t d, From c4170c07c56dde0337070a7df205cc94ffae0bd6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 14 Nov 2024 09:30:41 +0300 Subject: [PATCH 25/38] refactor --- src/frontend/ContentGfxCache.cpp | 16 +++--- src/frontend/ContentGfxCache.hpp | 4 +- src/frontend/LevelFrontend.cpp | 35 ++++++++------ src/frontend/LevelFrontend.hpp | 13 ++--- src/frontend/debug_panel.cpp | 63 ++++++++++++------------ src/frontend/hud.cpp | 54 ++++++++++----------- src/frontend/hud.hpp | 4 +- src/frontend/screens/LevelScreen.cpp | 17 ++++--- src/graphics/render/BlocksPreview.cpp | 67 +++++++++++++------------- src/graphics/render/BlocksPreview.hpp | 16 +++--- src/graphics/render/BlocksRenderer.cpp | 26 +++++----- src/graphics/render/BlocksRenderer.hpp | 13 +++-- src/graphics/render/ChunksRenderer.cpp | 40 +++++++-------- src/graphics/render/ChunksRenderer.hpp | 12 ++--- src/graphics/render/Skybox.cpp | 39 +++++++++------ src/graphics/render/Skybox.hpp | 4 +- src/graphics/render/WorldRenderer.cpp | 47 +++++++++--------- src/graphics/render/WorldRenderer.hpp | 9 +--- src/logic/scripting/scripting_hud.cpp | 2 +- src/world/Level.cpp | 4 ++ src/world/Level.hpp | 2 + 21 files changed, 255 insertions(+), 232 deletions(-) diff --git a/src/frontend/ContentGfxCache.cpp b/src/frontend/ContentGfxCache.cpp index 7d3944b7..c6ba4e1c 100644 --- a/src/frontend/ContentGfxCache.cpp +++ b/src/frontend/ContentGfxCache.cpp @@ -11,25 +11,25 @@ #include "maths/UVRegion.hpp" #include "voxels/Block.hpp" -ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) +ContentGfxCache::ContentGfxCache(const Content* content, const Assets& assets) : content(content) { auto indices = content->getIndices(); sideregions = std::make_unique(indices->blocks.count() * 6); - auto atlas = assets->get("blocks"); + const auto& atlas = assets.require("blocks"); const auto& blocks = indices->blocks.getIterable(); for (blockid_t i = 0; i < blocks.size(); i++) { auto def = blocks[i]; for (uint side = 0; side < 6; side++) { const std::string& tex = def->textureFaces[side]; - if (atlas->has(tex)) { - sideregions[i * 6 + side] = atlas->get(tex); - } else if (atlas->has(TEXTURE_NOTFOUND)) { - sideregions[i * 6 + side] = atlas->get(TEXTURE_NOTFOUND); + if (atlas.has(tex)) { + sideregions[i * 6 + side] = atlas.get(tex); + } else if (atlas.has(TEXTURE_NOTFOUND)) { + sideregions[i * 6 + side] = atlas.get(TEXTURE_NOTFOUND); } } if (def->model == BlockModel::custom) { - auto model = assets->require(def->modelName); + auto model = assets.require(def->modelName); // temporary dirty fix tbh if (def->modelName.find(':') == std::string::npos) { for (auto& mesh : model.meshes) { @@ -37,7 +37,7 @@ ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) if (pos == std::string::npos) { continue; } - if (auto region = atlas->getIf(mesh.texture.substr(pos+1))) { + if (auto region = atlas.getIf(mesh.texture.substr(pos+1))) { for (auto& vertex : mesh.vertices) { vertex.uv = region->apply(vertex.uv); } diff --git a/src/frontend/ContentGfxCache.hpp b/src/frontend/ContentGfxCache.hpp index 3d3161d3..96d46ea5 100644 --- a/src/frontend/ContentGfxCache.hpp +++ b/src/frontend/ContentGfxCache.hpp @@ -22,7 +22,7 @@ class ContentGfxCache { std::unique_ptr sideregions; std::unordered_map models; public: - ContentGfxCache(const Content* content, Assets* assets); + ContentGfxCache(const Content* content, const Assets& assets); ~ContentGfxCache(); inline const UVRegion& getRegion(blockid_t id, int side) const { @@ -30,6 +30,6 @@ public: } const model::Model& getModel(blockid_t id) const; - + const Content* getContent() const; }; diff --git a/src/frontend/LevelFrontend.cpp b/src/frontend/LevelFrontend.cpp index 977a0350..79784375 100644 --- a/src/frontend/LevelFrontend.cpp +++ b/src/frontend/LevelFrontend.cpp @@ -14,25 +14,28 @@ #include "world/Level.hpp" LevelFrontend::LevelFrontend( - Player* currentPlayer, LevelController* controller, Assets* assets -) : level(controller->getLevel()), + Player* currentPlayer, LevelController* controller, Assets& assets +) : level(*controller->getLevel()), controller(controller), assets(assets), - contentCache(std::make_unique(level->content, assets)) + contentCache(std::make_unique(level.content, assets)) { - assets->store( - BlocksPreview::build(contentCache.get(), assets, level->content), + assets.store( + BlocksPreview::build( + *contentCache, assets, *level.content->getIndices() + ), "block-previews" ); controller->getBlocksController()->listenBlockInteraction( - [=](auto player, const auto& pos, const auto& def, BlockInteraction type) { - auto material = level->content->findBlockMaterial(def.material); + [currentPlayer, controller, &assets](auto player, const auto& pos, const auto& def, BlockInteraction type) { + const auto& level = *controller->getLevel(); + auto material = level.content->findBlockMaterial(def.material); if (material == nullptr) { return; } if (type == BlockInteraction::step) { - auto sound = assets->get(material->stepsSound); + auto sound = assets.get(material->stepsSound); glm::vec3 pos {}; auto soundsCamera = currentPlayer->currentCamera.get(); if (soundsCamera == currentPlayer->spCamera.get() || @@ -58,10 +61,10 @@ LevelFrontend::LevelFrontend( audio::Sound* sound = nullptr; switch (type) { case BlockInteraction::placing: - sound = assets->get(material->placeSound); + sound = assets.get(material->placeSound); break; case BlockInteraction::destruction: - sound = assets->get(material->breakSound); + sound = assets.get(material->breakSound); break; default: break; @@ -83,16 +86,20 @@ LevelFrontend::LevelFrontend( LevelFrontend::~LevelFrontend() = default; -Level* LevelFrontend::getLevel() const { +Level& LevelFrontend::getLevel() { return level; } -Assets* LevelFrontend::getAssets() const { +const Level& LevelFrontend::getLevel() const { + return level; +} + +const Assets& LevelFrontend::getAssets() const { return assets; } -ContentGfxCache* LevelFrontend::getContentGfxCache() const { - return contentCache.get(); +const ContentGfxCache& LevelFrontend::getContentGfxCache() const { + return *contentCache; } LevelController* LevelFrontend::getController() const { diff --git a/src/frontend/LevelFrontend.hpp b/src/frontend/LevelFrontend.hpp index ed149598..163fc678 100644 --- a/src/frontend/LevelFrontend.hpp +++ b/src/frontend/LevelFrontend.hpp @@ -9,16 +9,17 @@ class ContentGfxCache; class LevelController; class LevelFrontend { - Level* level; + Level& level; LevelController* controller; - Assets* assets; + const Assets& assets; std::unique_ptr contentCache; public: - LevelFrontend(Player* currentPlayer, LevelController* controller, Assets* assets); + LevelFrontend(Player* currentPlayer, LevelController* controller, Assets& assets); ~LevelFrontend(); - Level* getLevel() const; - Assets* getAssets() const; - ContentGfxCache* getContentGfxCache() const; + Level& getLevel(); + const Level& getLevel() const; + const Assets& getAssets() const; + const ContentGfxCache& getContentGfxCache() const; LevelController* getController() const; }; diff --git a/src/frontend/debug_panel.cpp b/src/frontend/debug_panel.cpp index a8d205b3..9043f5b9 100644 --- a/src/frontend/debug_panel.cpp +++ b/src/frontend/debug_panel.cpp @@ -42,8 +42,8 @@ static std::shared_ptr