introduce ChunkMesh
This commit is contained in:
parent
5793c52ac6
commit
5b6256e0fa
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
|
||||
29
src/graphics/render/commons.hpp
Normal file
29
src/graphics/render/commons.hpp
Normal 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;
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user