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;