diff --git a/res/content/base/textures/blocks/dirt.png b/res/content/base/textures/blocks/dirt.png index 9fc51ad88..8df51c45e 100644 Binary files a/res/content/base/textures/blocks/dirt.png and b/res/content/base/textures/blocks/dirt.png differ diff --git a/res/content/base/textures/blocks/grass.png b/res/content/base/textures/blocks/grass.png index 98dbda01f..0b93571b2 100644 Binary files a/res/content/base/textures/blocks/grass.png and b/res/content/base/textures/blocks/grass.png differ diff --git a/res/content/base/textures/blocks/grass_side.png b/res/content/base/textures/blocks/grass_side.png index 553bd8b4f..c6b2a8c4c 100644 Binary files a/res/content/base/textures/blocks/grass_side.png and b/res/content/base/textures/blocks/grass_side.png differ diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index 115cb9274..3a12c406e 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -30,7 +30,7 @@ void main() { texColor.rgb = u_debugNormals ? (a_normal * 0.5 + 0.5) : vec3(1.0); f_color = texColor; - f_color.rgb *= min(vec3(1.0), a_torchLight.rgb + a_skyLight); + f_color.rgb *= max(a_torchLight.rgb, a_skyLight); #ifndef ADVANCED_RENDER vec3 fogColor = texture(u_skybox, a_dir).rgb; diff --git a/src/audio/AL/ALAudio.cpp b/src/audio/AL/ALAudio.cpp index 048a8630a..41ce83c08 100644 --- a/src/audio/AL/ALAudio.cpp +++ b/src/audio/AL/ALAudio.cpp @@ -485,6 +485,8 @@ ALAudio::ALAudio(ALCdevice* device, ALCcontext* context) for (auto& name : inputDevices) { logger.info() << " " << name; } + + alDopplerFactor(1.0 / 3.0); } ALAudio::~ALAudio() { diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index c3ca56b4f..8466008da 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -28,10 +28,6 @@ BlocksRenderer::BlocksRenderer( cache(cache), settings(settings) { - voxelsBuffer = std::make_unique( - CHUNK_W + voxelBufferPadding*2, - CHUNK_H, - CHUNK_D + voxelBufferPadding*2); blockDefsCache = content.getIndices()->blocks.getDefs(); } @@ -313,6 +309,7 @@ void BlocksRenderer::blockCustomModel( overflow = true; return; } + bool shading = mesh.shading && !block.shadeless; for (int triangle = 0; triangle < mesh.vertices.size() / 3; triangle++) { auto r = mesh.vertices[triangle * 3 + (triangle % 2) * 2].coord - mesh.vertices[triangle * 3 + 1].coord; @@ -329,7 +326,9 @@ void BlocksRenderer::blockCustomModel( 0.5f; vp = vp.x * X + vp.y * Y + vp.z * Z; - if (!isOpen(glm::floor(coord + vp + 0.5f + n * 1e-3f), block, variant) && is_aligned(n)) { + if (!block.rt.extended + && !isOpen(glm::floor(coord + vp + 0.5f + n * 1e-3f), block, variant) + && is_aligned(n)) { continue; } @@ -342,22 +341,29 @@ void BlocksRenderer::blockCustomModel( const auto& vcoord = vertex.coord - 0.5f; glm::vec4 aoColor {1.0f, 1.0f, 1.0f, 1.0f}; - if (mesh.shading && ao) { + if (shading && ao) { const float eps = 0.05f; auto p = coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z + r * 0.5f + t * 0.5f + n * eps; auto p1 = p + n * eps; auto p2 = p + n * 0.5f; aoColor = pickSoftLight(p1.x, p1.y, p1.z, glm::ivec3(r), glm::ivec3(t)); - aoColor = glm::max(aoColor, pickSoftLight(p2.x, p2.y, p2.z, glm::ivec3(r), glm::ivec3(t))); + if (!block.lightPassing) { + aoColor = glm::max( + aoColor, + pickSoftLight( + p2.x, p2.y, p2.z, glm::ivec3(r), glm::ivec3(t) + ) + ); + } } this->vertex( coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z, vertex.uv.x, vertex.uv.y, - mesh.shading ? (glm::vec4(d, d, d, d) * aoColor) : glm::vec4(1, 1, 1, d), + shading ? (glm::vec4(d, d, d, d) * aoColor) : glm::vec4(1, 1, 1, d), n, - mesh.shading ? 0.0f : 1.0 + shading ? 0.0f : 1.0 ); indexBuffer[indexCount++] = vertexOffset++; } @@ -691,13 +697,9 @@ SortingMeshData BlocksRenderer::renderTranslucent( return sortingMesh; } -void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) { +void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) { this->chunk = chunk; - voxelsBuffer->setPosition( - chunk->x * CHUNK_W - voxelBufferPadding, 0, - chunk->z * CHUNK_D - voxelBufferPadding); - chunks->getVoxels(*voxelsBuffer, settings.graphics.backlight.get()); - + this->voxelsBuffer = &volume; if (voxelsBuffer->pickBlockId( chunk->x * CHUNK_W, 0, chunk->z * CHUNK_D ) == BLOCK_VOID) { @@ -738,7 +740,7 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) { indexCount = 0; denseIndexCount = 0; - denseRender = false; //settings.graphics.denseRender.get(); + denseRender = false; densePass = false; render(voxels, beginEnds); @@ -767,15 +769,18 @@ ChunkMeshData BlocksRenderer::createMesh() { util::Buffer(denseIndexBuffer.get(), denseIndexCount), }, util::Buffer( - ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute) + ChunkVertex::ATTRIBUTES, + sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute) ) ), std::move(sortingMesh) }; } -ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) { - build(chunk, chunks); +ChunkMesh BlocksRenderer::render( + const Chunk* chunk, const VoxelsVolume& volume +) { + build(chunk, volume); return ChunkMesh{std::make_unique>( vertexBuffer.get(), vertexCount, @@ -786,11 +791,6 @@ ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) { ), std::move(sortingMesh)}; } -VoxelsVolume* BlocksRenderer::getVoxelsBuffer() const { - return voxelsBuffer.get(); -} - size_t BlocksRenderer::getMemoryConsumption() const { - size_t volume = voxelsBuffer->getW() * voxelsBuffer->getH() * voxelsBuffer->getD(); - return capacity * (sizeof(ChunkVertex) + sizeof(uint32_t) * 2) + volume * (sizeof(voxel) + sizeof(light_t)); + return capacity * (sizeof(ChunkVertex) + sizeof(uint32_t) * 2); } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index a954fad6e..2006baab3 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -32,13 +32,12 @@ class BlocksRenderer { size_t indexCount; size_t denseIndexCount; size_t capacity; - int voxelBufferPadding = 2; bool overflow = false; bool cancelled = false; bool densePass = false; bool denseRender = false; const Chunk* chunk = nullptr; - std::unique_ptr voxelsBuffer; + const VoxelsVolume* voxelsBuffer = nullptr; const Block* const* blockDefsCache; const ContentGfxCache& cache; @@ -152,9 +151,13 @@ class BlocksRenderer { glm::vec4 pickLight(int x, int y, int z) const; glm::vec4 pickLight(const glm::ivec3& coord) const; - glm::vec4 pickSoftLight(const glm::ivec3& coord, const glm::ivec3& right, const glm::ivec3& up) const; - glm::vec4 pickSoftLight(float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up) const; - + glm::vec4 pickSoftLight( + const glm::ivec3& coord, const glm::ivec3& right, const glm::ivec3& up + ) const; + glm::vec4 pickSoftLight( + float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up + ) const; + void render(const voxel* voxels, const int beginEnds[256][2]); SortingMeshData renderTranslucent(const voxel* voxels, int beginEnds[256][2]); public: @@ -166,10 +169,11 @@ public: ); virtual ~BlocksRenderer(); - void build(const Chunk* chunk, const Chunks* chunks); - ChunkMesh render(const Chunk* chunk, const Chunks* chunks); + void build(const Chunk* chunk, const VoxelsVolume& volume); + ChunkMesh render( + const Chunk* chunk, const VoxelsVolume& volume + ); ChunkMeshData createMesh(); - VoxelsVolume* getVoxelsBuffer() const; size_t getMemoryConsumption() const; diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index b0dfaec3e..8289967c1 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -12,24 +12,22 @@ #include "window/Camera.hpp" #include "maths/FrustumCulling.hpp" #include "util/listutil.hpp" +#include "util/ObjectsPool.hpp" #include "settings.hpp" static debug::Logger logger("chunks-render"); size_t ChunksRenderer::visibleChunks = 0; -class RendererWorker : public util::Worker, RendererResult> { - const Chunks& chunks; +class RendererWorker : public util::Worker { BlocksRenderer renderer; public: RendererWorker( const Level& level, - const Chunks& chunks, const ContentGfxCache& cache, const EngineSettings& settings ) - : chunks(chunks), - renderer( + : renderer( settings.graphics.denseRender.get() ? settings.graphics.chunkMaxVerticesDense.get() : settings.graphics.chunkMaxVertices.get(), @@ -39,8 +37,10 @@ public: ) { } - RendererResult operator()(const std::shared_ptr& chunk) override { - renderer.build(chunk.get(), &chunks); + RendererResult operator()(const RendererJob& job) override { + auto chunk = job.chunk; + auto volume = job.volume; + renderer.build(chunk.get(), *volume); if (renderer.isCancelled()) { return RendererResult { glm::ivec2(chunk->x, chunk->z), true, ChunkMeshData {}}; @@ -51,6 +51,9 @@ public: } }; +static util::ObjectsPool voxelsVolumesPool {}; +static inline const int VOXELS_BUFFER_PADDING = 2; + ChunksRenderer::ChunksRenderer( const Level* level, const Chunks& chunks, @@ -67,7 +70,7 @@ ChunksRenderer::ChunksRenderer( "chunks-render-pool", [&]() { return std::make_shared( - *level, chunks, cache, settings + *level, cache, settings ); }, [&](RendererResult& result) { @@ -87,30 +90,61 @@ ChunksRenderer::ChunksRenderer( level->content, cache, settings ); logger.info() << "created " << threadPool.getWorkersCount() << " workers"; - logger.info() << "memory consumption is " - << renderer->getMemoryConsumption() * threadPool.getWorkersCount() - << " B"; + logger.info() << "memory consumption is " + << renderer->getMemoryConsumption() * + threadPool.getWorkersCount() + + voxelsVolumesPool.countTotal() * + (sizeof(VoxelsVolume) + + (CHUNK_W + VOXELS_BUFFER_PADDING * 2) * CHUNK_H * + (CHUNK_D + VOXELS_BUFFER_PADDING * 2) * + (sizeof(voxel) + sizeof(light_t))) + << " B"; } ChunksRenderer::~ChunksRenderer() = default; +std::shared_ptr ChunksRenderer::prepareVoxelsVolume( + const Chunk& chunk +) { + auto voxelsBuffer = voxelsVolumesPool.create( + CHUNK_W + VOXELS_BUFFER_PADDING * 2, + CHUNK_H, + CHUNK_D + VOXELS_BUFFER_PADDING * 2 + ); + voxelsBuffer->setPosition( + chunk.x * CHUNK_W - VOXELS_BUFFER_PADDING, 0, + chunk.z * CHUNK_D - VOXELS_BUFFER_PADDING + ); + chunks.getVoxels( + *voxelsBuffer, settings.graphics.backlight.get(), chunk.top + 1 + ); + return voxelsBuffer; +} + const Mesh* ChunksRenderer::render( const std::shared_ptr& chunk, bool important ) { + glm::ivec2 key(chunk->x, chunk->z); chunk->flags.modified = false; if (important) { - auto mesh = renderer->render(chunk.get(), &chunks); - meshes[glm::ivec2(chunk->x, chunk->z)] = ChunkMesh { - std::move(mesh.mesh), std::move(mesh.sortingMeshData) - }; + auto voxelsBuffer = prepareVoxelsVolume(*chunk); + inwork[key] = true; + + auto mesh = renderer->render(chunk.get(), *voxelsBuffer); + meshes[glm::ivec2(chunk->x, chunk->z)] = + ChunkMesh {std::move(mesh.mesh), std::move(mesh.sortingMeshData)}; return meshes[glm::ivec2(chunk->x, chunk->z)].mesh.get(); } - glm::ivec2 key(chunk->x, chunk->z); if (inwork.find(key) != inwork.end()) { return nullptr; } + auto voxelsBuffer = prepareVoxelsVolume(*chunk); inwork[key] = true; - threadPool.enqueueJob(chunk); + chunks.getVoxels( + *voxelsBuffer, settings.graphics.backlight.get(), chunk->top + 1 + ); + + threadPool.enqueueJob({chunk, std::move(voxelsBuffer)}); return nullptr; } diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index 9215a8638..9794a8405 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -21,6 +21,7 @@ class Chunks; class Frustum; class BlocksRenderer; class ContentGfxCache; +class VoxelsVolume; struct EngineSettings; struct ChunksSortEntry { @@ -38,6 +39,11 @@ struct RendererResult { ChunkMeshData meshData; }; +struct RendererJob { + std::shared_ptr chunk; + std::shared_ptr volume; +}; + class ChunksRenderer { const Chunks& chunks; const Assets& assets; @@ -48,10 +54,11 @@ class ChunksRenderer { std::unordered_map meshes; std::unordered_map inwork; std::vector indices; - util::ThreadPool, RendererResult> threadPool; + util::ThreadPool threadPool; const Mesh* retrieveChunk( size_t index, const Camera& camera, bool culling ); + std::shared_ptr prepareVoxelsVolume(const Chunk& chunk); public: ChunksRenderer( const Level* level, diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index cc7450f9f..aa817b354 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -126,7 +126,7 @@ void Emitter::update( } void Emitter::stop() { - count = 0; + this->count = 0; } bool Emitter::isDead() const { @@ -138,7 +138,7 @@ bool Emitter::isReferred() const { } const EmitterOrigin& Emitter::getOrigin() const { - return origin; + return this->origin; } void Emitter::setOrigin(const EmitterOrigin& origin) { diff --git a/src/graphics/render/PrecipitationRenderer.cpp b/src/graphics/render/PrecipitationRenderer.cpp index 68c955c34..484425273 100644 --- a/src/graphics/render/PrecipitationRenderer.cpp +++ b/src/graphics/render/PrecipitationRenderer.cpp @@ -149,7 +149,7 @@ void PrecipitationRenderer::render( glm::cross(glm::vec3(0, 1, 0), face.right), FACE_SIZE, light_at(chunks, pos.x, y, pos.z), - glm::vec3(2.0f), + glm::vec3(3.0f), calc_uv(pos, face.right, timer, weather) ); } diff --git a/src/util/ObjectsPool.hpp b/src/util/ObjectsPool.hpp index 075024f8e..25f633ab1 100644 --- a/src/util/ObjectsPool.hpp +++ b/src/util/ObjectsPool.hpp @@ -46,6 +46,10 @@ namespace util { freeObjects.push(ptr); }); } + + size_t countTotal() const { + return objects.size(); + } private: std::vector> objects; std::queue freeObjects; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index eded34e89..96c709639 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -334,7 +334,8 @@ bool Chunks::putChunk(const std::shared_ptr& chunk) { // reduce nesting on next modification // 25.06.2024: not now // 11.11.2024: not now -void Chunks::getVoxels(VoxelsVolume& volume, bool backlight) const { +// 12.12.2025: not now +void Chunks::getVoxels(VoxelsVolume& volume, bool backlight, int top) const { voxel* voxels = volume.getVoxels(); light_t* lights = volume.getLights(); int x = volume.getX(); @@ -342,7 +343,7 @@ void Chunks::getVoxels(VoxelsVolume& volume, bool backlight) const { int z = volume.getZ(); int w = volume.getW(); - int h = volume.getH(); + int h = std::min(volume.getH(), top); int d = volume.getD(); int scx = floordiv(x); diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index 214e47c67..2448d8333 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -9,6 +9,7 @@ #include "typedefs.hpp" #include "voxel.hpp" +#include "constants.hpp" #include "util/AreaMap2D.hpp" class VoxelRenderer; @@ -126,7 +127,7 @@ 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 getVoxels(VoxelsVolume& volume, bool backlight = false, int top = CHUNK_H) const; void setCenter(int32_t x, int32_t z); void resize(uint32_t newW, uint32_t newD);