mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-04 18:41:51 +00:00
fix block wraps high draw call count
This commit is contained in:
parent
5e05b44c26
commit
21951770ea
4 changed files with 44 additions and 34 deletions
|
|
@ -8,18 +8,16 @@
|
|||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/render/MainBatch.hpp"
|
||||
#include "lighting/Lightmap.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "voxels/Chunks.hpp"
|
||||
#include "world/Level.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
BlockWrapsRenderer::BlockWrapsRenderer(
|
||||
const Assets& assets, const Level& level, const Chunks& chunks
|
||||
const Assets& assets, const Content& content, const Chunks& chunks
|
||||
)
|
||||
: assets(assets),
|
||||
level(level),
|
||||
content(content),
|
||||
chunks(chunks),
|
||||
batch(std::make_unique<MainBatch>(1024)) {
|
||||
}
|
||||
|
|
@ -43,16 +41,14 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) {
|
|||
}
|
||||
|
||||
const voxel* vox = chunks.get(wrapper.position);
|
||||
if (vox == nullptr || vox->id == BLOCK_VOID) {
|
||||
if (vox == nullptr || vox->id == BLOCK_AIR) {
|
||||
return;
|
||||
}
|
||||
// one frame can be invalid due to texture change but ok
|
||||
const auto& def =
|
||||
level.content.getIndices()->blocks.require(vox->id);
|
||||
const auto& def = content.getIndices()->blocks.require(vox->id);
|
||||
|
||||
if (wrapper.modelType != def.getModel(vox->state.userbits).type) {
|
||||
wrapper.dirtySides = 0xFF;
|
||||
refreshWrapper(wrapper);
|
||||
}
|
||||
glm::vec4 light(1, 1, 1, 0);
|
||||
if (wrapper.emission < 1.0f) {
|
||||
|
|
@ -95,6 +91,8 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) {
|
|||
}
|
||||
|
||||
void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) {
|
||||
clearOrder(&wrapper);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if ((wrapper.cullingBits & (1 << i)) == 0) {
|
||||
continue;
|
||||
|
|
@ -104,15 +102,19 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) {
|
|||
wrapper.texRegions[i] = texRegion;
|
||||
wrapper.uvRegions[i] = texRegion.region;
|
||||
|
||||
renderOrder.insert({texRegion.texture, &wrapper});
|
||||
auto& wrappers = renderOrder[texRegion.texture];
|
||||
if (std::find(wrappers.begin(), wrappers.end(), &wrapper) ==
|
||||
wrappers.end()) {
|
||||
wrappers.emplace_back(&wrapper);
|
||||
}
|
||||
}
|
||||
wrapper.dirtySides = 0x0;
|
||||
|
||||
const voxel* vox = chunks.get(wrapper.position);
|
||||
if (vox == nullptr || vox->id == BLOCK_VOID) {
|
||||
if (vox == nullptr || vox->id == BLOCK_AIR) {
|
||||
return;
|
||||
}
|
||||
const auto& def = level.content.getIndices()->blocks.require(vox->id);
|
||||
const auto& def = content.getIndices()->blocks.require(vox->id);
|
||||
wrapper.modelType = def.getModel(vox->state.userbits).type;
|
||||
switch (wrapper.modelType) {
|
||||
case BlockModelType::AABB: {
|
||||
|
|
@ -133,7 +135,7 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) {
|
|||
}
|
||||
}
|
||||
|
||||
void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) {
|
||||
void BlockWrapsRenderer::draw(const DrawContext& pctx) {
|
||||
auto ctx = pctx.sub();
|
||||
|
||||
auto& shader = assets.require<Shader>("entity");
|
||||
|
|
@ -146,9 +148,11 @@ void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) {
|
|||
}
|
||||
}
|
||||
|
||||
for (const auto& [texture, wrapper] : renderOrder) {
|
||||
for (const auto& [texture, wrappersArray] : renderOrder) {
|
||||
batch->setTexture(texture);
|
||||
draw(*wrapper, texture);
|
||||
for (auto wrapper : wrappersArray) {
|
||||
draw(*wrapper, texture);
|
||||
}
|
||||
}
|
||||
batch->flush();
|
||||
}
|
||||
|
|
@ -181,15 +185,21 @@ void BlockWrapsRenderer::remove(u64id_t id) {
|
|||
if (found == wrappers.end()) {
|
||||
return;
|
||||
}
|
||||
auto wrapper = std::move(found->second);
|
||||
clearOrder(found->second.get());
|
||||
wrappers.erase(id);
|
||||
}
|
||||
|
||||
void BlockWrapsRenderer::clearOrder(const BlockWrapper* const wrapper) {
|
||||
auto it = renderOrder.begin();
|
||||
while (it != renderOrder.end()) {
|
||||
if (it->second == wrapper.get()) {
|
||||
it->second.erase(
|
||||
std::remove(it->second.begin(), it->second.end(), wrapper),
|
||||
it->second.end()
|
||||
);
|
||||
if (it->second.empty()) {
|
||||
it = renderOrder.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,13 +9,9 @@
|
|||
#include <string>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
class Assets;
|
||||
class Player;
|
||||
class Level;
|
||||
struct voxel;
|
||||
class Content;
|
||||
class Chunks;
|
||||
class Texture;
|
||||
class DrawContext;
|
||||
|
|
@ -36,24 +32,25 @@ struct BlockWrapper {
|
|||
|
||||
class BlockWrapsRenderer {
|
||||
const Assets& assets;
|
||||
const Level& level;
|
||||
const Content& content;
|
||||
const Chunks& chunks;
|
||||
std::unique_ptr<MainBatch> batch;
|
||||
|
||||
std::multimap<const Texture*, BlockWrapper*> renderOrder;
|
||||
std::unordered_map<const Texture*, std::vector<BlockWrapper*>> renderOrder;
|
||||
std::unordered_map<u64id_t, std::unique_ptr<BlockWrapper>> wrappers;
|
||||
u64id_t nextWrapper = 1;
|
||||
|
||||
void draw(BlockWrapper& wrapper, const Texture* texture);
|
||||
|
||||
void refreshWrapper(BlockWrapper& wrapper);
|
||||
void clearOrder(const BlockWrapper* const wrapper);
|
||||
public:
|
||||
BlockWrapsRenderer(
|
||||
const Assets& assets, const Level& level, const Chunks& chunks
|
||||
const Assets& assets, const Content& content, const Chunks& chunks
|
||||
);
|
||||
~BlockWrapsRenderer();
|
||||
|
||||
void draw(const DrawContext& ctx, const Player& player);
|
||||
void draw(const DrawContext& ctx);
|
||||
|
||||
u64id_t add(
|
||||
const glm::ivec3& position,
|
||||
|
|
|
|||
|
|
@ -94,9 +94,9 @@ WorldRenderer::WorldRenderer(
|
|||
assets, level, *player.chunks, engine.getSettings().graphics
|
||||
)),
|
||||
texts(std::make_unique<TextsRenderer>(*batch3d, assets, *frustumCulling)),
|
||||
blockWraps(
|
||||
std::make_unique<BlockWrapsRenderer>(assets, level, *player.chunks)
|
||||
) {
|
||||
blockWraps(std::make_unique<BlockWrapsRenderer>(
|
||||
assets, level.content, *player.chunks
|
||||
)) {
|
||||
auto& settings = engine.getSettings();
|
||||
level.events->listen(
|
||||
LevelEventType::CHUNK_HIDDEN,
|
||||
|
|
@ -214,7 +214,7 @@ void WorldRenderer::renderOpaque(
|
|||
setupWorldShader(shader, camera, settings, fogFactor);
|
||||
|
||||
chunksRenderer->drawChunks(camera, shader);
|
||||
blockWraps->draw(ctx, player);
|
||||
blockWraps->draw(ctx);
|
||||
|
||||
int cloudsQuality = settings.graphics.cloudsQuality.get();
|
||||
if (cloudsQuality > 0) {
|
||||
|
|
|
|||
|
|
@ -34,10 +34,14 @@ static int l_set_pos(lua::State* L) {
|
|||
|
||||
static int l_set_texture(lua::State* L) {
|
||||
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
|
||||
const char* newTexture = lua::require_string(L, 2);
|
||||
|
||||
for (int i = 0; i < wrapper->textureFaces.size(); i++) {
|
||||
wrapper->textureFaces[i] = lua::require_string(L, 2);
|
||||
if (wrapper->textureFaces[i] != newTexture) {
|
||||
wrapper->textureFaces[i] = newTexture;
|
||||
wrapper->dirtySides = 0xFF;
|
||||
}
|
||||
}
|
||||
wrapper->dirtySides = 0xFF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -52,7 +56,7 @@ static int l_set_faces(lua::State* L) {
|
|||
wrapper->dirtySides |= (1 << i);
|
||||
}
|
||||
} else {
|
||||
auto texture = lua::require_string(L, 2 + i);;
|
||||
auto texture = lua::require_string(L, 2 + i);
|
||||
if ((wrapper->cullingBits & (1 << i)) == 0x0
|
||||
|| wrapper->textureFaces[i] != texture) {
|
||||
wrapper->cullingBits |= (1 << i);
|
||||
|
|
@ -73,7 +77,6 @@ static int l_set_tints(lua::State* L) {
|
|||
wrapper->tints[i] = lua::tovec3(L, 2 + i);
|
||||
}
|
||||
}
|
||||
wrapper->dirtySides = 0xFF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue