From 787011d16454ca686c1bdc30ad3d8e4d0f0031f8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 9 Feb 2025 14:48:53 +0300 Subject: [PATCH] optimize PrecipitationRenderer --- src/graphics/render/PrecipitationRenderer.cpp | 52 ++++++++++++------ src/util/CentredMatrix.hpp | 55 +++++++++++++++++++ 2 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 src/util/CentredMatrix.hpp diff --git a/src/graphics/render/PrecipitationRenderer.cpp b/src/graphics/render/PrecipitationRenderer.cpp index c54dd872..95297f83 100644 --- a/src/graphics/render/PrecipitationRenderer.cpp +++ b/src/graphics/render/PrecipitationRenderer.cpp @@ -7,7 +7,10 @@ #include "graphics/core/Texture.hpp" #include "lighting/Lightmap.hpp" #include "maths/util.hpp" +#include "maths/voxmaths.hpp" +#include "util/CentredMatrix.hpp" #include "settings.hpp" +#include "voxels/Chunk.hpp" #include "voxels/Chunks.hpp" #include "window/Camera.hpp" #include "world/Level.hpp" @@ -29,12 +32,20 @@ PrecipitationRenderer::~PrecipitationRenderer() = default; int PrecipitationRenderer::getHeightAt(int x, int z) { int y = CHUNK_H - 1; + int cx = floordiv(x); + int cz = floordiv(z); + auto chunk = chunks.getChunk(cx, cz); + if (chunk == nullptr) { + return y; + } + y = chunk->top; + x -= cx * CHUNK_W; + z -= cz * CHUNK_D; while (y > 0) { - if (auto voxel = chunks.get({x, y, z})) { - if (voxel->id == 0) { - y--; - continue; - } + const auto& vox = chunk->voxels[vox_index(x, y, z)]; + if (vox.id == 0) { + y--; + continue; } break; } @@ -68,12 +79,12 @@ void PrecipitationRenderer::render(const Camera& camera, float delta) { const auto& front = camera.front; glm::ivec2 size {1, 16}; - float horizontal = 0.5f; + float horizontal = 0.5f * 5; glm::vec4 light = light_at(chunks, x, y, z); - int radius = 6; - int depth = 12; + const int radius = 6; + const int depth = 12; float scale = 0.4f; int quads = 0; float k = 21.41149; @@ -88,16 +99,26 @@ void PrecipitationRenderer::render(const Camera& camera, float delta) { {{0, 0, 1}, {1, 0, 0}}, }; + util::CentredMatrix heights; + heights.setCenter(x, z); + for (int z = heights.beginY(); z < heights.endY(); z++) { + for (int x = heights.beginX(); x < heights.endX(); x++) { + heights.at(x, z) = getHeightAt(x, z); + } + } + for (const auto& face : faces) { for (int lx = -radius; lx <= radius; lx++) { for (int lz = depth; lz > 0; lz--) { + // Position calculations glm::vec3 pos = face.right * static_cast(lx) + face.front * static_cast(lz); pos += glm::vec3(x, 0, z); - pos.y = glm::max(y - size.y / 2, getHeightAt(pos.x, pos.z)) + + pos.y = glm::max(y - size.y / 2, heights.at(pos.x, pos.z)) + size.y / 2 + 1; pos += glm::vec3(0.5f, 0.0f, 0.5f); + // UV coords calculations float m = glm::sign(face.right.x + face.right.z); int ux = pos.x; int uz = pos.z; @@ -106,9 +127,13 @@ void PrecipitationRenderer::render(const Camera& camera, float delta) { std::swap(ux, uz); } - glm::vec4 light = light_at(chunks, pos.x, y, pos.z); random.setSeed(uz); float hspeed = (random.randFloat() * 2.0f - 1.0f) * horizontal; + float u1 = ux * scale + timer * hspeed * -m; + float v1 = timer + pos.y * scale + uz * k; + + // Draw + glm::vec4 light = light_at(chunks, pos.x, y, pos.z); batch->quad( pos, face.right, @@ -116,12 +141,7 @@ void PrecipitationRenderer::render(const Camera& camera, float delta) { size, light, glm::vec3(1.0f), - UVRegion( - ux * scale + timer * hspeed * -m, - timer + pos.y * scale + uz * k, - (ux + m) * scale + timer * hspeed * -m, - timer + (size.y + pos.y) * scale + uz * k - ) + UVRegion(u1, v1, u1 + m * scale, v1 + size.y * scale) ); } } diff --git a/src/util/CentredMatrix.hpp b/src/util/CentredMatrix.hpp new file mode 100644 index 00000000..805a1aa1 --- /dev/null +++ b/src/util/CentredMatrix.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +namespace util { + template + class CentredMatrix { + public: + static constexpr CoordT radius = diameter / 2; + + CentredMatrix() {} + + void setCenter(CoordT x, CoordT y) { + centerX = x; + centerY = y; + } + + T& at(CoordT x, CoordT y) { + x -= centerX - (diameter - radius); + y -= centerY - (diameter - radius); + if (x < 0 || y < 0 || x >= diameter || y >= diameter) { + throw std::invalid_argument("position is out if matrix"); + } + return arr.at(y * diameter + x); + } + + auto begin() { + return arr.begin(); + } + + auto end() { + return arr.end(); + } + + CoordT beginX() const { + return centerX - (diameter - radius); + } + + CoordT beginY() const { + return centerY - (diameter - radius); + } + + CoordT endX() const { + return centerX + radius; + } + + CoordT endY() const { + return centerY + radius; + } + private: + std::array arr; + CoordT centerX = 0, centerY = 0; + }; +}