diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index e95bedf2..1e72d7fb 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -44,9 +44,9 @@ inline Label* create_label(gui::wstringsupplier supplier) { return label; } -HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), guiController(engine->getGUI()) { +HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), gui(engine->getGUI()) { batch = new Batch2D(1024); - uicamera = new Camera(vec3(), Window::height); + uicamera = new Camera(vec3(), 1); uicamera->perspective = false; uicamera->flipped = true; @@ -139,13 +139,13 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en panel->add(shared_ptr(button)); } panel->visible(false); - guiController->add(this->debugPanel); - guiController->add(this->pauseMenu); + gui->add(this->debugPanel); + gui->add(this->pauseMenu); } HudRenderer::~HudRenderer() { - guiController->remove(debugPanel); - guiController->remove(pauseMenu); + gui->remove(debugPanel); + gui->remove(pauseMenu); delete batch; delete uicamera; } @@ -157,7 +157,11 @@ void HudRenderer::drawDebug(int fps, bool occlusion){ fpsMax = max(fps, fpsMax); } -void HudRenderer::drawInventory(Player* player) { +void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { + const Viewport& viewport = ctx.getViewport(); + const uint width = viewport.getWidth(); + const uint height = viewport.getHeight(); + Texture* blocks = assets->getTexture("block_tex"); uint size = 48; uint step = 64; @@ -165,15 +169,15 @@ void HudRenderer::drawInventory(Player* player) { uint inv_rows = 8; uint inv_w = step*inv_cols + size; uint inv_h = step*inv_rows + size; - int inv_x = (Window::width - (inv_w)) / 2; - int inv_y = (Window::height - (inv_h)) / 2; - int xs = (Window::width - inv_w + step)/2; - int ys = (Window::height - inv_h + step)/2; - if (Window::width > inv_w*3){ - inv_x = (Window::width + (inv_w)) / 2; - inv_y = (Window::height - (inv_h)) / 2; - xs = (Window::width + inv_w + step)/2; - ys = (Window::height - inv_h + step)/2; + int inv_x = (width - (inv_w)) / 2; + int inv_y = (height - (inv_h)) / 2; + int xs = (width - inv_w + step)/2; + int ys = (height - inv_h + step)/2; + if (width > inv_w*3){ + inv_x = (width + (inv_w)) / 2; + inv_y = (height - (inv_h)) / 2; + xs = (width + inv_w + step)/2; + ys = (height - inv_h + step)/2; } vec4 tint = vec4(1.0f); int mx = Events::x; @@ -234,17 +238,18 @@ void HudRenderer::drawInventory(Player* player) { } } -void HudRenderer::draw(){ +void HudRenderer::draw(const GfxContext& ctx){ + const Viewport& viewport = ctx.getViewport(); + const uint width = viewport.getWidth(); + const uint height = viewport.getHeight(); + debugPanel->visible(level->player->debug); - pauseMenu->setCoord((Window::size() - pauseMenu->size()) / 2.0f); + pauseMenu->setCoord((viewport.size() - pauseMenu->size()) / 2.0f); - auto settingsPanel = guiController->get("settings"); - settingsPanel->setCoord((Window::size() - settingsPanel->size()) / 2.0f); + auto settingsPanel = gui->get("settings"); + settingsPanel->setCoord((viewport.size() - settingsPanel->size()) / 2.0f); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - uicamera->fov = Window::height; + uicamera->fov = height; Shader* uishader = assets->getShader("ui"); uishader->use(); @@ -256,9 +261,7 @@ void HudRenderer::draw(){ batch->texture(nullptr); batch->color = vec4(1.0f); if (Events::_cursor_locked && !level->player->debug) { - glLineWidth(2); - const uint width = Window::width; - const uint height = Window::height; + batch->lineWidth(2); batch->line(width/2, height/2-6, width/2, height/2+6, 0.2f, 0.2f, 0.2f, 1.0f); batch->line(width/2+6, height/2, width/2-6, height/2, 0.2f, 0.2f, 0.2f, 1.0f); batch->line(width/2-5, height/2-5, width/2+5, height/2+5, 0.9f, 0.9f, 0.9f, 1.0f); @@ -266,19 +269,19 @@ void HudRenderer::draw(){ } Player* player = level->player; - batch->rect(Window::width/2-128-4, Window::height-80-4, 256+8, 64+8, + batch->rect(width/2-128-4, height-80-4, 256+8, 64+8, 0.95f, 0.95f, 0.95f, 0.85f, 0.85f, 0.85f, 0.7f, 0.7f, 0.7f, 0.55f, 0.55f, 0.55f, 0.45f, 0.45f, 0.45f, 4); - batch->rect(Window::width/2-128, Window::height - 80, 256, 64, + batch->rect(width/2-128, height - 80, 256, 64, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 4); - batch->rect(Window::width/2-32+2, Window::height - 80+2, 60, 60, + batch->rect(width/2-32+2, height - 80+2, 60, 60, 0.45f, 0.45f, 0.45f, 0.55f, 0.55f, 0.55f, 0.7f, 0.7f, 0.7f, 0.85f, 0.85f, 0.85f, 0.95f, 0.95f, 0.95f, 2); - batch->rect(Window::width/2-32+4, Window::height - 80+4, 56, 56, + batch->rect(width/2-32+4, height - 80+4, 56, 56, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 2); @@ -288,13 +291,13 @@ void HudRenderer::draw(){ { Block* cblock = Block::blocks[player->choosenBlock]; if (cblock->model == BlockModel::block){ - batch->blockSprite(Window::width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); + batch->blockSprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); } else if (cblock->model == BlockModel::xsprite){ - batch->sprite(Window::width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); + batch->sprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); } } - if (Events::jpressed(keycode::ESCAPE) && !guiController->isFocusCaught()) { + if (Events::jpressed(keycode::ESCAPE) && !gui->isFocusCaught()) { if (pause) { pause = false; pauseMenu->visible(false); @@ -317,10 +320,10 @@ void HudRenderer::draw(){ if (pause || inventoryOpen) { batch->texture(nullptr); batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f); - batch->rect(0, 0, Window::width, Window::height); + batch->rect(0, 0, width, height); } if (inventoryOpen) { - drawInventory(player); + drawInventory(ctx, player); } batch->render(); } diff --git a/src/frontend/hud.h b/src/frontend/hud.h index a9b0ae4a..0dd0466d 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -4,6 +4,8 @@ #include #include +#include "../graphics/GfxContext.h" + class Batch2D; class Camera; class Level; @@ -33,12 +35,12 @@ class HudRenderer { std::shared_ptr debugPanel; std::shared_ptr pauseMenu; - gui::GUI* guiController; + gui::GUI* gui; public: HudRenderer(Engine* engine, Level* level); ~HudRenderer(); - void drawInventory(Player* player); - void draw(); + void drawInventory(const GfxContext& ctx, Player* player); + void draw(const GfxContext& context); void drawDebug(int fps, bool occlusion); bool isInventoryOpen() const; diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 0a45adfa..e6d13241 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -13,6 +13,7 @@ #include "../window/input.h" #include "../graphics/Shader.h" #include "../graphics/Batch2D.h" +#include "../graphics/GfxContext.h" #include "../assets/Assets.h" #include "../world/Level.h" #include "../world/World.h" @@ -356,8 +357,11 @@ void LevelScreen::update(float delta) { void LevelScreen::draw(float delta) { Camera* camera = level->player->camera; - worldRenderer->draw(camera, occlusion); - hud->draw(); + Viewport viewport(Window::width, Window::height); + GfxContext ctx(nullptr, viewport, nullptr); + + worldRenderer->draw(ctx, camera, occlusion); + hud->draw(ctx); if (level->player->debug) { hud->drawDebug( 1 / delta, occlusion); } diff --git a/src/frontend/world_render.cpp b/src/frontend/world_render.cpp index c3227872..5e102287 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/world_render.cpp @@ -60,51 +60,15 @@ bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool } mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1)); shader->uniformMatrix("u_model", model); - mesh->draw(GL_TRIANGLES); + mesh->draw(); return true; } - -void WorldRenderer::draw(Camera* camera, bool occlusion){ - EngineSettings& settings = engine->getSettings(); - Assets* assets = engine->getAssets(); - Chunks* chunks = level->chunks; - - vec3 skyColor(0.7f, 0.81f, 1.0f); - - Window::setBgColor(skyColor); - Window::clear(); - Window::viewport(0, 0, Window::width, Window::height); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - - float fogFactor = 18.0f / (float)settings.chunks.loadDistance; - - Texture* texture = assets->getTexture("block"); - Shader* shader = assets->getShader("main"); - Shader* linesShader = assets->getShader("lines"); - shader->use(); - shader->uniformMatrix("u_proj", camera->getProjection()); - shader->uniformMatrix("u_view", camera->getView()); - shader->uniform1f("u_gamma", 1.6f); - shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f); - shader->uniform3f("u_fogColor", skyColor); - shader->uniform1f("u_fogFactor", fogFactor); - shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); - shader->uniform3f("u_cameraPos", camera->position); - - Block* cblock = Block::blocks[level->player->choosenBlock]; - 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); - texture->bind(); - +void WorldRenderer::drawChunks(Chunks* chunks, + Camera* camera, + Shader* shader, + bool occlusion) { std::vector indices; - for (size_t i = 0; i < chunks->volume; i++){ shared_ptr chunk = chunks->chunks[i]; if (chunk == nullptr) @@ -126,34 +90,84 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){ for (size_t i = 0; i < indices.size(); i++){ chunks->visible += drawChunk(indices[i], camera, shader, occlusion); } +} - shader->uniformMatrix("u_model", mat4(1.0f)); - if (level->playerController->selectedBlockId != -1){ - Block* selectedBlock = Block::blocks[level->playerController->selectedBlockId]; - vec3 pos = level->playerController->selectedBlockPosition; - linesShader->use(); - linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView()); - glLineWidth(2.0f); - if (selectedBlock->model == BlockModel::block){ - lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f); - } else if (selectedBlock->model == BlockModel::xsprite){ - lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f, 0.805f,0.705f,0.805f, 0,0,0,0.5f); +void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){ + Assets* assets = engine->getAssets(); + Texture* texture = assets->getTexture("block"); + Shader* shader = assets->getShader("main"); + Shader* linesShader = assets->getShader("lines"); + + const Viewport& viewport = pctx.getViewport(); + int displayWidth = viewport.getWidth(); + int displayHeight = viewport.getHeight(); + { + GfxContext ctx = pctx.sub(); + ctx.depthTest(true); + ctx.cullFace(true); + + EngineSettings& settings = engine->getSettings(); + + vec3 skyColor(0.7f, 0.81f, 1.0f); + + Window::setBgColor(skyColor); + Window::clear(); + Window::viewport(0, 0, displayWidth, displayHeight); + + float fogFactor = 18.0f / (float)settings.chunks.loadDistance; + + shader->use(); + shader->uniformMatrix("u_proj", camera->getProjection()); + shader->uniformMatrix("u_view", camera->getView()); + shader->uniform1f("u_gamma", 1.6f); + shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f); + shader->uniform3f("u_fogColor", skyColor); + shader->uniform1f("u_fogFactor", fogFactor); + shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); + shader->uniform3f("u_cameraPos", camera->position); + + Block* cblock = Block::blocks[level->player->choosenBlock]; + 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); + texture->bind(); + + Chunks* chunks = level->chunks; + drawChunks(chunks, camera, shader, occlusion); + + shader->uniformMatrix("u_model", mat4(1.0f)); + + if (level->playerController->selectedBlockId != -1){ + Block* block = Block::blocks[level->playerController->selectedBlockId]; + vec3 pos = level->playerController->selectedBlockPosition; + linesShader->use(); + linesShader->uniformMatrix("u_projview", camera->getProjView()); + lineBatch->lineWidth(2.0f); + if (block->model == BlockModel::block){ + lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, + 1.008f,1.008f,1.008f, 0,0,0,0.5f); + } else if (block->model == BlockModel::xsprite){ + lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f, + 0.805f,0.705f,0.805f, 0,0,0,0.5f); + } + lineBatch->render(); } - lineBatch->render(); } - glDisable(GL_DEPTH_TEST); - if (level->player->debug) { float length = 40.f; linesShader->use(); - vec3 tsl = vec3(Window::width/2, -((int)Window::height)/2, 0.f); + // top-right: vec3 tsl = vec3(displayWidth - length - 4, -length - 4, 0.f); + vec3 tsl = vec3(displayWidth/2, -((int)displayHeight)/2, 0.f); glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); linesShader->uniformMatrix("u_projview", glm::ortho( - 0.f, (float)Window::width, - -(float)Window::height, 0.f, + 0.f, (float)displayWidth, + -(float)displayHeight, 0.f, -length, length) * model * glm::inverse(camera->rotation)); lineBatch->lineWidth(4.0f); diff --git a/src/frontend/world_render.h b/src/frontend/world_render.h index 34e9df8b..3ff65c19 100644 --- a/src/frontend/world_render.h +++ b/src/frontend/world_render.h @@ -10,6 +10,8 @@ #include #include +#include "../graphics/GfxContext.h" + class Level; class Camera; class LineBatch; @@ -18,6 +20,7 @@ class Shader; class Texture; class Frustum; class Engine; +class Chunks; class WorldRenderer { Engine* engine; @@ -26,12 +29,13 @@ class WorldRenderer { LineBatch* lineBatch; ChunksRenderer* renderer; bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion); + void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion); public: WorldRenderer(Engine* engine, Level* level); ~WorldRenderer(); - void draw(Camera* camera, bool occlusion); + void draw(const GfxContext& context, Camera* camera, bool occlusion); }; diff --git a/src/graphics/Batch2D.cpp b/src/graphics/Batch2D.cpp index e74a72a4..c27af864 100644 --- a/src/graphics/Batch2D.cpp +++ b/src/graphics/Batch2D.cpp @@ -361,3 +361,7 @@ void Batch2D::render(unsigned int gl_primitive) { void Batch2D::render() { render(GL_TRIANGLES); } + +void Batch2D::lineWidth(float width) { + glLineWidth(width); +} diff --git a/src/graphics/Batch2D.h b/src/graphics/Batch2D.h index 3f2933b9..6d66106f 100644 --- a/src/graphics/Batch2D.h +++ b/src/graphics/Batch2D.h @@ -62,6 +62,8 @@ public: float r4, float g4, float b4, int sh); void render(unsigned int gl_primitive); void render(); + + void lineWidth(float width); }; #endif /* SRC_GRAPHICS_BATCH2D_H_ */ diff --git a/src/graphics/GfxContext.cpp b/src/graphics/GfxContext.cpp new file mode 100644 index 00000000..e15dd5bf --- /dev/null +++ b/src/graphics/GfxContext.cpp @@ -0,0 +1,59 @@ +#include "GfxContext.h" + +#include + +#include "Batch2D.h" + +GfxContext::GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d) + : parent(parent), viewport(viewport), g2d(g2d) { +} + +GfxContext::~GfxContext() { + if (parent == nullptr) + return; + if (depthTest_ != parent->depthTest_) { + if (depthTest_) glDisable(GL_DEPTH_TEST); + else glEnable(GL_DEPTH_TEST); + } + if (cullFace_ != parent->cullFace_) { + if (cullFace_) glDisable(GL_CULL_FACE); + else glEnable(GL_CULL_FACE); + } +} + +const Viewport& GfxContext::getViewport() const { + return viewport; +} + +Batch2D* GfxContext::getBatch2D() const { + return g2d; +} + +GfxContext GfxContext::sub() const { + auto ctx = GfxContext(this, viewport, g2d); + ctx.depthTest_ = depthTest_; + ctx.cullFace_ = cullFace_; + return ctx; +} + +void GfxContext::depthTest(bool flag) { + if (depthTest_ == flag) + return; + depthTest_ = flag; + if (depthTest_) { + glEnable(GL_DEPTH_TEST); + } else { + glDisable(GL_DEPTH_TEST); + } +} + +void GfxContext::cullFace(bool flag) { + if (cullFace_ == flag) + return; + cullFace_ = flag; + if (cullFace_) { + glEnable(GL_CULL_FACE); + } else { + glDisable(GL_CULL_FACE); + } +} \ No newline at end of file diff --git a/src/graphics/GfxContext.h b/src/graphics/GfxContext.h new file mode 100644 index 00000000..43e97b5c --- /dev/null +++ b/src/graphics/GfxContext.h @@ -0,0 +1,27 @@ +#ifndef GRAPHICS_GFX_CONTEXT_H_ +#define GRAPHICS_GFX_CONTEXT_H_ + +#include "../typedefs.h" +#include "Viewport.h" + +class Batch2D; + +class GfxContext { + const GfxContext* parent; + Viewport& viewport; + Batch2D* const g2d; + bool depthTest_ = false; + bool cullFace_ = false; +public: + GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d); + ~GfxContext(); + + Batch2D* getBatch2D() const; + const Viewport& getViewport() const; + GfxContext sub() const; + + void depthTest(bool flag); + void cullFace(bool flag); +}; + +#endif // GRAPHICS_GFX_CONTEXT_H_ \ No newline at end of file diff --git a/src/graphics/Viewport.cpp b/src/graphics/Viewport.cpp new file mode 100644 index 00000000..166d28f8 --- /dev/null +++ b/src/graphics/Viewport.cpp @@ -0,0 +1,13 @@ +#include "Viewport.h" + +Viewport::Viewport(uint width, uint height) + : width(width), height(height) { +} + +uint Viewport::getWidth() const { + return width; +} + +uint Viewport::getHeight() const { + return height; +} \ No newline at end of file diff --git a/src/graphics/Viewport.h b/src/graphics/Viewport.h new file mode 100644 index 00000000..da027b8e --- /dev/null +++ b/src/graphics/Viewport.h @@ -0,0 +1,22 @@ +#ifndef GRAPHICS_VIEWPORT_H_ +#define GRAPHICS_VIEWPORT_H_ + +#include + +#include "../typedefs.h" + +class Viewport { + uint width; + uint height; +public: + Viewport(uint width, uint height); + + virtual uint getWidth() const; + virtual uint getHeight() const; + + glm::vec2 size() const { + return glm::vec2(width, height); + } +}; + +#endif // GRAPHICS_VIEWPORT_H_ \ No newline at end of file diff --git a/src/objects/player_control.cpp b/src/objects/player_control.cpp index 6c3b4fdc..73273ebf 100644 --- a/src/objects/player_control.cpp +++ b/src/objects/player_control.cpp @@ -215,8 +215,21 @@ void PlayerController::updateInteraction(){ Camera* camera = player->camera; vec3 end; vec3 norm; + + bool xkey = Events::pressed(keycode::X); + bool lclick = Events::jclicked(mousecode::BUTTON_1) || + (xkey && Events::clicked(mousecode::BUTTON_1)); + bool rclick = Events::jclicked(mousecode::BUTTON_2) || + (xkey && Events::clicked(mousecode::BUTTON_2)); + float maxDistance = 10.0f; + if (xkey) { + maxDistance *= 20.0f; + } vec3 iend; - voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend); + voxel* vox = chunks->rayCast(camera->position, + camera->front, + maxDistance, + end, norm, iend); if (vox != nullptr){ player->selectedVoxel = *vox; selectedBlockId = vox->id; @@ -238,11 +251,11 @@ void PlayerController::updateInteraction(){ } Block* block = Block::blocks[vox->id]; - if (Events::jclicked(mousecode::BUTTON_1) && block->breakable){ + if (lclick && block->breakable){ chunks->set(x,y,z, 0, 0); lighting->onBlockSet(x,y,z, 0); } - if (Events::jclicked(mousecode::BUTTON_2)){ + if (rclick){ if (block->model != BlockModel::xsprite){ x = (int)(iend.x)+(int)(norm.x); y = (int)(iend.y)+(int)(norm.y);