mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-13 15:01:49 +00:00
fix translucent rendering order across chunk boundaries
This commit is contained in:
parent
1bea18294f
commit
b201151500
1 changed files with 50 additions and 32 deletions
|
|
@ -329,7 +329,7 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) {
|
||||||
static int frameid = 0;
|
static int frameid = 0;
|
||||||
frameid++;
|
frameid++;
|
||||||
|
|
||||||
bool culling = settings.graphics.frustumCulling.get();
|
const bool culling = settings.graphics.frustumCulling.get();
|
||||||
const auto& chunks = this->chunks.getChunks();
|
const auto& chunks = this->chunks.getChunks();
|
||||||
const auto& cameraPos = camera.position;
|
const auto& cameraPos = camera.position;
|
||||||
const auto& atlas = assets.require<Atlas>("blocks");
|
const auto& atlas = assets.require<Atlas>("blocks");
|
||||||
|
|
@ -339,59 +339,77 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) {
|
||||||
shader.uniformMatrix("u_model", glm::mat4(1.0f));
|
shader.uniformMatrix("u_model", glm::mat4(1.0f));
|
||||||
shader.uniform1i("u_alphaClip", false);
|
shader.uniform1i("u_alphaClip", false);
|
||||||
|
|
||||||
|
struct VisibleChunkTrans {
|
||||||
|
glm::ivec2 key;
|
||||||
|
const std::shared_ptr<Chunk>* chunkPtr;
|
||||||
|
long long nearestDist2;
|
||||||
|
};
|
||||||
|
std::vector<VisibleChunkTrans> order;
|
||||||
|
order.reserve(indices.size());
|
||||||
|
|
||||||
|
// Build per-chunk nearest distance for translucent entries
|
||||||
for (const auto& index : indices) {
|
for (const auto& index : indices) {
|
||||||
const auto& chunk = chunks[index.index];
|
const auto& chunk = chunks[index.index];
|
||||||
if (chunk == nullptr || !chunk->flags.lighted) {
|
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto& found = meshes.find(glm::ivec2(chunk->x, chunk->z));
|
const auto found = meshes.find(glm::ivec2(chunk->x, chunk->z));
|
||||||
if (found == meshes.end() || found->second.sortingMeshData.entries.empty()) {
|
if (found == meshes.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto& entries = found->second.sortingMeshData.entries;
|
||||||
|
if (entries.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (culling) {
|
if (culling) {
|
||||||
glm::vec3 min(chunk->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, chunk->z * CHUNK_D + CHUNK_D);
|
glm::vec3 max(chunk->x * CHUNK_W + CHUNK_W, chunk->top, chunk->z * CHUNK_D + CHUNK_D);
|
||||||
const auto& found2 = meshes.find(glm::ivec2(chunk->x, chunk->z));
|
const auto& aabb = found->second.localAabb;
|
||||||
if (found2 != meshes.end()) {
|
if (aabb.size().x > 0.0f || aabb.size().y > 0.0f || aabb.size().z > 0.0f) {
|
||||||
const auto& aabb = found2->second.localAabb;
|
min = glm::vec3(chunk->x * CHUNK_W + aabb.min().x + 0.5f,
|
||||||
if (aabb.size().x > 0.0f || aabb.size().y > 0.0f || aabb.size().z > 0.0f) {
|
(std::max)(static_cast<float>(chunk->bottom), aabb.min().y + 0.5f),
|
||||||
min = glm::vec3(chunk->x * CHUNK_W + aabb.min().x + 0.5f,
|
chunk->z * CHUNK_D + aabb.min().z + 0.5f);
|
||||||
(std::max)(static_cast<float>(chunk->bottom), aabb.min().y + 0.5f),
|
max = glm::vec3(chunk->x * CHUNK_W + aabb.max().x + 0.5f,
|
||||||
chunk->z * CHUNK_D + aabb.min().z + 0.5f);
|
(std::min)(static_cast<float>(chunk->top), aabb.max().y + 0.5f),
|
||||||
max = glm::vec3(chunk->x * CHUNK_W + aabb.max().x + 0.5f,
|
chunk->z * CHUNK_D + aabb.max().z + 0.5f);
|
||||||
(std::min)(static_cast<float>(chunk->top), aabb.max().y + 0.5f),
|
|
||||||
chunk->z * CHUNK_D + aabb.max().z + 0.5f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!frustum.isBoxVisible(min, max)) continue;
|
if (!frustum.isBoxVisible(min, max)) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& chunkEntries = found->second.sortingMeshData.entries;
|
long long nearest = LLONG_MAX;
|
||||||
|
for (const auto& e : entries) {
|
||||||
|
long long d2 = static_cast<long long>(glm::distance2(e.position, cameraPos));
|
||||||
|
if (d2 < nearest) nearest = d2;
|
||||||
|
}
|
||||||
|
order.push_back(VisibleChunkTrans{glm::ivec2(chunk->x, chunk->z), &chunks[index.index], nearest});
|
||||||
|
}
|
||||||
|
|
||||||
if (chunkEntries.size() == 1) {
|
// Sort chunks by nearest translucent distance back-to-front (far to near)
|
||||||
auto& entry = chunkEntries.at(0);
|
std::sort(order.begin(), order.end(), [](const VisibleChunkTrans& a, const VisibleChunkTrans& b) {
|
||||||
if (found->second.sortedMesh == nullptr) {
|
return a.nearestDist2 > b.nearestDist2;
|
||||||
found->second.sortedMesh = std::make_unique<Mesh<ChunkVertex>>(
|
});
|
||||||
entry.vertexData.data(), entry.vertexData.size()
|
|
||||||
|
// Draw per-chunk sorted mesh (keeps GPU buffers and avoids per-frame repack)
|
||||||
|
for (const auto& item : order) {
|
||||||
|
const auto& chunk = *item.chunkPtr;
|
||||||
|
const auto found = meshes.find(item.key);
|
||||||
|
if (found == meshes.end()) continue;
|
||||||
|
auto& chunkEntries = found->second.sortingMeshData.entries;
|
||||||
|
if (chunkEntries.empty()) continue;
|
||||||
|
|
||||||
|
// Keep per-chunk internal order up-to-date occasionally
|
||||||
|
if (found->second.sortedMesh == nullptr || (frameid + chunk->x) % sortInterval == 0) {
|
||||||
|
for (auto& entry : chunkEntries) {
|
||||||
|
entry.distance = static_cast<long long>(
|
||||||
|
glm::distance2(entry.position, cameraPos)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
found->second.sortedMesh->draw();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (auto& entry : chunkEntries) {
|
|
||||||
entry.distance = static_cast<long long>(
|
|
||||||
glm::distance2(entry.position, cameraPos)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (found->second.sortedMesh == nullptr ||
|
|
||||||
(frameid + chunk->x) % sortInterval == 0) {
|
|
||||||
std::sort(chunkEntries.begin(), chunkEntries.end());
|
std::sort(chunkEntries.begin(), chunkEntries.end());
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
for (const auto& entry : chunkEntries) {
|
for (const auto& entry : chunkEntries) {
|
||||||
size += entry.vertexData.size();
|
size += entry.vertexData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
static util::Buffer<ChunkVertex> buffer;
|
static util::Buffer<ChunkVertex> buffer;
|
||||||
if (buffer.size() < size) {
|
if (buffer.size() < size) {
|
||||||
buffer = util::Buffer<ChunkVertex>(size);
|
buffer = util::Buffer<ChunkVertex>(size);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue