diff --git a/src/graphics/core/Mesh.inl b/src/graphics/core/Mesh.inl index 778baaf9..c4cec966 100644 --- a/src/graphics/core/Mesh.inl +++ b/src/graphics/core/Mesh.inl @@ -126,11 +126,9 @@ void Mesh::draw(unsigned int primitive, int iboIndex) const { if (!ibos.empty()) { if (iboIndex < ibos.size()) { glBindVertexArray(vao); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibos[ - std::min(static_cast(iboIndex), ibos.size()) - ].ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibos[iboIndex].ibo); glDrawElements( - primitive, ibos.at(0).indexCount, GL_UNSIGNED_INT, nullptr + primitive, ibos.at(iboIndex).indexCount, GL_UNSIGNED_INT, nullptr ); glBindVertexArray(0); } diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index d52fea6c..1f14d2c7 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -20,6 +20,7 @@ BlocksRenderer::BlocksRenderer( ) : content(content), vertexBuffer(std::make_unique(capacity)), indexBuffer(std::make_unique(capacity)), + denseIndexBuffer(std::make_unique(capacity)), vertexCount(0), vertexOffset(0), indexCount(0), @@ -475,9 +476,10 @@ glm::vec4 BlocksRenderer::pickSoftLight( } void BlocksRenderer::render( - const voxel* voxels, int beginEnds[256][2] + const voxel* voxels, const int beginEnds[256][2] ) { bool denseRender = this->denseRender; + bool densePass = this->densePass; for (const auto drawGroup : *content.drawGroups) { int begin = beginEnds[drawGroup][0]; if (begin == 0) { @@ -494,16 +496,19 @@ void BlocksRenderer::render( if (id == 0 || variant.drawGroup != drawGroup || state.segment) { continue; } + if (denseRender != (variant.culling == CullingMode::OPTIONAL)) { + continue; + } if (def.translucent) { continue; } const UVRegion texfaces[6] { - cache.getRegion(id, variantId, 0, denseRender), - cache.getRegion(id, variantId, 1, denseRender), - cache.getRegion(id, variantId, 2, denseRender), - cache.getRegion(id, variantId, 3, denseRender), - cache.getRegion(id, variantId, 4, denseRender), - cache.getRegion(id, variantId, 5, denseRender) + cache.getRegion(id, variantId, 0, densePass), + cache.getRegion(id, variantId, 1, densePass), + cache.getRegion(id, variantId, 2, densePass), + cache.getRegion(id, variantId, 3, densePass), + cache.getRegion(id, variantId, 4, densePass), + cache.getRegion(id, variantId, 5, densePass) }; int x = i % CHUNK_W; int y = i / (CHUNK_D * CHUNK_W); @@ -514,16 +519,19 @@ void BlocksRenderer::render( def.ambientOcclusion); break; case BlockModelType::XSPRITE: { + if (!denseRender) blockXSprite(x, y, z, glm::vec3(1.0f), texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f); break; } case BlockModelType::AABB: { + if (!denseRender) blockAABB({x, y, z}, texfaces, &def, vox.state.rotation, !def.shadeless, def.ambientOcclusion); break; } case BlockModelType::CUSTOM: { + if (!denseRender) blockCustomModel( {x, y, z}, def, @@ -552,7 +560,7 @@ SortingMeshData BlocksRenderer::renderTranslucent( bool aabbInit = false; size_t totalSize = 0; - bool denseRender = this->denseRender; + bool densePass = this->densePass; for (const auto drawGroup : *content.drawGroups) { int begin = beginEnds[drawGroup][0]; if (begin == 0) { @@ -573,12 +581,12 @@ SortingMeshData BlocksRenderer::renderTranslucent( continue; } const UVRegion texfaces[6] { - cache.getRegion(id, variantId, 0, denseRender), - cache.getRegion(id, variantId, 1, denseRender), - cache.getRegion(id, variantId, 2, denseRender), - cache.getRegion(id, variantId, 3, denseRender), - cache.getRegion(id, variantId, 4, denseRender), - cache.getRegion(id, variantId, 5, denseRender) + cache.getRegion(id, variantId, 0, densePass), + cache.getRegion(id, variantId, 1, densePass), + cache.getRegion(id, variantId, 2, densePass), + cache.getRegion(id, variantId, 3, densePass), + cache.getRegion(id, variantId, 4, densePass), + cache.getRegion(id, variantId, 5, densePass) }; int x = i % CHUNK_W; int y = i / (CHUNK_D * CHUNK_W); @@ -703,29 +711,45 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) { vertexCount = 0; vertexOffset = indexCount = 0; + denseRender = false; + densePass = false; + sortingMesh = renderTranslucent(voxels, beginEnds); overflow = false; vertexCount = 0; vertexOffset = 0; indexCount = 0; + denseIndexCount = 0; - denseRender = settings.graphics.denseRender.get(); - // denseRender = false; - + denseRender = false; //settings.graphics.denseRender.get(); + densePass = false; render(voxels, beginEnds); - // denseRender = settings.graphics.denseRender.get(); - // if (denseRender) { - - // } + size_t endIndex = indexCount; + + denseRender = true; + densePass = true; + render(voxels, beginEnds); + + denseIndexCount = indexCount; + for (size_t i = 0; i < denseIndexCount; i++) { + denseIndexBuffer[i] = indexBuffer[i]; + } + + indexCount = endIndex; + densePass = false; + render(voxels, beginEnds); } ChunkMeshData BlocksRenderer::createMesh() { - return ChunkMeshData{ + return ChunkMeshData { MeshData( util::Buffer(vertexBuffer.get(), vertexCount), - std::vector> {util::Buffer(indexBuffer.get(), indexCount)}, + std::vector> { + util::Buffer(indexBuffer.get(), indexCount), + util::Buffer(denseIndexBuffer.get(), denseIndexCount), + }, util::Buffer( ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute) ) @@ -739,10 +763,18 @@ ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) { return ChunkMesh{std::make_unique>( vertexBuffer.get(), vertexCount, - std::vector {IndexBufferData {indexBuffer.get(), indexCount}} + std::vector { + IndexBufferData {indexBuffer.get(), indexCount}, + IndexBufferData {denseIndexBuffer.get(), denseIndexCount}, + } ), 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)); +} diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 6f1ff0d6..a954fad6 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -26,13 +26,16 @@ class BlocksRenderer { const Content& content; std::unique_ptr vertexBuffer; std::unique_ptr indexBuffer; + std::unique_ptr denseIndexBuffer; size_t vertexCount; size_t vertexOffset; 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; @@ -136,10 +139,12 @@ class BlocksRenderer { if ((otherDrawGroup && (otherDrawGroup != variant.drawGroup)) || !blockVariant.rt.solid) { return true; } - if ((variant.culling == CullingMode::DISABLED || - (variant.culling == CullingMode::OPTIONAL && - denseRender)) && - vox.id == def.rt.id) { + if (densePass) { + return variant.culling == CullingMode::OPTIONAL; + } else if (variant.culling == CullingMode::OPTIONAL) { + return false; + } + if (variant.culling == CullingMode::DISABLED && vox.id == def.rt.id) { return true; } return !vox.id; @@ -150,7 +155,7 @@ class BlocksRenderer { 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, int beginEnds[256][2]); + void render(const voxel* voxels, const int beginEnds[256][2]); SortingMeshData renderTranslucent(const voxel* voxels, int beginEnds[256][2]); public: BlocksRenderer( @@ -166,6 +171,8 @@ public: ChunkMeshData createMesh(); VoxelsVolume* getVoxelsBuffer() const; + size_t getMemoryConsumption() const; + bool isCancelled() const { return cancelled; } diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 4f8bfc69..e3c1afb9 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -18,6 +18,9 @@ static debug::Logger logger("chunks-render"); size_t ChunksRenderer::visibleChunks = 0; +inline constexpr int DENSE_DISTANCE = 64; +inline constexpr int DENSE_DISTANCE2 = DENSE_DISTANCE * DENSE_DISTANCE; + class RendererWorker : public util::Worker, RendererResult> { const Chunks& chunks; BlocksRenderer renderer; @@ -87,6 +90,9 @@ ChunksRenderer::ChunksRenderer( level->content, cache, settings ); logger.info() << "created " << threadPool.getWorkersCount() << " workers"; + logger.info() << "memory consumption is " + << renderer->getMemoryConsumption() * threadPool.getWorkersCount() + << " B"; } ChunksRenderer::~ChunksRenderer() = default; @@ -182,7 +188,7 @@ const Mesh* ChunksRenderer::retrieveChunk( } void ChunksRenderer::drawChunksShadowsPass( - const Camera& camera, Shader& shader + const Camera& camera, Shader& shader, const Camera& playerCamera ) { Frustum frustum; frustum.update(camera.getProjView()); @@ -205,7 +211,7 @@ void ChunksRenderer::drawChunksShadowsPass( pos.x * CHUNK_W + 0.5f, 0.5f, pos.y * CHUNK_D + 0.5f ); - glm::vec3 min(pos.x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); + glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); glm::vec3 max( chunk->x * CHUNK_W + CHUNK_W, chunk->top, @@ -217,7 +223,9 @@ void ChunksRenderer::drawChunksShadowsPass( } glm::mat4 model = glm::translate(glm::mat4(1.0f), coord); shader.uniformMatrix("u_model", model); - found->second.mesh->draw(); + found->second.mesh->draw(GL_TRIANGLES, + glm::distance2(playerCamera.position * glm::vec3(1, 0, 1), + (min + max) * 0.5f * glm::vec3(1, 0, 1)) < DENSE_DISTANCE2); } } @@ -265,7 +273,8 @@ void ChunksRenderer::drawChunks( ); glm::mat4 model = glm::translate(glm::mat4(1.0f), coord); shader.uniformMatrix("u_model", model); - mesh->draw(); + mesh->draw(GL_TRIANGLES, glm::distance2(camera.position * glm::vec3(1, 0, 1), + (coord + glm::vec3(CHUNK_W * 0.5f, 0.0f, CHUNK_D * 0.5f))) < DENSE_DISTANCE2); visibleChunks++; } } diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index fcc8b07d..70925343 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -73,7 +73,9 @@ public: const std::shared_ptr& chunk, bool important ); - void drawChunksShadowsPass(const Camera& camera, Shader& shader); + void drawChunksShadowsPass( + const Camera& camera, Shader& shader, const Camera& playerCamera + ); void drawChunks(const Camera& camera, Shader& shader); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 065673ba..30a25430 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -406,7 +406,7 @@ void WorldRenderer::generateShadowsMap( sctx.setViewport({resolution, resolution}); shadowMap.bind(); setupWorldShader(shadowsShader, shadowCamera, settings, 0.0f); - chunks->drawChunksShadowsPass(shadowCamera, shadowsShader); + chunks->drawChunksShadowsPass(shadowCamera, shadowsShader, camera); shadowMap.unbind(); } }