refactor
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include "graphics/ui/elements/InputBindBox.hpp"
|
#include "graphics/ui/elements/InputBindBox.hpp"
|
||||||
#include "graphics/render/WorldRenderer.hpp"
|
#include "graphics/render/WorldRenderer.hpp"
|
||||||
#include "graphics/render/ParticlesRenderer.hpp"
|
#include "graphics/render/ParticlesRenderer.hpp"
|
||||||
|
#include "graphics/render/ChunksRenderer.hpp"
|
||||||
#include "logic/scripting/scripting.hpp"
|
#include "logic/scripting/scripting.hpp"
|
||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "objects/Entities.hpp"
|
#include "objects/Entities.hpp"
|
||||||
@@ -95,7 +96,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
}));
|
}));
|
||||||
panel->add(create_label([=]() {
|
panel->add(create_label([=]() {
|
||||||
return L"chunks: "+std::to_wstring(level->chunks->getChunksCount())+
|
return L"chunks: "+std::to_wstring(level->chunks->getChunksCount())+
|
||||||
L" visible: "+std::to_wstring(level->chunks->visible);
|
L" visible: "+std::to_wstring(ChunksRenderer::visibleChunks);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([=]() {
|
panel->add(create_label([=]() {
|
||||||
return L"entities: "+std::to_wstring(level->entities->size())+L" next: "+
|
return L"entities: "+std::to_wstring(level->entities->size())+L" next: "+
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
#include "ChunksRenderer.hpp"
|
#include "ChunksRenderer.hpp"
|
||||||
#include "BlocksRenderer.hpp"
|
#include "BlocksRenderer.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
|
#include "assets/Assets.hpp"
|
||||||
#include "graphics/core/Mesh.hpp"
|
#include "graphics/core/Mesh.hpp"
|
||||||
|
#include "graphics/core/Shader.hpp"
|
||||||
|
#include "graphics/core/Texture.hpp"
|
||||||
|
#include "graphics/core/Atlas.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
|
#include "voxels/Chunks.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
|
#include "window/Camera.hpp"
|
||||||
|
#include "maths/FrustumCulling.hpp"
|
||||||
|
#include "util/listutil.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -12,6 +20,8 @@
|
|||||||
|
|
||||||
static debug::Logger logger("chunks-render");
|
static debug::Logger logger("chunks-render");
|
||||||
|
|
||||||
|
size_t ChunksRenderer::visibleChunks = 0;
|
||||||
|
|
||||||
class RendererWorker : public util::Worker<std::shared_ptr<Chunk>, RendererResult> {
|
class RendererWorker : public util::Worker<std::shared_ptr<Chunk>, RendererResult> {
|
||||||
Level* level;
|
Level* level;
|
||||||
BlocksRenderer renderer;
|
BlocksRenderer renderer;
|
||||||
@@ -39,9 +49,14 @@ public:
|
|||||||
|
|
||||||
ChunksRenderer::ChunksRenderer(
|
ChunksRenderer::ChunksRenderer(
|
||||||
Level* level,
|
Level* level,
|
||||||
|
const Assets& assets,
|
||||||
|
const Frustum& frustum,
|
||||||
const ContentGfxCache* cache,
|
const ContentGfxCache* cache,
|
||||||
const EngineSettings* settings
|
const EngineSettings* settings
|
||||||
) : level(level),
|
) : level(level),
|
||||||
|
assets(assets),
|
||||||
|
frustum(frustum),
|
||||||
|
settings(settings),
|
||||||
threadPool(
|
threadPool(
|
||||||
"chunks-render-pool",
|
"chunks-render-pool",
|
||||||
[=](){return std::make_shared<RendererWorker>(level, cache, settings);},
|
[=](){return std::make_shared<RendererWorker>(level, cache, settings);},
|
||||||
@@ -103,14 +118,84 @@ std::shared_ptr<Mesh> ChunksRenderer::getOrRender(const std::shared_ptr<Chunk>&
|
|||||||
return found->second;
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Mesh> ChunksRenderer::get(Chunk* chunk) {
|
|
||||||
auto found = meshes.find(glm::ivec2(chunk->x, chunk->z));
|
|
||||||
if (found != meshes.end()) {
|
|
||||||
return found->second;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChunksRenderer::update() {
|
void ChunksRenderer::update() {
|
||||||
threadPool.update();
|
threadPool.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChunksRenderer::drawChunk(
|
||||||
|
size_t index, const Camera& camera, Shader& shader, bool culling
|
||||||
|
) {
|
||||||
|
auto chunk = level->chunks->getChunks()[index];
|
||||||
|
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
float distance = glm::distance(
|
||||||
|
camera.position,
|
||||||
|
glm::vec3(
|
||||||
|
(chunk->x + 0.5f) * CHUNK_W,
|
||||||
|
camera.position.y,
|
||||||
|
(chunk->z + 0.5f) * CHUNK_D
|
||||||
|
)
|
||||||
|
);
|
||||||
|
auto mesh = getOrRender(chunk, distance < CHUNK_W * 1.5f);
|
||||||
|
if (mesh == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (culling) {
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!frustum.isBoxVisible(min, max)) return false;
|
||||||
|
}
|
||||||
|
glm::vec3 coord(chunk->x * CHUNK_W + 0.5f, 0.5f, chunk->z * CHUNK_D + 0.5f);
|
||||||
|
glm::mat4 model = glm::translate(glm::mat4(1.0f), coord);
|
||||||
|
shader.uniformMatrix("u_model", model);
|
||||||
|
mesh->draw();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChunksRenderer::drawChunks(
|
||||||
|
const Camera& camera, Shader& shader
|
||||||
|
) {
|
||||||
|
const auto& chunks = *level->chunks;
|
||||||
|
const auto& atlas = assets.require<Atlas>("blocks");
|
||||||
|
|
||||||
|
atlas.getTexture()->bind();
|
||||||
|
update();
|
||||||
|
|
||||||
|
// [warning] this whole method is not thread-safe for chunks
|
||||||
|
|
||||||
|
int chunksWidth = chunks.getWidth();
|
||||||
|
int chunksOffsetX = chunks.getOffsetX();
|
||||||
|
int chunksOffsetY = chunks.getOffsetY();
|
||||||
|
|
||||||
|
if (indices.size() != chunks.getVolume()) {
|
||||||
|
indices.clear();
|
||||||
|
for (int i = 0; i < chunks.getVolume(); i++) {
|
||||||
|
indices.push_back(ChunksSortEntry {i, 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float px = camera.position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
||||||
|
float pz = camera.position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
||||||
|
for (auto& index : indices) {
|
||||||
|
float x = index.index % chunksWidth + chunksOffsetX - px;
|
||||||
|
float z = index.index / chunksWidth + chunksOffsetY - pz;
|
||||||
|
index.d = (x * x + z * z) * 1024;
|
||||||
|
}
|
||||||
|
util::insertion_sort(indices.begin(), indices.end());
|
||||||
|
|
||||||
|
bool culling = settings->graphics.frustumCulling.get();
|
||||||
|
|
||||||
|
visibleChunks = 0;
|
||||||
|
//if (GLEW_ARB_multi_draw_indirect && false) {
|
||||||
|
// TODO: implement Multi Draw Indirect chunks draw
|
||||||
|
//} else {
|
||||||
|
for (size_t i = 0; i < indices.size(); i++) {
|
||||||
|
visibleChunks += drawChunk(indices[i].index, camera, shader, culling);
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,10 +14,24 @@
|
|||||||
class Mesh;
|
class Mesh;
|
||||||
class Chunk;
|
class Chunk;
|
||||||
class Level;
|
class Level;
|
||||||
|
class Camera;
|
||||||
|
class Shader;
|
||||||
|
class Chunks;
|
||||||
|
class Assets;
|
||||||
|
class Frustum;
|
||||||
class BlocksRenderer;
|
class BlocksRenderer;
|
||||||
class ContentGfxCache;
|
class ContentGfxCache;
|
||||||
struct EngineSettings;
|
struct EngineSettings;
|
||||||
|
|
||||||
|
struct ChunksSortEntry {
|
||||||
|
int index;
|
||||||
|
int d;
|
||||||
|
|
||||||
|
inline bool operator<(const ChunksSortEntry& o) const noexcept {
|
||||||
|
return d > o.d;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct RendererResult {
|
struct RendererResult {
|
||||||
glm::ivec2 key;
|
glm::ivec2 key;
|
||||||
bool cancelled;
|
bool cancelled;
|
||||||
@@ -26,25 +40,41 @@ struct RendererResult {
|
|||||||
|
|
||||||
class ChunksRenderer {
|
class ChunksRenderer {
|
||||||
Level* level;
|
Level* level;
|
||||||
|
const Assets& assets;
|
||||||
|
const Frustum& frustum;
|
||||||
|
const EngineSettings* settings;
|
||||||
std::unique_ptr<BlocksRenderer> renderer;
|
std::unique_ptr<BlocksRenderer> renderer;
|
||||||
std::unordered_map<glm::ivec2, std::shared_ptr<Mesh>> meshes;
|
std::unordered_map<glm::ivec2, std::shared_ptr<Mesh>> meshes;
|
||||||
std::unordered_map<glm::ivec2, bool> inwork;
|
std::unordered_map<glm::ivec2, bool> inwork;
|
||||||
|
std::vector<ChunksSortEntry> indices;
|
||||||
|
|
||||||
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;
|
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;
|
||||||
|
|
||||||
|
bool drawChunk(
|
||||||
|
size_t index, const Camera& camera, Shader& shader, bool culling
|
||||||
|
);
|
||||||
public:
|
public:
|
||||||
ChunksRenderer(
|
ChunksRenderer(
|
||||||
Level* level,
|
Level* level,
|
||||||
|
const Assets& assets,
|
||||||
|
const Frustum& frustum,
|
||||||
const ContentGfxCache* cache,
|
const ContentGfxCache* cache,
|
||||||
const EngineSettings* settings
|
const EngineSettings* settings
|
||||||
);
|
);
|
||||||
virtual ~ChunksRenderer();
|
virtual ~ChunksRenderer();
|
||||||
|
|
||||||
std::shared_ptr<Mesh> render(const std::shared_ptr<Chunk>& chunk, bool important);
|
std::shared_ptr<Mesh> render(
|
||||||
|
const std::shared_ptr<Chunk>& chunk, bool important
|
||||||
|
);
|
||||||
void unload(const Chunk* chunk);
|
void unload(const Chunk* chunk);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
std::shared_ptr<Mesh> getOrRender(const std::shared_ptr<Chunk>& chunk, bool important);
|
std::shared_ptr<Mesh> getOrRender(
|
||||||
std::shared_ptr<Mesh> get(Chunk* chunk);
|
const std::shared_ptr<Chunk>& chunk, bool important
|
||||||
|
);
|
||||||
|
void drawChunks(const Camera& camera, Shader& shader);
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
static size_t visibleChunks;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ static glm::mat4 extract_rotation(glm::mat4 matrix) {
|
|||||||
|
|
||||||
ModelBatch::ModelBatch(
|
ModelBatch::ModelBatch(
|
||||||
size_t capacity,
|
size_t capacity,
|
||||||
Assets* assets,
|
const Assets& assets,
|
||||||
Chunks* chunks,
|
const Chunks& chunks,
|
||||||
const EngineSettings* settings
|
const EngineSettings& settings
|
||||||
)
|
)
|
||||||
: batch(std::make_unique<MainBatch>(capacity)),
|
: batch(std::make_unique<MainBatch>(capacity)),
|
||||||
assets(assets),
|
assets(assets),
|
||||||
@@ -73,7 +73,7 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix,
|
|||||||
if (mesh.lighting) {
|
if (mesh.lighting) {
|
||||||
glm::vec3 gpos = matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
glm::vec3 gpos = matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
gpos += lightsOffset;
|
gpos += lightsOffset;
|
||||||
lights = MainBatch::sampleLight(gpos, *chunks, backlight);
|
lights = MainBatch::sampleLight(gpos, chunks, backlight);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < vcount / 3; i++) {
|
for (size_t i = 0; i < vcount / 3; i++) {
|
||||||
batch->prepare(3);
|
batch->prepare(3);
|
||||||
@@ -107,7 +107,7 @@ void ModelBatch::render() {
|
|||||||
return a.mesh->texture < b.mesh->texture;
|
return a.mesh->texture < b.mesh->texture;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
bool backlight = settings->graphics.backlight.get();
|
bool backlight = settings.graphics.backlight.get();
|
||||||
for (auto& entry : entries) {
|
for (auto& entry : entries) {
|
||||||
draw(
|
draw(
|
||||||
*entry.mesh,
|
*entry.mesh,
|
||||||
@@ -136,6 +136,6 @@ void ModelBatch::setTexture(const std::string& name,
|
|||||||
return setTexture(found->second, varTextures);
|
return setTexture(found->second, varTextures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto region = util::get_texture_region(*assets, name, "blocks:notfound");
|
auto region = util::get_texture_region(assets, name, "blocks:notfound");
|
||||||
batch->setTexture(region.texture, region.region);
|
batch->setTexture(region.texture, region.region);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ namespace model {
|
|||||||
using texture_names_map = std::unordered_map<std::string, std::string>;
|
using texture_names_map = std::unordered_map<std::string, std::string>;
|
||||||
|
|
||||||
class ModelBatch {
|
class ModelBatch {
|
||||||
Assets* assets;
|
const Assets& assets;
|
||||||
Chunks* chunks;
|
const Chunks& chunks;
|
||||||
|
|
||||||
const EngineSettings* settings;
|
const EngineSettings& settings;
|
||||||
glm::vec3 lightsOffset {};
|
glm::vec3 lightsOffset {};
|
||||||
|
|
||||||
static inline glm::vec3 SUN_VECTOR {0.411934f, 0.863868f, -0.279161f};
|
static inline glm::vec3 SUN_VECTOR {0.411934f, 0.863868f, -0.279161f};
|
||||||
@@ -39,6 +39,7 @@ class ModelBatch {
|
|||||||
glm::vec3 tint,
|
glm::vec3 tint,
|
||||||
const texture_names_map* varTextures,
|
const texture_names_map* varTextures,
|
||||||
bool backlight);
|
bool backlight);
|
||||||
|
|
||||||
void setTexture(const std::string& name,
|
void setTexture(const std::string& name,
|
||||||
const texture_names_map* varTextures);
|
const texture_names_map* varTextures);
|
||||||
|
|
||||||
@@ -53,9 +54,9 @@ class ModelBatch {
|
|||||||
public:
|
public:
|
||||||
ModelBatch(
|
ModelBatch(
|
||||||
size_t capacity,
|
size_t capacity,
|
||||||
Assets* assets,
|
const Assets& assets,
|
||||||
Chunks* chunks,
|
const Chunks& chunks,
|
||||||
const EngineSettings* settings
|
const EngineSettings& settings
|
||||||
);
|
);
|
||||||
~ModelBatch();
|
~ModelBatch();
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,15 @@
|
|||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "presets/NotePreset.hpp"
|
#include "presets/NotePreset.hpp"
|
||||||
|
|
||||||
TextsRenderer::TextsRenderer(const Frustum* frustum) : frustum(frustum) {
|
TextsRenderer::TextsRenderer(
|
||||||
|
Batch3D& batch, const Assets& assets, const Frustum& frustum
|
||||||
|
)
|
||||||
|
: batch(batch), assets(assets), frustum(frustum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextsRenderer::renderText(
|
void TextsRenderer::renderText(
|
||||||
Batch3D& batch,
|
|
||||||
const TextNote& note,
|
const TextNote& note,
|
||||||
const DrawContext& context,
|
const DrawContext& context,
|
||||||
const Assets& assets,
|
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
const EngineSettings& settings,
|
const EngineSettings& settings,
|
||||||
bool hudVisible
|
bool hudVisible
|
||||||
@@ -54,8 +55,8 @@ void TextsRenderer::renderText(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (preset.displayMode != NoteDisplayMode::PROJECTED) {
|
if (preset.displayMode != NoteDisplayMode::PROJECTED) {
|
||||||
if (!frustum->isBoxVisible(pos - xvec * (width * 0.5f),
|
if (!frustum.isBoxVisible(pos - xvec * (width * 0.5f),
|
||||||
pos + xvec * (width * 0.5f))) {
|
pos + xvec * (width * 0.5f))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,9 +72,7 @@ void TextsRenderer::renderText(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextsRenderer::renderTexts(
|
void TextsRenderer::renderTexts(
|
||||||
Batch3D& batch,
|
|
||||||
const DrawContext& context,
|
const DrawContext& context,
|
||||||
const Assets& assets,
|
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
const EngineSettings& settings,
|
const EngineSettings& settings,
|
||||||
bool hudVisible,
|
bool hudVisible,
|
||||||
@@ -96,9 +95,8 @@ void TextsRenderer::renderTexts(
|
|||||||
shader.uniformMatrix("u_projview", camera.getProjView());
|
shader.uniformMatrix("u_projview", camera.getProjView());
|
||||||
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
||||||
batch.begin();
|
batch.begin();
|
||||||
|
|
||||||
for (const auto& note : notes) {
|
for (const auto& note : notes) {
|
||||||
renderText(batch, note, context, assets, camera, settings, hudVisible);
|
renderText(note, context, camera, settings, hudVisible);
|
||||||
}
|
}
|
||||||
batch.flush();
|
batch.flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,24 +9,22 @@ class TextNote;
|
|||||||
struct EngineSettings;
|
struct EngineSettings;
|
||||||
|
|
||||||
class TextsRenderer {
|
class TextsRenderer {
|
||||||
const Frustum* frustum;
|
Batch3D& batch;
|
||||||
|
const Assets& assets;
|
||||||
|
const Frustum& frustum;
|
||||||
|
|
||||||
void renderText(
|
void renderText(
|
||||||
Batch3D& batch,
|
|
||||||
const TextNote& note,
|
const TextNote& note,
|
||||||
const DrawContext& context,
|
const DrawContext& context,
|
||||||
const Assets& assets,
|
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
const EngineSettings& settings,
|
const EngineSettings& settings,
|
||||||
bool hudVisible
|
bool hudVisible
|
||||||
);
|
);
|
||||||
public:
|
public:
|
||||||
TextsRenderer(const Frustum* frustum);
|
TextsRenderer(Batch3D& batch, const Assets& assets, const Frustum& frustum);
|
||||||
|
|
||||||
void renderTexts(
|
void renderTexts(
|
||||||
Batch3D& batch,
|
|
||||||
const DrawContext& context,
|
const DrawContext& context,
|
||||||
const Assets& assets,
|
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
const EngineSettings& settings,
|
const EngineSettings& settings,
|
||||||
bool hudVisible,
|
bool hudVisible,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include "maths/voxmaths.hpp"
|
#include "maths/voxmaths.hpp"
|
||||||
#include "objects/Entities.hpp"
|
#include "objects/Entities.hpp"
|
||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "util/listutil.hpp"
|
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
@@ -51,6 +50,9 @@
|
|||||||
#include "Emitter.hpp"
|
#include "Emitter.hpp"
|
||||||
#include "TextNote.hpp"
|
#include "TextNote.hpp"
|
||||||
|
|
||||||
|
inline constexpr size_t BATCH3D_CAPACITY = 4096;
|
||||||
|
inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000;
|
||||||
|
|
||||||
bool WorldRenderer::showChunkBorders = false;
|
bool WorldRenderer::showChunkBorders = false;
|
||||||
bool WorldRenderer::showEntitiesDebug = false;
|
bool WorldRenderer::showEntitiesDebug = false;
|
||||||
|
|
||||||
@@ -60,30 +62,28 @@ WorldRenderer::WorldRenderer(
|
|||||||
: engine(engine),
|
: engine(engine),
|
||||||
level(frontend->getLevel()),
|
level(frontend->getLevel()),
|
||||||
player(player),
|
player(player),
|
||||||
|
assets(*engine->getAssets()),
|
||||||
frustumCulling(std::make_unique<Frustum>()),
|
frustumCulling(std::make_unique<Frustum>()),
|
||||||
lineBatch(std::make_unique<LineBatch>()),
|
lineBatch(std::make_unique<LineBatch>()),
|
||||||
|
batch3d(std::make_unique<Batch3D>(BATCH3D_CAPACITY)),
|
||||||
modelBatch(std::make_unique<ModelBatch>(
|
modelBatch(std::make_unique<ModelBatch>(
|
||||||
20'000,
|
MODEL_BATCH_CAPACITY, assets, *level->chunks, engine->getSettings()
|
||||||
engine->getAssets(),
|
|
||||||
level->chunks.get(),
|
|
||||||
&engine->getSettings()
|
|
||||||
)),
|
)),
|
||||||
particles(std::make_unique<ParticlesRenderer>(
|
particles(std::make_unique<ParticlesRenderer>(
|
||||||
*engine->getAssets(),
|
assets, *level, &engine->getSettings().graphics
|
||||||
*frontend->getLevel(),
|
|
||||||
&engine->getSettings().graphics
|
|
||||||
)),
|
)),
|
||||||
texts(std::make_unique<TextsRenderer>(frustumCulling.get())),
|
texts(std::make_unique<TextsRenderer>(
|
||||||
guides(std::make_unique<GuidesRenderer>()) {
|
*batch3d, assets, *frustumCulling
|
||||||
renderer = std::make_unique<ChunksRenderer>(
|
)),
|
||||||
level, frontend->getContentGfxCache(), &engine->getSettings()
|
guides(std::make_unique<GuidesRenderer>()),
|
||||||
);
|
chunks(std::make_unique<ChunksRenderer>(
|
||||||
batch3d = std::make_unique<Batch3D>(4096);
|
level, assets, *frustumCulling, frontend->getContentGfxCache(), &engine->getSettings()
|
||||||
|
))
|
||||||
|
{
|
||||||
auto& settings = engine->getSettings();
|
auto& settings = engine->getSettings();
|
||||||
level->events->listen(
|
level->events->listen(
|
||||||
EVT_CHUNK_HIDDEN,
|
EVT_CHUNK_HIDDEN,
|
||||||
[this](lvl_event_type, Chunk* chunk) { renderer->unload(chunk); }
|
[this](lvl_event_type, Chunk* chunk) { chunks->unload(chunk); }
|
||||||
);
|
);
|
||||||
auto assets = engine->getAssets();
|
auto assets = engine->getAssets();
|
||||||
skybox = std::make_unique<Skybox>(
|
skybox = std::make_unique<Skybox>(
|
||||||
@@ -94,87 +94,6 @@ WorldRenderer::WorldRenderer(
|
|||||||
|
|
||||||
WorldRenderer::~WorldRenderer() = default;
|
WorldRenderer::~WorldRenderer() = default;
|
||||||
|
|
||||||
bool WorldRenderer::drawChunk(
|
|
||||||
size_t index, const Camera& camera, Shader& shader, bool culling
|
|
||||||
) {
|
|
||||||
auto chunk = level->chunks->getChunks()[index];
|
|
||||||
if (chunk == nullptr || !chunk->flags.lighted) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
float distance = glm::distance(
|
|
||||||
camera.position,
|
|
||||||
glm::vec3(
|
|
||||||
(chunk->x + 0.5f) * CHUNK_W,
|
|
||||||
camera.position.y,
|
|
||||||
(chunk->z + 0.5f) * CHUNK_D
|
|
||||||
)
|
|
||||||
);
|
|
||||||
auto mesh = renderer->getOrRender(chunk, distance < CHUNK_W * 1.5f);
|
|
||||||
if (mesh == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (culling) {
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!frustumCulling->isBoxVisible(min, max)) return false;
|
|
||||||
}
|
|
||||||
glm::vec3 coord(chunk->x * CHUNK_W + 0.5f, 0.5f, chunk->z * CHUNK_D + 0.5f);
|
|
||||||
glm::mat4 model = glm::translate(glm::mat4(1.0f), coord);
|
|
||||||
shader.uniformMatrix("u_model", model);
|
|
||||||
mesh->draw();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldRenderer::drawChunks(
|
|
||||||
Chunks* chunks, const Camera& camera, Shader& shader
|
|
||||||
) {
|
|
||||||
auto assets = engine->getAssets();
|
|
||||||
auto atlas = assets->get<Atlas>("blocks");
|
|
||||||
|
|
||||||
atlas->getTexture()->bind();
|
|
||||||
renderer->update();
|
|
||||||
|
|
||||||
// [warning] this whole method is not thread-safe for chunks
|
|
||||||
|
|
||||||
int chunksWidth = chunks->getWidth();
|
|
||||||
int chunksOffsetX = chunks->getOffsetX();
|
|
||||||
int chunksOffsetY = chunks->getOffsetY();
|
|
||||||
|
|
||||||
if (indices.size() != chunks->getVolume()) {
|
|
||||||
indices.clear();
|
|
||||||
for (int i = 0; i < chunks->getVolume(); i++) {
|
|
||||||
indices.push_back(ChunksSortEntry {i, 0});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float px = camera.position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
|
||||||
float pz = camera.position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
|
||||||
for (auto& index : indices) {
|
|
||||||
float x = index.index % chunksWidth + chunksOffsetX - px;
|
|
||||||
float z = index.index / chunksWidth + chunksOffsetY - pz;
|
|
||||||
index.d = (x * x + z * z) * 1024;
|
|
||||||
}
|
|
||||||
util::insertion_sort(indices.begin(), indices.end());
|
|
||||||
|
|
||||||
bool culling = engine->getSettings().graphics.frustumCulling.get();
|
|
||||||
if (culling) {
|
|
||||||
frustumCulling->update(camera.getProjView());
|
|
||||||
}
|
|
||||||
|
|
||||||
chunks->visible = 0;
|
|
||||||
if (GLEW_ARB_multi_draw_indirect && false) {
|
|
||||||
// TODO: implement Multi Draw Indirect chunks draw
|
|
||||||
} else {
|
|
||||||
for (size_t i = 0; i < indices.size(); i++) {
|
|
||||||
chunks->visible += drawChunk(indices[i].index, camera, shader, culling);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldRenderer::setupWorldShader(
|
void WorldRenderer::setupWorldShader(
|
||||||
Shader& shader,
|
Shader& shader,
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
@@ -219,11 +138,7 @@ void WorldRenderer::renderLevel(
|
|||||||
bool pause,
|
bool pause,
|
||||||
bool hudVisible
|
bool hudVisible
|
||||||
) {
|
) {
|
||||||
const auto& assets = *engine->getAssets();
|
texts->renderTexts(ctx, camera, settings, hudVisible, false);
|
||||||
|
|
||||||
texts->renderTexts(
|
|
||||||
*batch3d, ctx, assets, camera, settings, hudVisible, false
|
|
||||||
);
|
|
||||||
|
|
||||||
bool culling = engine->getSettings().graphics.frustumCulling.get();
|
bool culling = engine->getSettings().graphics.frustumCulling.get();
|
||||||
float fogFactor =
|
float fogFactor =
|
||||||
@@ -233,6 +148,10 @@ void WorldRenderer::renderLevel(
|
|||||||
setupWorldShader(entityShader, camera, settings, fogFactor);
|
setupWorldShader(entityShader, camera, settings, fogFactor);
|
||||||
skybox->bind();
|
skybox->bind();
|
||||||
|
|
||||||
|
if (culling) {
|
||||||
|
frustumCulling->update(camera.getProjView());
|
||||||
|
}
|
||||||
|
|
||||||
level->entities->render(
|
level->entities->render(
|
||||||
assets,
|
assets,
|
||||||
*modelBatch,
|
*modelBatch,
|
||||||
@@ -246,7 +165,7 @@ void WorldRenderer::renderLevel(
|
|||||||
auto& shader = assets.require<Shader>("main");
|
auto& shader = assets.require<Shader>("main");
|
||||||
setupWorldShader(shader, camera, settings, fogFactor);
|
setupWorldShader(shader, camera, settings, fogFactor);
|
||||||
|
|
||||||
drawChunks(level->chunks.get(), camera, shader);
|
chunks->drawChunks(camera, shader);
|
||||||
|
|
||||||
if (!pause) {
|
if (!pause) {
|
||||||
scripting::on_frontend_render();
|
scripting::on_frontend_render();
|
||||||
@@ -302,7 +221,7 @@ void WorldRenderer::renderLines(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldRenderer::renderHands(
|
void WorldRenderer::renderHands(
|
||||||
const Camera& camera, const Assets& assets, float delta
|
const Camera& camera, float delta
|
||||||
) {
|
) {
|
||||||
auto& entityShader = assets.require<Shader>("entity");
|
auto& entityShader = assets.require<Shader>("entity");
|
||||||
auto indices = level->content->getIndices();
|
auto indices = level->content->getIndices();
|
||||||
@@ -408,11 +327,11 @@ void WorldRenderer::draw(
|
|||||||
}
|
}
|
||||||
renderLines(camera, linesShader, ctx);
|
renderLines(camera, linesShader, ctx);
|
||||||
if (player->currentCamera == player->fpCamera) {
|
if (player->currentCamera == player->fpCamera) {
|
||||||
renderHands(camera, assets, delta * !pause);
|
renderHands(camera, delta * !pause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderBlockOverlay(wctx, assets);
|
renderBlockOverlay(wctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rendering fullscreen quad with
|
// Rendering fullscreen quad with
|
||||||
@@ -423,7 +342,7 @@ void WorldRenderer::draw(
|
|||||||
postProcessing->render(pctx, screenShader);
|
postProcessing->render(pctx, screenShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldRenderer::renderBlockOverlay(const DrawContext& wctx, const Assets& assets) {
|
void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) {
|
||||||
int x = std::floor(player->currentCamera->position.x);
|
int x = std::floor(player->currentCamera->position.x);
|
||||||
int y = std::floor(player->currentCamera->position.y);
|
int y = std::floor(player->currentCamera->position.y);
|
||||||
int z = std::floor(player->currentCamera->position.z);
|
int z = std::floor(player->currentCamera->position.z);
|
||||||
@@ -469,5 +388,5 @@ void WorldRenderer::renderBlockOverlay(const DrawContext& wctx, const Assets& as
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldRenderer::clear() {
|
void WorldRenderer::clear() {
|
||||||
renderer->clear();
|
chunks->clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ class TextsRenderer;
|
|||||||
class Shader;
|
class Shader;
|
||||||
class Frustum;
|
class Frustum;
|
||||||
class Engine;
|
class Engine;
|
||||||
class Chunks;
|
|
||||||
class LevelFrontend;
|
class LevelFrontend;
|
||||||
class Skybox;
|
class Skybox;
|
||||||
class PostProcessing;
|
class PostProcessing;
|
||||||
@@ -36,39 +35,26 @@ namespace model {
|
|||||||
struct Model;
|
struct Model;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChunksSortEntry {
|
|
||||||
int index;
|
|
||||||
int d;
|
|
||||||
|
|
||||||
inline bool operator<(const ChunksSortEntry& o) const noexcept {
|
|
||||||
return d > o.d;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class WorldRenderer {
|
class WorldRenderer {
|
||||||
Engine* engine;
|
Engine* engine;
|
||||||
Level* level;
|
Level* level;
|
||||||
Player* player;
|
Player* player;
|
||||||
|
const Assets& assets;
|
||||||
std::unique_ptr<Frustum> frustumCulling;
|
std::unique_ptr<Frustum> frustumCulling;
|
||||||
std::unique_ptr<LineBatch> lineBatch;
|
std::unique_ptr<LineBatch> lineBatch;
|
||||||
std::unique_ptr<ChunksRenderer> renderer;
|
std::unique_ptr<Batch3D> batch3d;
|
||||||
|
std::unique_ptr<ChunksRenderer> chunks;
|
||||||
std::unique_ptr<TextsRenderer> texts;
|
std::unique_ptr<TextsRenderer> texts;
|
||||||
std::unique_ptr<GuidesRenderer> guides;
|
std::unique_ptr<GuidesRenderer> guides;
|
||||||
std::unique_ptr<Skybox> skybox;
|
std::unique_ptr<Skybox> skybox;
|
||||||
std::unique_ptr<Batch3D> batch3d;
|
|
||||||
std::unique_ptr<ModelBatch> modelBatch;
|
std::unique_ptr<ModelBatch> modelBatch;
|
||||||
|
|
||||||
std::vector<ChunksSortEntry> indices;
|
|
||||||
|
|
||||||
float timer = 0.0f;
|
float timer = 0.0f;
|
||||||
|
|
||||||
bool drawChunk(size_t index, const Camera& camera, Shader& shader, bool culling);
|
|
||||||
void drawChunks(Chunks* chunks, const Camera& camera, Shader& shader);
|
|
||||||
|
|
||||||
/// @brief Render block selection lines
|
/// @brief Render block selection lines
|
||||||
void renderBlockSelection();
|
void renderBlockSelection();
|
||||||
|
|
||||||
void renderHands(const Camera& camera, const Assets& assets, float delta);
|
void renderHands(const Camera& camera, float delta);
|
||||||
|
|
||||||
/// @brief Render lines (selection and debug)
|
/// @brief Render lines (selection and debug)
|
||||||
/// @param camera active camera
|
/// @param camera active camera
|
||||||
@@ -77,7 +63,7 @@ class WorldRenderer {
|
|||||||
const Camera& camera, Shader& linesShader, const DrawContext& pctx
|
const Camera& camera, Shader& linesShader, const DrawContext& pctx
|
||||||
);
|
);
|
||||||
|
|
||||||
void renderBlockOverlay(const DrawContext& context, const Assets& assets);
|
void renderBlockOverlay(const DrawContext& context);
|
||||||
|
|
||||||
void setupWorldShader(
|
void setupWorldShader(
|
||||||
Shader& shader,
|
Shader& shader,
|
||||||
|
|||||||
@@ -40,10 +40,8 @@ class Chunks {
|
|||||||
);
|
);
|
||||||
|
|
||||||
util::AreaMap2D<std::shared_ptr<Chunk>, int32_t> areaMap;
|
util::AreaMap2D<std::shared_ptr<Chunk>, int32_t> areaMap;
|
||||||
public:
|
|
||||||
size_t visible = 0;
|
|
||||||
WorldFiles* worldFiles;
|
WorldFiles* worldFiles;
|
||||||
|
public:
|
||||||
Chunks(
|
Chunks(
|
||||||
int32_t w,
|
int32_t w,
|
||||||
int32_t d,
|
int32_t d,
|
||||||
|
|||||||
Reference in New Issue
Block a user