mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-07 12:01:50 +00:00
stabilize delays of chunks meshes building
This commit is contained in:
parent
f47ccd5f30
commit
88544183d0
13 changed files with 335 additions and 191 deletions
|
|
@ -42,21 +42,22 @@ void BlocksRenderer::vertex(
|
|||
const glm::vec3& normal,
|
||||
float emission
|
||||
) {
|
||||
vertexBuffer[vertexCount].position = coord;
|
||||
|
||||
vertexBuffer[vertexCount].uv = {u,v};
|
||||
|
||||
vertexBuffer[vertexCount].normal[0] = static_cast<uint8_t>(normal.r * 127 + 128);
|
||||
vertexBuffer[vertexCount].normal[1] = static_cast<uint8_t>(normal.g * 127 + 128);
|
||||
vertexBuffer[vertexCount].normal[2] = static_cast<uint8_t>(normal.b * 127 + 128);
|
||||
vertexBuffer[vertexCount].normal[3] = static_cast<uint8_t>(emission * 255);
|
||||
|
||||
vertexBuffer[vertexCount].color[0] = static_cast<uint8_t>(light.r * 255);
|
||||
vertexBuffer[vertexCount].color[1] = static_cast<uint8_t>(light.g * 255);
|
||||
vertexBuffer[vertexCount].color[2] = static_cast<uint8_t>(light.b * 255);
|
||||
vertexBuffer[vertexCount].color[3] = static_cast<uint8_t>(light.a * 255);
|
||||
|
||||
vertexCount++;
|
||||
vertexBuffer[vertexCount++] = {
|
||||
coord,
|
||||
{u, v},
|
||||
{
|
||||
static_cast<uint8_t>(light.r * 255),
|
||||
static_cast<uint8_t>(light.g * 255),
|
||||
static_cast<uint8_t>(light.b * 255),
|
||||
static_cast<uint8_t>(light.a * 255),
|
||||
}, {
|
||||
static_cast<uint8_t>(normal.x * 127 + 128),
|
||||
static_cast<uint8_t>(normal.y * 127 + 128),
|
||||
static_cast<uint8_t>(normal.z * 127 + 128),
|
||||
static_cast<uint8_t>(emission * 255)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void BlocksRenderer::index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f) {
|
||||
|
|
@ -434,28 +435,11 @@ void BlocksRenderer::blockCube(
|
|||
}
|
||||
}
|
||||
|
||||
bool BlocksRenderer::isOpenForLight(int x, int y, int z) const {
|
||||
blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x,
|
||||
y,
|
||||
chunk->z * CHUNK_D + z);
|
||||
if (id == BLOCK_VOID) {
|
||||
return false;
|
||||
}
|
||||
const Block& block = *blockDefsCache[id];
|
||||
if (block.lightPassing) {
|
||||
return true;
|
||||
}
|
||||
return !id;
|
||||
}
|
||||
|
||||
glm::vec4 BlocksRenderer::pickLight(int x, int y, int z) const {
|
||||
if (isOpenForLight(x, y, z)) {
|
||||
light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y,
|
||||
chunk->z * CHUNK_D + z);
|
||||
return Lightmap::extractNormalized(light);
|
||||
} else {
|
||||
return glm::vec4(0.0f);
|
||||
}
|
||||
light_t light = voxelsBuffer->pickLight(
|
||||
chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z
|
||||
);
|
||||
return light ? Lightmap::extractNormalized(light) : glm::vec4(0.0f);
|
||||
}
|
||||
|
||||
glm::vec4 BlocksRenderer::pickLight(const glm::ivec3& coord) const {
|
||||
|
|
@ -694,7 +678,9 @@ SortingMeshData BlocksRenderer::renderTranslucent(
|
|||
return sortingMesh;
|
||||
}
|
||||
|
||||
void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) {
|
||||
void BlocksRenderer::build(
|
||||
const Chunk* chunk, const VoxelsRenderVolume& volume
|
||||
) {
|
||||
this->chunk = chunk;
|
||||
this->voxelsBuffer = &volume;
|
||||
if (voxelsBuffer->pickBlockId(
|
||||
|
|
@ -707,16 +693,17 @@ void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) {
|
|||
|
||||
int totalBegin = chunk->bottom * (CHUNK_W * CHUNK_D);
|
||||
int totalEnd = chunk->top * (CHUNK_W * CHUNK_D);
|
||||
|
||||
bool hasTranslucent = false;
|
||||
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];
|
||||
const auto& variant = def.getVariantByBits(vox.state.userbits);
|
||||
hasTranslucent = def.translucent || hasTranslucent;
|
||||
|
||||
if (beginEnds[variant.drawGroup][0] == 0) {
|
||||
beginEnds[variant.drawGroup][0] = i+1;
|
||||
beginEnds[variant.drawGroup][0] = i + 1;
|
||||
}
|
||||
beginEnds[variant.drawGroup][1] = i;
|
||||
}
|
||||
|
|
@ -729,7 +716,11 @@ void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) {
|
|||
denseRender = false;
|
||||
densePass = false;
|
||||
|
||||
sortingMesh = renderTranslucent(voxels, beginEnds);
|
||||
if (hasTranslucent) {
|
||||
sortingMesh = renderTranslucent(voxels, beginEnds);
|
||||
} else {
|
||||
sortingMesh = {};
|
||||
}
|
||||
|
||||
overflow = false;
|
||||
vertexCount = 0;
|
||||
|
|
@ -775,7 +766,7 @@ ChunkMeshData BlocksRenderer::createMesh() {
|
|||
}
|
||||
|
||||
ChunkMesh BlocksRenderer::render(
|
||||
const Chunk* chunk, const VoxelsVolume& volume
|
||||
const Chunk* chunk, const VoxelsRenderVolume& volume
|
||||
) {
|
||||
build(chunk, volume);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ class Content;
|
|||
class Block;
|
||||
class Chunk;
|
||||
class Chunks;
|
||||
class VoxelsVolume;
|
||||
class ContentGfxCache;
|
||||
struct UVRegion;
|
||||
|
||||
|
|
@ -31,9 +30,9 @@ public:
|
|||
);
|
||||
~BlocksRenderer();
|
||||
|
||||
void build(const Chunk* chunk, const VoxelsVolume& volume);
|
||||
void build(const Chunk* chunk, const VoxelsRenderVolume& volume);
|
||||
ChunkMesh render(
|
||||
const Chunk* chunk, const VoxelsVolume& volume
|
||||
const Chunk* chunk, const VoxelsRenderVolume& volume
|
||||
);
|
||||
ChunkMeshData createMesh();
|
||||
|
||||
|
|
@ -58,7 +57,7 @@ private:
|
|||
bool densePass = false;
|
||||
bool denseRender = false;
|
||||
const Chunk* chunk = nullptr;
|
||||
const VoxelsVolume* voxelsBuffer = nullptr;
|
||||
const VoxelsRenderVolume* voxelsBuffer = nullptr;
|
||||
|
||||
const Block* const* blockDefsCache;
|
||||
const ContentGfxCache& cache;
|
||||
|
|
@ -143,8 +142,6 @@ private:
|
|||
bool ao
|
||||
);
|
||||
|
||||
bool isOpenForLight(int x, int y, int z) const;
|
||||
|
||||
// Does block allow to see other blocks sides (is it transparent)
|
||||
inline bool isOpen(const glm::ivec3& pos, const Block& def, const Variant& variant) const {
|
||||
auto vox = voxelsBuffer->pickBlock(
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ static debug::Logger logger("chunks-render");
|
|||
|
||||
size_t ChunksRenderer::visibleChunks = 0;
|
||||
|
||||
static constexpr inline size_t MAX_CHUNKS_ENQUEUED_IN_FRAME = 4;
|
||||
|
||||
class RendererWorker : public util::Worker<RendererJob, RendererResult> {
|
||||
BlocksRenderer renderer;
|
||||
public:
|
||||
|
|
@ -51,8 +53,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
static util::ObjectsPool<VoxelsVolume> voxelsVolumesPool {};
|
||||
static inline const int VOXELS_BUFFER_PADDING = 2;
|
||||
static util::ObjectsPool<VoxelsRenderVolume> voxelsVolumesPool {};
|
||||
|
||||
ChunksRenderer::ChunksRenderer(
|
||||
const Level* level,
|
||||
|
|
@ -69,7 +70,7 @@ ChunksRenderer::ChunksRenderer(
|
|||
threadPool(
|
||||
"chunks-render-pool",
|
||||
[&]() {
|
||||
return std::make_shared<RendererWorker>(
|
||||
return std::make_unique<RendererWorker>(
|
||||
*level, cache, settings
|
||||
);
|
||||
},
|
||||
|
|
@ -105,14 +106,10 @@ ChunksRenderer::ChunksRenderer(
|
|||
|
||||
ChunksRenderer::~ChunksRenderer() = default;
|
||||
|
||||
std::shared_ptr<VoxelsVolume> ChunksRenderer::prepareVoxelsVolume(
|
||||
std::shared_ptr<VoxelsRenderVolume> ChunksRenderer::prepareVoxelsVolume(
|
||||
const Chunk& chunk
|
||||
) {
|
||||
auto voxelsBuffer = voxelsVolumesPool.create(
|
||||
CHUNK_W + VOXELS_BUFFER_PADDING * 2,
|
||||
CHUNK_H,
|
||||
CHUNK_D + VOXELS_BUFFER_PADDING * 2
|
||||
);
|
||||
auto voxelsBuffer = voxelsVolumesPool.create();
|
||||
voxelsBuffer->setPosition(
|
||||
chunk.x * CHUNK_W - VOXELS_BUFFER_PADDING, 0,
|
||||
chunk.z * CHUNK_D - VOXELS_BUFFER_PADDING
|
||||
|
|
@ -123,8 +120,10 @@ std::shared_ptr<VoxelsVolume> ChunksRenderer::prepareVoxelsVolume(
|
|||
return voxelsBuffer;
|
||||
}
|
||||
|
||||
#include "util/timeutil.hpp"
|
||||
|
||||
const Mesh<ChunkVertex>* ChunksRenderer::render(
|
||||
const std::shared_ptr<Chunk>& chunk, bool important
|
||||
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
|
||||
) {
|
||||
glm::ivec2 key(chunk->x, chunk->z);
|
||||
chunk->flags.modified = false;
|
||||
|
|
@ -136,16 +135,16 @@ const Mesh<ChunkVertex>* ChunksRenderer::render(
|
|||
std::move(mesh.mesh), std::move(mesh.sortingMeshData), nullptr};
|
||||
return meshes[key].mesh.get();
|
||||
}
|
||||
if (inwork.find(key) != inwork.end()) {
|
||||
if (inwork.find(key) != inwork.end() ||
|
||||
((inwork.size() >= threadPool.getWorkTotal() ||
|
||||
enqueuedInFrame >= MAX_CHUNKS_ENQUEUED_IN_FRAME) &&
|
||||
lowPriority)) {
|
||||
return nullptr;
|
||||
}
|
||||
enqueuedInFrame++;
|
||||
auto voxelsBuffer = prepareVoxelsVolume(*chunk);
|
||||
inwork[key] = true;
|
||||
chunks.getVoxels(
|
||||
*voxelsBuffer, settings.graphics.backlight.get(), chunk->top + 1
|
||||
);
|
||||
|
||||
threadPool.enqueueJob({chunk, std::move(voxelsBuffer)});
|
||||
inwork[key] = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -163,20 +162,21 @@ void ChunksRenderer::clear() {
|
|||
}
|
||||
|
||||
const Mesh<ChunkVertex>* ChunksRenderer::getOrRender(
|
||||
const std::shared_ptr<Chunk>& chunk, bool important
|
||||
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
|
||||
) {
|
||||
auto found = meshes.find(glm::ivec2(chunk->x, chunk->z));
|
||||
if (found == meshes.end()) {
|
||||
return render(chunk, important);
|
||||
return render(chunk, important, lowPriority);
|
||||
}
|
||||
if (chunk->flags.modified && chunk->flags.lighted) {
|
||||
render(chunk, important);
|
||||
render(chunk, important, lowPriority);
|
||||
}
|
||||
return found->second.mesh.get();
|
||||
}
|
||||
|
||||
void ChunksRenderer::update() {
|
||||
threadPool.pullResults();
|
||||
enqueuedInFrame = 0;
|
||||
}
|
||||
|
||||
const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(
|
||||
|
|
@ -202,7 +202,11 @@ const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(
|
|||
(chunk->z + 0.5f) * CHUNK_D
|
||||
)
|
||||
);
|
||||
auto mesh = getOrRender(chunk, distance < CHUNK_W * 1.5f);
|
||||
auto mesh = getOrRender(
|
||||
chunk,
|
||||
distance < CHUNK_W * 1.5f,
|
||||
distance > CHUNK_W * settings.chunks.loadDistance.get() * 0.5
|
||||
);
|
||||
if (mesh == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ class Chunks;
|
|||
class Frustum;
|
||||
class BlocksRenderer;
|
||||
class ContentGfxCache;
|
||||
class VoxelsVolume;
|
||||
struct EngineSettings;
|
||||
|
||||
struct ChunksSortEntry {
|
||||
|
|
@ -41,7 +40,7 @@ struct RendererResult {
|
|||
|
||||
struct RendererJob {
|
||||
std::shared_ptr<Chunk> chunk;
|
||||
std::shared_ptr<VoxelsVolume> volume;
|
||||
std::shared_ptr<VoxelsRenderVolume> volume;
|
||||
};
|
||||
|
||||
class ChunksRenderer {
|
||||
|
|
@ -58,7 +57,8 @@ class ChunksRenderer {
|
|||
const Mesh<ChunkVertex>* retrieveChunk(
|
||||
size_t index, const Camera& camera, bool culling
|
||||
);
|
||||
std::shared_ptr<VoxelsVolume> prepareVoxelsVolume(const Chunk& chunk);
|
||||
std::shared_ptr<VoxelsRenderVolume> prepareVoxelsVolume(const Chunk& chunk);
|
||||
size_t enqueuedInFrame = 0;
|
||||
public:
|
||||
ChunksRenderer(
|
||||
const Level* level,
|
||||
|
|
@ -71,13 +71,13 @@ public:
|
|||
virtual ~ChunksRenderer();
|
||||
|
||||
const Mesh<ChunkVertex>* render(
|
||||
const std::shared_ptr<Chunk>& chunk, bool important
|
||||
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
|
||||
);
|
||||
void unload(const Chunk* chunk);
|
||||
void clear();
|
||||
|
||||
const Mesh<ChunkVertex>* getOrRender(
|
||||
const std::shared_ptr<Chunk>& chunk, bool important
|
||||
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
|
||||
);
|
||||
|
||||
void drawShadowsPass(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "graphics/core/MeshData.hpp"
|
||||
#include "util/Buffer.hpp"
|
||||
|
||||
|
|
@ -51,3 +52,12 @@ struct ChunkMesh {
|
|||
SortingMeshData sortingMeshData;
|
||||
std::unique_ptr<Mesh<ChunkVertex> > sortedMesh;
|
||||
};
|
||||
|
||||
inline constexpr int VOXELS_BUFFER_PADDING = 2;
|
||||
|
||||
template<int, int, int> class StaticVoxelsVolume;
|
||||
|
||||
using VoxelsRenderVolume = StaticVoxelsVolume<
|
||||
CHUNK_W + VOXELS_BUFFER_PADDING * 2,
|
||||
CHUNK_H,
|
||||
CHUNK_D + VOXELS_BUFFER_PADDING * 2>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue