introduce ChunkMesh

This commit is contained in:
MihailRis 2024-11-16 04:13:00 +03:00
parent 5793c52ac6
commit 5b6256e0fa
5 changed files with 172 additions and 42 deletions

View File

@ -12,6 +12,8 @@
#include <glm/glm.hpp>
#include "util/timeutil.hpp"
const uint BlocksRenderer::VERTEX_SIZE = 6;
const glm::vec3 BlocksRenderer::SUN_VECTOR (0.411934f, 0.863868f, -0.279161f);
@ -433,21 +435,9 @@ glm::vec4 BlocksRenderer::pickSoftLight(
right, up);
}
void BlocksRenderer::render(const voxel* voxels) {
int totalBegin = chunk->bottom * (CHUNK_W * CHUNK_D);
int totalEnd = chunk->top * (CHUNK_W * CHUNK_D);
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];
if (beginEnds[def.drawGroup][0] == 0) {
beginEnds[def.drawGroup][0] = i+1;
}
beginEnds[def.drawGroup][1] = i;
}
void BlocksRenderer::render(
const voxel* voxels, int beginEnds[256][2]
) {
for (const auto drawGroup : *content.drawGroups) {
int begin = beginEnds[drawGroup][0];
if (begin == 0) {
@ -462,13 +452,13 @@ void BlocksRenderer::render(const voxel* voxels) {
if (id == 0 || def.drawGroup != drawGroup || state.segment) {
continue;
}
//if (def.translucent) {
// continue;
//}
const UVRegion texfaces[6] {
cache.getRegion(id, 0),
cache.getRegion(id, 1),
cache.getRegion(id, 2),
cache.getRegion(id, 3),
cache.getRegion(id, 4),
cache.getRegion(id, 5)
cache.getRegion(id, 0), cache.getRegion(id, 1),
cache.getRegion(id, 2), cache.getRegion(id, 3),
cache.getRegion(id, 4), cache.getRegion(id, 5)
};
int x = i % CHUNK_W;
int y = i / (CHUNK_D * CHUNK_W);
@ -503,43 +493,143 @@ void BlocksRenderer::render(const voxel* voxels) {
}
}
SortingMeshData BlocksRenderer::renderTranslucent(
const voxel* voxels, int beginEnds[256][2]
) {
timeutil::ScopeLogTimer log(555);
SortingMeshData sortingMesh {{}};
for (const auto drawGroup : *content.drawGroups) {
int begin = beginEnds[drawGroup][0];
if (begin == 0) {
continue;
}
int end = beginEnds[drawGroup][1];
for (int i = begin-1; i <= end; i++) {
const voxel& vox = voxels[i];
blockid_t id = vox.id;
blockstate state = vox.state;
const auto& def = *blockDefsCache[id];
if (id == 0 || def.drawGroup != drawGroup || state.segment) {
continue;
}
if (!def.translucent) {
continue;
}
const UVRegion texfaces[6] {
cache.getRegion(id, 0), cache.getRegion(id, 1),
cache.getRegion(id, 2), cache.getRegion(id, 3),
cache.getRegion(id, 4), cache.getRegion(id, 5)
};
int x = i % CHUNK_W;
int y = i / (CHUNK_D * CHUNK_W);
int z = (i / CHUNK_D) % CHUNK_W;
switch (def.model) {
case BlockModel::block:
blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless,
def.ambientOcclusion);
break;
case BlockModel::xsprite: {
blockXSprite(x, y, z, glm::vec3(1.0f),
texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f);
break;
}
case BlockModel::aabb: {
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
!def.shadeless, def.ambientOcclusion);
break;
}
case BlockModel::custom: {
blockCustomModel({x, y, z}, &def, vox.state.rotation,
!def.shadeless, def.ambientOcclusion);
break;
}
default:
break;
}
if (vertexOffset == 0) {
continue;
}
SortingMeshEntry entry {glm::vec3(
x + chunk->x * CHUNK_W, y, z + chunk->z * CHUNK_D
), util::Buffer<float>(indexSize * VERTEX_SIZE)};
for (int j = 0; j < indexSize; j++) {
std::memcpy(
entry.vertexData.data(),
vertexBuffer.get() + indexBuffer[j] * VERTEX_SIZE,
sizeof(float) * VERTEX_SIZE
);
}
sortingMesh.entries.push_back(std::move(entry));
vertexOffset = 0;
indexOffset = indexSize = 0;
}
}
return sortingMesh;
}
void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) {
this->chunk = chunk;
voxelsBuffer->setPosition(
chunk->x * CHUNK_W - voxelBufferPadding, 0,
chunk->z * CHUNK_D - voxelBufferPadding);
chunks->getVoxels(voxelsBuffer.get(), settings.graphics.backlight.get());
overflow = false;
vertexOffset = 0;
indexOffset = indexSize = 0;
if (voxelsBuffer->pickBlockId(
chunk->x * CHUNK_W, 0, chunk->z * CHUNK_D
) == BLOCK_VOID) {
cancelled = true;
return;
}
cancelled = false;
const voxel* voxels = chunk->voxels;
render(voxels);
int totalBegin = chunk->bottom * (CHUNK_W * CHUNK_D);
int totalEnd = chunk->top * (CHUNK_W * CHUNK_D);
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];
if (beginEnds[def.drawGroup][0] == 0) {
beginEnds[def.drawGroup][0] = i+1;
}
beginEnds[def.drawGroup][1] = i;
}
cancelled = false;
overflow = false;
vertexOffset = 0;
indexOffset = indexSize = 0;
sortingMesh = std::move(renderTranslucent(voxels, beginEnds));
overflow = false;
vertexOffset = 0;
indexOffset = indexSize = 0;
render(voxels, beginEnds);
}
MeshData BlocksRenderer::createMesh() {
ChunkMeshData BlocksRenderer::createMesh() {
const vattr attrs[]{ {3}, {2}, {1}, {0} };
return MeshData(
return ChunkMeshData{MeshData(
util::Buffer<float>(vertexBuffer.get(), vertexOffset),
util::Buffer<int>(indexBuffer.get(), indexSize),
util::Buffer<vattr>({{3}, {2}, {1}, {0}})
);
), std::move(sortingMesh)};
}
std::shared_ptr<Mesh> BlocksRenderer::render(const Chunk* chunk, const Chunks* chunks) {
ChunkMesh BlocksRenderer::render(const Chunk* chunk, const Chunks* chunks) {
build(chunk, chunks);
const vattr attrs[]{ {3}, {2}, {1}, {0} };
size_t vcount = vertexOffset / BlocksRenderer::VERTEX_SIZE;
return std::make_shared<Mesh>(
return ChunkMesh{std::make_shared<Mesh>(
vertexBuffer.get(), vcount, indexBuffer.get(), indexSize, attrs
);
), std::move(sortingMesh)};
}
VoxelsVolume* BlocksRenderer::getVoxelsBuffer() const {

View File

@ -12,6 +12,7 @@
#include "voxels/VoxelsVolume.hpp"
#include "graphics/core/MeshData.hpp"
#include "maths/util.hpp"
#include "commons.hpp"
class Content;
class Mesh;
@ -45,6 +46,8 @@ class BlocksRenderer {
util::PseudoRandom randomizer;
SortingMeshData sortingMesh;
void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light);
void index(int a, int b, int c, int d, int e, int f);
@ -115,7 +118,6 @@ class BlocksRenderer {
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, ubyte group) const {
auto id = voxelsBuffer->pickBlockId(
@ -135,7 +137,9 @@ class BlocksRenderer {
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;
void render(const voxel* voxels);
void render(const voxel* voxels, int beginEnds[256][2]);
SortingMeshData renderTranslucent(const voxel* voxels, int beginEnds[256][2]);
public:
BlocksRenderer(
size_t capacity,
@ -146,8 +150,8 @@ public:
virtual ~BlocksRenderer();
void build(const Chunk* chunk, const Chunks* chunks);
std::shared_ptr<Mesh> render(const Chunk* chunk, const Chunks* chunks);
MeshData createMesh();
ChunkMesh render(const Chunk* chunk, const Chunks* chunks);
ChunkMeshData createMesh();
VoxelsVolume* getVoxelsBuffer() const;
bool isCancelled() const {

View File

@ -62,7 +62,11 @@ ChunksRenderer::ChunksRenderer(
[&](){return std::make_shared<RendererWorker>(*level, cache, settings);},
[&](RendererResult& result){
if (!result.cancelled) {
meshes[result.key] = std::make_shared<Mesh>(result.meshData);
auto meshData = std::move(result.meshData);
meshes[result.key] = ChunkMesh {
std::make_shared<Mesh>(meshData.mesh),
std::move(meshData.sortingMesh)
};
}
inwork.erase(result.key);
}, settings.graphics.chunkMaxRenderers.get())
@ -82,8 +86,10 @@ std::shared_ptr<Mesh> ChunksRenderer::render(const std::shared_ptr<Chunk>& chunk
chunk->flags.modified = false;
if (important) {
auto mesh = renderer->render(chunk.get(), level.chunks.get());
meshes[glm::ivec2(chunk->x, chunk->z)] = mesh;
return mesh;
meshes[glm::ivec2(chunk->x, chunk->z)] = ChunkMesh {
std::move(mesh.mesh), std::move(mesh.sortingMesh)
};
return meshes[glm::ivec2(chunk->x, chunk->z)].mesh;
}
glm::ivec2 key(chunk->x, chunk->z);
if (inwork.find(key) != inwork.end()) {
@ -115,7 +121,7 @@ std::shared_ptr<Mesh> ChunksRenderer::getOrRender(const std::shared_ptr<Chunk>&
if (chunk->flags.modified) {
render(chunk, important);
}
return found->second;
return found->second.mesh;
}
void ChunksRenderer::update() {

View File

@ -10,6 +10,7 @@
#include "voxels/ChunksStorage.hpp"
#include "util/ThreadPool.hpp"
#include "graphics/core/MeshData.hpp"
#include "commons.hpp"
class Mesh;
class Chunk;
@ -35,7 +36,7 @@ struct ChunksSortEntry {
struct RendererResult {
glm::ivec2 key;
bool cancelled;
MeshData meshData;
ChunkMeshData meshData;
};
class ChunksRenderer {
@ -45,7 +46,7 @@ class ChunksRenderer {
const EngineSettings& settings;
std::unique_ptr<BlocksRenderer> renderer;
std::unordered_map<glm::ivec2, std::shared_ptr<Mesh>> meshes;
std::unordered_map<glm::ivec2, ChunkMesh> meshes;
std::unordered_map<glm::ivec2, bool> inwork;
std::vector<ChunksSortEntry> indices;
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;

View File

@ -0,0 +1,29 @@
#pragma once
#include <vector>
#include <memory>
#include <glm/vec3.hpp>
#include "graphics/core/MeshData.hpp"
#include "util/Buffer.hpp"
class Mesh;
struct SortingMeshEntry {
glm::vec3 position;
util::Buffer<float> vertexData;
};
struct SortingMeshData {
std::vector<SortingMeshEntry> entries;
};
struct ChunkMeshData {
MeshData mesh;
SortingMeshData sortingMesh;
};
struct ChunkMesh {
std::shared_ptr<Mesh> mesh;
SortingMeshData sortingMesh;
};