diff --git a/res/content/base/blocks/water.json b/res/content/base/blocks/water.json index de702de1..c0d6b3e2 100644 --- a/res/content/base/blocks/water.json +++ b/res/content/base/blocks/water.json @@ -1,9 +1,10 @@ { "texture": "water", + "overlay-texture": "water", "draw-group": 3, "light-passing": true, "sky-light-passing": false, "obstacle": false, "selectable": false, "replaceable": true -} \ No newline at end of file +} diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 3294b040..7bad427e 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -326,6 +326,7 @@ void ContentLoader::loadBlock( root.at("ui-layout").get(def.uiLayout); root.at("inventory-size").get(def.inventorySize); root.at("tick-interval").get(def.tickInterval); + root.at("overlay-texture").get(def.overlayTexture); if (root.has("fields")) { def.dataStruct = std::make_unique(); diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index f2926998..22927b3c 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -58,11 +58,13 @@ Skybox::Skybox(uint size, Shader* shader) Skybox::~Skybox() = default; -void Skybox::drawBackground(Camera* camera, Assets* assets, int width, int height) { - auto backShader = assets->get("background"); +void Skybox::drawBackground( + const Camera& camera, const Assets& assets, int width, int height +) { + auto backShader = assets.get("background"); backShader->use(); - backShader->uniformMatrix("u_view", camera->getView(false)); - backShader->uniform1f("u_zoom", camera->zoom*camera->getFov()/(M_PI*0.5f)); + backShader->uniformMatrix("u_view", camera.getView(false)); + backShader->uniform1f("u_zoom", camera.zoom*camera.getFov()/(M_PI*0.5f)); backShader->uniform1f("u_ar", float(width)/float(height)); backShader->uniform1i("u_cubemap", 1); bind(); @@ -93,8 +95,8 @@ void Skybox::drawStars(float angle, float opacity) { void Skybox::draw( const DrawContext& pctx, - Camera* camera, - Assets* assets, + const Camera& camera, + const Assets& assets, float daytime, float fog) { @@ -107,9 +109,9 @@ void Skybox::draw( DrawContext ctx = pctx.sub(); ctx.setBlendMode(BlendMode::addition); - auto p_shader = assets->get("ui3d"); + auto p_shader = assets.get("ui3d"); p_shader->use(); - p_shader->uniformMatrix("u_projview", camera->getProjView(false)); + p_shader->uniformMatrix("u_projview", camera.getProjView(false)); p_shader->uniformMatrix("u_apply", glm::mat4(1.0f)); batch3d->begin(); @@ -117,7 +119,7 @@ void Skybox::draw( float opacity = glm::pow(1.0f-fog, 7.0f); for (auto& sprite : sprites) { - batch3d->texture(assets->get(sprite.texture)); + batch3d->texture(assets.get(sprite.texture)); float sangle = daytime * float(M_PI)*2.0 + sprite.phase; float distance = sprite.distance; diff --git a/src/graphics/render/Skybox.hpp b/src/graphics/render/Skybox.hpp index c0635f90..2781a95a 100644 --- a/src/graphics/render/Skybox.hpp +++ b/src/graphics/render/Skybox.hpp @@ -35,15 +35,17 @@ class Skybox { std::vector sprites; void drawStars(float angle, float opacity); - void drawBackground(Camera* camera, Assets* assets, int width, int height); + void drawBackground( + const Camera& camera, const Assets& assets, int width, int height + ); public: Skybox(uint size, Shader* shader); ~Skybox(); void draw( const DrawContext& pctx, - Camera* camera, - Assets* assets, + const Camera& camera, + const Assets& assets, float daytime, float fog ); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index cec7e3a2..f36c7a24 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -410,8 +410,8 @@ void WorldRenderer::draw( skybox->refresh(pctx, worldInfo.daytime, 1.0f + worldInfo.fog * 2.0f, 4); - auto assets = engine->getAssets(); - auto linesShader = assets->get("lines"); + const auto& assets = *engine->getAssets(); + auto linesShader = assets.get("lines"); // World render scope with diegetic HUD included { @@ -421,7 +421,7 @@ void WorldRenderer::draw( Window::clearDepth(); // Drawing background sky plane - skybox->draw(pctx, &camera, assets, worldInfo.daytime, worldInfo.fog); + skybox->draw(pctx, camera, assets, worldInfo.daytime, worldInfo.fog); // Actually world render with depth buffer on { @@ -432,23 +432,66 @@ void WorldRenderer::draw( // Debug lines if (hudVisible) { renderLines(camera, linesShader, ctx); - renderHands(camera, *assets); + renderHands(camera, assets); } } - if (hudVisible && player->debug) { renderDebugLines(wctx, camera, linesShader); } + renderBlockOverlay(wctx, assets); } // Rendering fullscreen quad with - auto screenShader = assets->get("screen"); + auto screenShader = assets.get("screen"); screenShader->use(); screenShader->uniform1f("u_timer", timer); screenShader->uniform1f("u_dayTime", worldInfo.daytime); postProcessing->render(pctx, screenShader); } +void WorldRenderer::renderBlockOverlay(const DrawContext& wctx, const Assets& assets) { + int x = std::floor(player->camera->position.x); + int y = std::floor(player->camera->position.y); + int z = std::floor(player->camera->position.z); + auto block = level->chunks->get(x, y, z); + if (block && block->id) { + const auto& def = + level->content->getIndices()->blocks.require(block->id); + if (def.overlayTexture.empty()) { + return; + } + DrawContext ctx = wctx.sub(); + ctx.setDepthTest(false); + ctx.setCullFace(false); + + auto& shader = assets.require("ui3d"); + auto& atlas = assets.require("blocks"); + shader.use(); + batch3d->begin(); + shader.uniformMatrix("u_projview", glm::mat4(1.0f)); + shader.uniformMatrix("u_apply", glm::mat4(1.0f)); + auto light = level->chunks->getLight(x, y, z); + float s = Lightmap::extract(light, 3) / 15.0f; + glm::vec4 tint( + glm::min(1.0f, Lightmap::extract(light, 0) / 15.0f + s), + glm::min(1.0f, Lightmap::extract(light, 1) / 15.0f + s), + glm::min(1.0f, Lightmap::extract(light, 2) / 15.0f + s), + 1.0f + ); + batch3d->texture(atlas.getTexture()); + batch3d->sprite( + glm::vec3(), + glm::vec3(0, 1, 0), + glm::vec3(1, 0, 0), + 2, + 2, + atlas.get(def.overlayTexture), + tint + ); + batch3d->flush(); + } +} + void WorldRenderer::drawBorders( int sx, int sy, int sz, int ex, int ey, int ez ) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 8ccbd928..c5d7040e 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -67,6 +67,8 @@ class WorldRenderer { Shader* linesShader ); + void renderBlockOverlay(const DrawContext& context, const Assets& assets); + void setupWorldShader( Shader* shader, const Camera& camera, diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index d09cbd99..963a0928 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -141,6 +141,7 @@ void Block::cloneTo(Block& dst) { dst.uiLayout = uiLayout; dst.inventorySize = inventorySize; dst.tickInterval = tickInterval; + dst.overlayTexture = overlayTexture; } static std::set> RESERVED_BLOCK_FIELDS { diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 90321ee6..2d2cdf90 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -185,6 +185,9 @@ public: /// @brief Block will be used instead of this if generated on surface std::string surfaceReplacement = name; + /// @brief Texture will be shown on screen if camera is inside of the block + std::string overlayTexture; + /// @brief Default block layout will be used by hud.open_block(...) std::string uiLayout = name;