General refactor

This commit is contained in:
MihailRis
2023-11-30 04:30:40 +03:00
parent de134dc2e5
commit 1d5037893c
27 changed files with 558 additions and 419 deletions
@@ -1,4 +1,4 @@
#include "world_render.h"
#include "WorldRenderer.h"
#include <iostream>
#include <GL/glew.h>
@@ -22,7 +22,7 @@
#include "../world/LevelEvents.h"
#include "../objects/Player.h"
#include "../assets/Assets.h"
#include "../objects/player_control.h"
#include "../logic/PlayerController.h"
#include "../maths/FrustumCulling.h"
#include "../maths/voxmaths.h"
#include "../settings.h"
@@ -32,20 +32,26 @@
using glm::vec3;
using glm::vec4;
using glm::mat4;
using std::string;
using std::shared_ptr;
WorldRenderer::WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache)
: engine(engine), level(level) {
EngineSettings& settings = engine->getSettings();
WorldRenderer::WorldRenderer(Engine* engine,
Level* level,
const ContentGfxCache* cache)
: engine(engine),
level(level),
frustumCulling(new Frustum()),
lineBatch(new LineBatch()),
renderer( new ChunksRenderer(level, cache, engine->getSettings())) {
lineBatch = new LineBatch(4096);
renderer = new ChunksRenderer(level, cache, settings);
frustumCulling = new Frustum();
level->events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) {
renderer->unload(chunk);
});
skybox = new Skybox(64, engine->getAssets()->getShader("skybox_gen"));
level->events->listen(EVT_CHUNK_HIDDEN,
[this](lvl_event_type type, Chunk* chunk) {
renderer->unload(chunk);
}
);
auto assets = engine->getAssets();
skybox = new Skybox(64, assets->getShader("skybox_gen"));
}
WorldRenderer::~WorldRenderer() {
@@ -55,22 +61,30 @@ WorldRenderer::~WorldRenderer() {
delete frustumCulling;
}
bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
shared_ptr<Chunk> chunk = level->chunks->chunks[index];
if (!chunk->isLighted())
bool WorldRenderer::drawChunk(size_t index,
Camera* camera,
Shader* shader,
bool culling){
auto chunk = level->chunks->chunks[index];
if (!chunk->isLighted()) {
return false;
}
shared_ptr<Mesh> mesh = renderer->getOrRender(chunk.get());
if (mesh == nullptr)
if (mesh == nullptr) {
return false;
// Simple frustum culling
if (occlusion){
vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D);
vec3 max(chunk->x * CHUNK_W + CHUNK_W, chunk->top, chunk->z * CHUNK_D + CHUNK_D);
}
if (culling){
vec3 min(chunk->x * CHUNK_W,
chunk->bottom,
chunk->z * CHUNK_D);
vec3 max(chunk->x * CHUNK_W + CHUNK_W,
chunk->top,
chunk->z * CHUNK_D + CHUNK_D);
if (!frustumCulling->IsBoxVisible(min, max)) return false;
}
mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1));
vec3 coord = vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1);
mat4 model = glm::translate(mat4(1.0f), coord);
shader->uniformMatrix("u_model", model);
mesh->draw();
return true;
@@ -78,8 +92,7 @@ bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool
void WorldRenderer::drawChunks(Chunks* chunks,
Camera* camera,
Shader* shader,
bool occlusion) {
Shader* shader) {
std::vector<size_t> indices;
for (size_t i = 0; i < chunks->volume; i++){
shared_ptr<Chunk> chunk = chunks->chunks[i];
@@ -87,25 +100,30 @@ void WorldRenderer::drawChunks(Chunks* chunks,
continue;
indices.push_back(i);
}
float px = camera->position.x / (float)CHUNK_W;
float pz = camera->position.z / (float)CHUNK_D;
std::sort(indices.begin(), indices.end(), [this, chunks, px, pz](size_t i, size_t j) {
shared_ptr<Chunk> a = chunks->chunks[i];
shared_ptr<Chunk> b = chunks->chunks[j];
return ((a->x + 0.5f - px)*(a->x + 0.5f - px) + (a->z + 0.5f - pz)*(a->z + 0.5f - pz) >
(b->x + 0.5f - px)*(b->x + 0.5f - px) + (b->z + 0.5f - pz)*(b->z + 0.5f - pz));
return ((a->x + 0.5f - px)*(a->x + 0.5f - px) +
(a->z + 0.5f - pz)*(a->z + 0.5f - pz)
>
(b->x + 0.5f - px)*(b->x + 0.5f - px) +
(b->z + 0.5f - pz)*(b->z + 0.5f - pz));
});
if (occlusion) frustumCulling->update(camera->getProjView());
bool culling = engine->getSettings().graphics.frustumCulling;
if (culling) {
frustumCulling->update(camera->getProjView());
}
chunks->visible = 0;
for (size_t i = 0; i < indices.size(); i++){
chunks->visible += drawChunk(indices[i], camera, shader, occlusion);
chunks->visible += drawChunk(indices[i], camera, shader, culling);
}
}
void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){
void WorldRenderer::draw(const GfxContext& pctx, Camera* camera){
EngineSettings& settings = engine->getSettings();
skybox->refresh(level->world->daytime,
fmax(1.0f, 18.0f/settings.chunks.loadDistance), 4);
@@ -123,6 +141,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
Window::clearDepth();
Window::viewport(0, 0, displayWidth, displayHeight);
// Drawing background sky plane
Shader* backShader = assets->getShader("background");
backShader->use();
backShader->uniformMatrix("u_view", camera->getView(false));
@@ -137,8 +156,8 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
float fogFactor = 18.0f / (float)settings.chunks.loadDistance;
// Setting up main shader
shader->use();
skybox->bind();
shader->uniformMatrix("u_proj", camera->getProjection());
shader->uniformMatrix("u_view", camera->getView());
shader->uniform1f("u_gamma", 1.0f);
@@ -146,34 +165,37 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve);
shader->uniform3f("u_cameraPos", camera->position);
shader->uniform1i("u_cubemap", 1);
{
blockid_t id = level->player->choosenBlock;
Block* block = contentIds->getBlockDef(id);
assert(block != nullptr);
float multiplier = 0.5f;
shader->uniform3f("u_torchlightColor",
block->emission[0] / 15.0f * multiplier,
block->emission[1] / 15.0f * multiplier,
block->emission[2] / 15.0f * multiplier);
shader->uniform1f("u_torchlightDistance", 6.0f);
}
Block* cblock = contentIds->getBlockDef(level->player->choosenBlock);
assert(cblock != nullptr);
float multiplier = 0.5f;
shader->uniform3f("u_torchlightColor",
cblock->emission[0] / 15.0f * multiplier,
cblock->emission[1] / 15.0f * multiplier,
cblock->emission[2] / 15.0f * multiplier);
shader->uniform1f("u_torchlightDistance", 6.0f);
// Binding main shader textures
skybox->bind();
atlas->getTexture()->bind();
Chunks* chunks = level->chunks;
drawChunks(chunks, camera, shader, occlusion);
drawChunks(level->chunks, camera, shader);
shader->uniformMatrix("u_model", mat4(1.0f));
if (level->playerController->selectedBlockId != -1){
Block* block = contentIds->getBlockDef(level->playerController->selectedBlockId);
// Selected block
if (PlayerController::selectedBlockId != -1){
blockid_t id = PlayerController::selectedBlockId;
Block* block = contentIds->getBlockDef(id);
assert(block != nullptr);
vec3 pos = level->playerController->selectedBlockPosition;
linesShader->use();
linesShader->uniformMatrix("u_projview", camera->getProjView());
lineBatch->lineWidth(2.0f);
const vec3 pos = PlayerController::selectedBlockPosition;
const AABB& hitbox = block->hitbox;
const vec3 center = pos + hitbox.center();
const vec3 size = hitbox.size();
lineBatch->box(center, size + vec3(0.02), vec4(0.0f, 0.0f, 0.0f, 0.5f));
linesShader->use();
linesShader->uniformMatrix("u_projview", camera->getProjView());
lineBatch->lineWidth(2.0f);
lineBatch->box(center, size + vec3(0.02), vec4(0.f, 0.f, 0.f, 0.5f));
lineBatch->render();
}
skybox->unbind();
@@ -191,44 +213,12 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
if (coord.z < 0) coord.z--;
int cx = floordiv((int)coord.x, CHUNK_W);
int cz = floordiv((int)coord.z, CHUNK_D);
/*corner*/ {
lineBatch->line( cx * CHUNK_W, 0, cz * CHUNK_D,
cx * CHUNK_W, CHUNK_H, cz * CHUNK_D, 0.8f, 0, 0.8f, 1);
lineBatch->line( cx * CHUNK_W, 0, (cz+1) * CHUNK_D,
cx * CHUNK_W, CHUNK_H, (cz+1) * CHUNK_D, 0.8f, 0, 0.8f, 1);
lineBatch->line((cx+1) * CHUNK_W, 0, cz * CHUNK_D,
(cx+1) * CHUNK_W, CHUNK_H, cz * CHUNK_D, 0.8f, 0, 0.8f, 1);
lineBatch->line((cx+1) * CHUNK_W, 0, (cz+1) * CHUNK_D,
(cx+1) * CHUNK_W, CHUNK_H, (cz+1) * CHUNK_D, 0.8f, 0, 0.8f, 1);
}
for (int i = 2; i < CHUNK_W; i+=2) {
lineBatch->line( cx * CHUNK_W + i, 0, cz * CHUNK_D,
cx * CHUNK_W + i, CHUNK_H, cz * CHUNK_D, 0, 0, 0.8f, 1);
lineBatch->line( cx * CHUNK_W + i, 0, (cz+1) * CHUNK_D,
cx * CHUNK_W + i, CHUNK_H, (cz+1) * CHUNK_D, 0, 0, 0.8f, 1);
}
for (int i = 2; i < CHUNK_D; i+=2) {
lineBatch->line( cx * CHUNK_W, 0, cz * CHUNK_D + i,
cx * CHUNK_W, CHUNK_H, cz * CHUNK_D + i, 0.8f, 0, 0, 1);
lineBatch->line((cx+1) * CHUNK_W, 0, cz * CHUNK_D + i,
(cx+1) * CHUNK_W, CHUNK_H, cz * CHUNK_D + i, 0.8f, 0, 0, 1);
}
for (int i=0; i < CHUNK_H; i+=2){
lineBatch->line( cx * CHUNK_W, i, cz * CHUNK_D,
cx * CHUNK_W, i, (cz+1) * CHUNK_D, 0, 0.8f, 0, 1);
lineBatch->line( cx * CHUNK_W, i, (cz+1) * CHUNK_D,
(cx+1) * CHUNK_W, i, (cz+1) * CHUNK_D, 0, 0.8f, 0, 1);
lineBatch->line((cx+1) * CHUNK_W, i, (cz+1) * CHUNK_D,
(cx+1) * CHUNK_W, i, cz * CHUNK_D, 0, 0.8f, 0, 1);
lineBatch->line((cx+1) * CHUNK_W, i, cz * CHUNK_D,
cx * CHUNK_W, i, cz * CHUNK_D, 0, 0.8f, 0, 1);
}
lineBatch->render();
drawBorders(cx * CHUNK_W, 0, cz * CHUNK_D,
(cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D);
}
float length = 40.f;
// top-right: vec3 tsl = vec3(displayWidth - length - 4, -length - 4, 0.f);
vec3 tsl = vec3(displayWidth/2, displayHeight/2, 0.f);
glm::mat4 model(glm::translate(glm::mat4(1.f), tsl));
linesShader->uniformMatrix("u_projview", glm::ortho(
@@ -251,3 +241,41 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
lineBatch->render();
}
}
void WorldRenderer::drawBorders(int sx, int sy, int sz, int ex, int ey, int ez) {
int ww = ex-sx;
int dd = ez-sz;
/*corner*/ {
lineBatch->line(sx, sy, sz,
sx, ey, sz, 0.8f, 0, 0.8f, 1);
lineBatch->line(sx, sy, ez,
sx, ey, ez, 0.8f, 0, 0.8f, 1);
lineBatch->line(ex, sy, sz,
ex, ey, sz, 0.8f, 0, 0.8f, 1);
lineBatch->line(ex, sy, ez,
ex, ey, ez, 0.8f, 0, 0.8f, 1);
}
for (int i = 2; i < ww; i+=2) {
lineBatch->line(sx + i, sy, sz,
sx + i, ey, sz, 0, 0, 0.8f, 1);
lineBatch->line(sx + i, sy, ez,
sx + i, ey, ez, 0, 0, 0.8f, 1);
}
for (int i = 2; i < dd; i+=2) {
lineBatch->line(sx, sy, sz + i,
sx, ey, sz + i, 0.8f, 0, 0, 1);
lineBatch->line(ex, sy, sz + i,
ex, ey, sz + i, 0.8f, 0, 0, 1);
}
for (int i = sy; i < ey; i+=2){
lineBatch->line(sx, i, sz,
sx, i, ez, 0, 0.8f, 0, 1);
lineBatch->line(sx, i, ez,
ex, i, ez, 0, 0.8f, 0, 1);
lineBatch->line(ex, i, ez,
ex, i, sz, 0, 0.8f, 0, 1);
lineBatch->line(ex, i, sz,
sx, i, sz, 0, 0.8f, 0, 1);
}
lineBatch->render();
}
@@ -31,14 +31,15 @@ class WorldRenderer {
LineBatch* lineBatch;
ChunksRenderer* renderer;
Skybox* skybox;
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion);
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling);
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader);
public:
WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache);
~WorldRenderer();
void draw(const GfxContext& context, Camera* camera, bool occlusion);
void draw(const GfxContext& context, Camera* camera);
void drawDebug(const GfxContext& context, Camera* camera);
void drawBorders(int sx, int sy, int sz, int ex, int ey, int ez);
};
+6 -5
View File
@@ -35,7 +35,7 @@
#include "gui/GUI.h"
#include "ContentGfxCache.h"
#include "screens.h"
#include "world_render.h"
#include "WorldRenderer.h"
#include "../engine.h"
#include "../core_defs.h"
@@ -81,8 +81,10 @@ HudRenderer::HudRenderer(Engine* engine,
panel->add(shared_ptr<Label>(create_label([this](){
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
})));
panel->add(shared_ptr<Label>(create_label([this](){
return L"occlusion: "+wstring(this->occlusion ? L"on" : L"off");
panel->add(shared_ptr<Label>(create_label([=](){
auto& settings = engine->getSettings();
bool culling = settings.graphics.frustumCulling;
return L"frustum-culling: "+wstring(culling ? L"on" : L"off");
})));
panel->add(shared_ptr<Label>(create_label([this, level]() {
return L"chunks: "+std::to_wstring(this->level->chunks->chunksCount)+
@@ -178,8 +180,7 @@ HudRenderer::~HudRenderer() {
delete uicamera;
}
void HudRenderer::drawDebug(int fps, bool occlusion){
this->occlusion = occlusion;
void HudRenderer::drawDebug(int fps){
this->fps = fps;
fpsMin = min(fps, fpsMin);
fpsMax = max(fps, fpsMax);
+1 -2
View File
@@ -31,7 +31,6 @@ class HudRenderer {
int fpsMin = 60;
int fpsMax = 60;
std::wstring fpsString;
bool occlusion;
bool inventoryOpen = false;
bool pause = false;
@@ -49,7 +48,7 @@ public:
void update();
void drawContentAccess(const GfxContext& ctx, Player* player);
void draw(const GfxContext& context);
void drawDebug(int fps, bool occlusion);
void drawDebug(int fps);
bool isInventoryOpen() const;
bool isPause() const;
+20 -18
View File
@@ -18,18 +18,18 @@
#include "../world/Level.h"
#include "../world/World.h"
#include "../objects/Player.h"
#include "../voxels/ChunksController.h"
#include "../logic/ChunksController.h"
#include "../logic/LevelController.h"
#include "../voxels/Chunks.h"
#include "../voxels/Chunk.h"
#include "world_render.h"
#include "../engine.h"
#include "../util/stringutil.h"
#include "../core_defs.h"
#include "WorldRenderer.h"
#include "hud.h"
#include "ContentGfxCache.h"
#include "gui/GUI.h"
#include "gui/panels.h"
#include "../engine.h"
#include "../util/stringutil.h"
#include "../core_defs.h"
#include "menu.h"
using std::string;
@@ -71,7 +71,7 @@ void MenuScreen::update(float delta) {
void MenuScreen::draw(float delta) {
Window::clear();
Window::setBgColor(vec3(0.2f, 0.2f, 0.2f));
Window::setBgColor(vec3(0.2f));
uicamera->fov = Window::height;
Shader* uishader = engine->getAssets()->getShader("ui");
@@ -88,16 +88,20 @@ void MenuScreen::draw(float delta) {
}
static bool backlight;
LevelScreen::LevelScreen(Engine* engine, Level* level)
: Screen(engine),
level(level) {
auto& settings = engine->getSettings();
controller = new LevelController(settings, level);
cache = new ContentGfxCache(level->content, engine->getAssets());
worldRenderer = new WorldRenderer(engine, level, cache);
hud = new HudRenderer(engine, level, cache, worldRenderer);
backlight = engine->getSettings().graphics.backlight;
backlight = settings.graphics.backlight;
}
LevelScreen::~LevelScreen() {
delete controller;
delete hud;
delete worldRenderer;
delete cache;
@@ -111,8 +115,9 @@ LevelScreen::~LevelScreen() {
}
void LevelScreen::updateHotkeys() {
auto& settings = engine->getSettings();
if (Events::jpressed(keycode::O)) {
occlusion = !occlusion;
settings.graphics.frustumCulling = !settings.graphics.frustumCulling;
}
if (Events::jpressed(keycode::F3)) {
level->player->debug = !level->player->debug;
@@ -124,14 +129,15 @@ void LevelScreen::updateHotkeys() {
void LevelScreen::update(float delta) {
gui::GUI* gui = engine->getGUI();
EngineSettings& settings = engine->getSettings();
bool inputLocked = hud->isPause() ||
hud->isInventoryOpen() ||
gui->isFocusCaught();
if (!gui->isFocusCaught()) {
updateHotkeys();
}
// TODO: subscribe for setting change
EngineSettings& settings = engine->getSettings();
if (settings.graphics.backlight != backlight) {
level->chunks->saveAndClear();
backlight = settings.graphics.backlight;
@@ -139,11 +145,7 @@ void LevelScreen::update(float delta) {
if (!hud->isPause()) {
level->world->updateTimers(delta);
}
level->updatePlayer(delta, !inputLocked, hud->isPause(), !inputLocked);
level->update();
level->chunksController->update(settings.chunks.loadSpeed);
controller->update(delta, !inputLocked, hud->isPause(), !inputLocked);
hud->update();
}
@@ -153,9 +155,9 @@ void LevelScreen::draw(float delta) {
Viewport viewport(Window::width, Window::height);
GfxContext ctx(nullptr, viewport, nullptr);
worldRenderer->draw(ctx, camera, occlusion);
worldRenderer->draw(ctx, camera);
hud->draw(ctx);
if (level->player->debug) {
hud->drawDebug( 1 / delta, occlusion);
hud->drawDebug(1 / delta);
}
}
+2 -1
View File
@@ -12,6 +12,7 @@ class Engine;
class Camera;
class Batch2D;
class ContentGfxCache;
class LevelController;
/* Screen is a mainloop state */
class Screen {
@@ -37,10 +38,10 @@ public:
class LevelScreen : public Screen {
Level* level;
LevelController* controller;
WorldRenderer* worldRenderer;
HudRenderer* hud;
ContentGfxCache* cache;
bool occlusion = true;
void updateHotkeys();
public:
LevelScreen(Engine* engine, Level* level);