From 561fb0fb58b5bdd543819c850ae8bc024ba29b3a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 19 Dec 2025 22:08:07 +0300 Subject: [PATCH 01/13] feat: naive texture-faces support for blockwraps implementation --- src/graphics/render/BlockWrapsRenderer.cpp | 92 +++++++++++----------- src/graphics/render/BlockWrapsRenderer.hpp | 4 +- src/graphics/render/MainBatch.cpp | 19 +++-- src/graphics/render/MainBatch.hpp | 3 +- 4 files changed, 63 insertions(+), 55 deletions(-) diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index 86c46c984..34b2dba45 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -25,59 +25,58 @@ BlockWrapsRenderer::BlockWrapsRenderer( BlockWrapsRenderer::~BlockWrapsRenderer() = default; void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) { - auto textureRegion = util::get_texture_region(assets, wrapper.texture, ""); - auto& shader = assets.require("entity"); shader.use(); shader.uniform1i("u_alphaClip", false); - const UVRegion& cracksRegion = textureRegion.region; - UVRegion regions[6] { - cracksRegion, cracksRegion, cracksRegion, - cracksRegion, cracksRegion, cracksRegion - }; - batch->setTexture(textureRegion.texture); + util::TextureRegion texRegions[6] {}; + UVRegion uvRegions[6] {}; + for (int i = 0; i < 6; i++) { + auto texRegion = util::get_texture_region(assets, wrapper.textureFaces[i], ""); + texRegions[i] = texRegion; + uvRegions[i] = texRegion.region; + } + batch->setTexture(texRegions[0].texture); const voxel* vox = chunks.get(wrapper.position); - if (vox == nullptr) { + if (vox == nullptr || vox->id == BLOCK_VOID) { return; } - if (vox->id != BLOCK_VOID) { - const auto& def = level.content.getIndices()->blocks.require(vox->id); - switch (def.getModel(vox->state.userbits).type) { - case BlockModelType::BLOCK: - batch->cube( - glm::vec3(wrapper.position) + glm::vec3(0.5f), - glm::vec3(1.01f), - regions, - glm::vec4(1,1,1,0), - false - ); - break; - case BlockModelType::AABB: { - const auto& aabb = - (def.rotatable ? def.rt.hitboxes[vox->state.rotation] - : def.hitboxes) - .at(0); - const auto& size = aabb.size(); - regions[0].scale(size.z, size.y); - regions[1].scale(size.z, size.y); - regions[2].scale(size.x, size.z); - regions[3].scale(size.x, size.z); - regions[4].scale(size.x, size.y); - regions[5].scale(size.x, size.y); - batch->cube( - glm::vec3(wrapper.position) + aabb.center(), - size * glm::vec3(1.01f), - regions, - glm::vec4(1,1,1,0), - false - ); - break; - } - default: - break; + const auto& def = level.content.getIndices()->blocks.require(vox->id); + switch (def.getModel(vox->state.userbits).type) { + case BlockModelType::BLOCK: + batch->cube( + glm::vec3(wrapper.position) + glm::vec3(0.5f), + glm::vec3(1.01f), + uvRegions, + glm::vec4(1, 1, 1, 0), + false, + wrapper.cullingBits + ); + break; + case BlockModelType::AABB: { + const auto& aabb = + (def.rotatable ? def.rt.hitboxes[vox->state.rotation] + : def.hitboxes).at(0); + const auto& size = aabb.size(); + uvRegions[0].scale(size.z, size.y); + uvRegions[1].scale(size.z, size.y); + uvRegions[2].scale(size.x, size.z); + uvRegions[3].scale(size.x, size.z); + uvRegions[4].scale(size.x, size.y); + uvRegions[5].scale(size.x, size.y); + batch->cube( + glm::vec3(wrapper.position) + aabb.center(), + size * glm::vec3(1.01f), + uvRegions, + glm::vec4(1, 1, 1, 0), + false, + wrapper.cullingBits + ); + break; } + default: + break; } } @@ -93,9 +92,8 @@ u64id_t BlockWrapsRenderer::add( const glm::ivec3& position, const std::string& texture ) { u64id_t id = nextWrapper++; - wrappers[id] = std::make_unique( - BlockWrapper {position, texture} - ); + wrappers[id] = std::make_unique(BlockWrapper { + position, {texture, texture, texture, texture, texture, texture}}); return id; } diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index 9d6184b90..2309aa434 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -15,7 +16,8 @@ class DrawContext; struct BlockWrapper { glm::ivec3 position; - std::string texture; + std::array textureFaces {}; + uint8_t cullingBits = 0xFF; }; class BlockWrapsRenderer { diff --git a/src/graphics/render/MainBatch.cpp b/src/graphics/render/MainBatch.cpp index f05b715d7..2cc6e90ca 100644 --- a/src/graphics/render/MainBatch.cpp +++ b/src/graphics/render/MainBatch.cpp @@ -83,50 +83,57 @@ inline glm::vec4 do_tint(float value) { } void MainBatch::cube( - const glm::vec3 &coord, - const glm::vec3 &size, - const UVRegion(&texfaces)[6], - const glm::vec4 &tint, - bool shading + const glm::vec3& coord, + const glm::vec3& size, + const UVRegion(&texfaces)[6], + const glm::vec4& tint, + bool shading, + uint8_t cullingBits ) { const glm::vec3 X(1.0f, 0.0f, 0.0f); const glm::vec3 Y(0.0f, 1.0f, 0.0f); const glm::vec3 Z(0.0f, 0.0f, 1.0f); + if (cullingBits & 0x20) quad( coord + Z * size.z * 0.5f, X, Y, Z, glm::vec2(size.x, size.y), (shading ? do_tint(0.8) * tint : tint), glm::vec3(1.0f), texfaces[5] ); + if (cullingBits & 0x10) quad( coord - Z * size.z * 0.5f, -X, Y, -Z, glm::vec2(size.x, size.y), (shading ? do_tint(0.9f) * tint : tint), glm::vec3(1.0f), texfaces[4] ); + if (cullingBits & 0x8) quad( coord + Y * size.y * 0.5f, -X, Z, Y, glm::vec2(size.x, size.z), (shading ? do_tint(1.0f) * tint : tint), glm::vec3(1.0f), texfaces[3] ); + if (cullingBits & 0x4) quad( coord - Y * size.y * 0.5f, X, Z, -Y, glm::vec2(size.x, size.z), (shading ? do_tint(0.7f) * tint : tint), glm::vec3(1.0f), texfaces[2] ); + if (cullingBits & 0x2) quad( coord + X * size.x * 0.5f, -Z, Y, X, glm::vec2(size.z, size.y), (shading ? do_tint(0.8f) * tint : tint), glm::vec3(1.0f), texfaces[1] ); + if (cullingBits & 0x1) quad( coord - X * size.x * 0.5f, Z, Y, -X, glm::vec2(size.z, size.y), (shading ? do_tint(0.9f) * tint : tint), - glm::vec3(1.0f), texfaces[1] + glm::vec3(1.0f), texfaces[0] ); } diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp index ec85b0082..2bb98cae8 100644 --- a/src/graphics/render/MainBatch.hpp +++ b/src/graphics/render/MainBatch.hpp @@ -152,6 +152,7 @@ public: const glm::vec3& size, const UVRegion(&texfaces)[6], const glm::vec4& tint, - bool shading + bool shading, + uint8_t cullingBits = 0xFF ); }; From 8a05541a9ee27d76e816545de48d2f195703ef4a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 19 Dec 2025 22:08:40 +0300 Subject: [PATCH 02/13] add gfx.blockwraps.set_faces --- .../scripting/lua/libs/libblockwraps.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index ceeec744c..6d6acb244 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -29,7 +29,24 @@ 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))) { - wrapper->texture = lua::require_string(L, 2); + for (int i = 0; i < wrapper->textureFaces.size(); i++) { + wrapper->textureFaces[i] = lua::require_string(L, 2); + } + } + return 0; +} + +static int l_set_faces(lua::State* L) { + if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { + for (int i = 0; i < wrapper->textureFaces.size(); i++) { + if (lua::isnil(L, 2 + i)) { + wrapper->cullingBits &= ~(1 << i); + wrapper->textureFaces[i] = ""; + } else { + wrapper->cullingBits |= (1 << i); + wrapper->textureFaces[i] = lua::require_string(L, 2 + i); + } + } } return 0; } @@ -39,5 +56,6 @@ const luaL_Reg blockwrapslib[] = { {"unwrap", lua::wrap}, {"set_pos", lua::wrap}, {"set_texture", lua::wrap}, + {"set_faces", lua::wrap}, {nullptr, nullptr} }; From 908fbc895e18d21ea00ae4e69f957534c4cdc0eb Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 19 Dec 2025 22:14:03 +0300 Subject: [PATCH 03/13] update target texture detection --- src/graphics/render/BlockWrapsRenderer.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index 34b2dba45..419dfc4fd 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -30,13 +30,21 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) { shader.uniform1i("u_alphaClip", false); util::TextureRegion texRegions[6] {}; + const Texture* texture = nullptr; UVRegion uvRegions[6] {}; for (int i = 0; i < 6; i++) { + if (wrapper.cullingBits & (1 << i) == 0) { + continue; + } auto texRegion = util::get_texture_region(assets, wrapper.textureFaces[i], ""); texRegions[i] = texRegion; uvRegions[i] = texRegion.region; + + if (texture == nullptr) { + texture = texRegion.texture; + } } - batch->setTexture(texRegions[0].texture); + batch->setTexture(texture); const voxel* vox = chunks.get(wrapper.position); if (vox == nullptr || vox->id == BLOCK_VOID) { From b0ecfd5add864b5dc3afdef7f9b69b1af96ad211 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 20 Dec 2025 22:21:00 +0300 Subject: [PATCH 04/13] feat: different textures/atlases support --- src/graphics/render/BlockWrapsRenderer.cpp | 127 ++++++++++++------ src/graphics/render/BlockWrapsRenderer.hpp | 13 +- .../scripting/lua/libs/libblockwraps.cpp | 14 +- 3 files changed, 110 insertions(+), 44 deletions(-) diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index 419dfc4fd..497e2d2c7 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -1,7 +1,6 @@ #include "BlockWrapsRenderer.hpp" #include "assets/Assets.hpp" -#include "assets/assets_util.hpp" #include "constants.hpp" #include "content/Content.hpp" #include "graphics/core/Atlas.hpp" @@ -13,6 +12,8 @@ #include "voxels/Chunks.hpp" #include "world/Level.hpp" +#include + BlockWrapsRenderer::BlockWrapsRenderer( const Assets& assets, const Level& level, const Chunks& chunks ) @@ -24,62 +25,46 @@ BlockWrapsRenderer::BlockWrapsRenderer( BlockWrapsRenderer::~BlockWrapsRenderer() = default; -void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) { - auto& shader = assets.require("entity"); - shader.use(); - shader.uniform1i("u_alphaClip", false); - - util::TextureRegion texRegions[6] {}; - const Texture* texture = nullptr; - UVRegion uvRegions[6] {}; - for (int i = 0; i < 6; i++) { - if (wrapper.cullingBits & (1 << i) == 0) { - continue; - } - auto texRegion = util::get_texture_region(assets, wrapper.textureFaces[i], ""); - texRegions[i] = texRegion; - uvRegions[i] = texRegion.region; - - if (texture == nullptr) { - texture = texRegion.texture; - } - } - batch->setTexture(texture); - - const voxel* vox = chunks.get(wrapper.position); - if (vox == nullptr || vox->id == BLOCK_VOID) { +void BlockWrapsRenderer::draw(const BlockWrapper& wrapper, const Texture* texture) { + if (wrapper.cullingBits == 0x0) { return; } - const auto& def = level.content.getIndices()->blocks.require(vox->id); - switch (def.getModel(vox->state.userbits).type) { + + uint8_t cullingBits = wrapper.cullingBits; + for (int i = 0; i < 6; i++) { + if ((cullingBits & (1 << i)) == 0x0) { + continue; + } + cullingBits &= ~((wrapper.texRegions[i].texture != texture) << i); + } + if (cullingBits == 0x0) { + return; + } + + const auto& def = level.content.getIndices()->blocks.require(wrapper.vox->id); + switch (def.getModel(wrapper.vox->state.userbits).type) { case BlockModelType::BLOCK: batch->cube( glm::vec3(wrapper.position) + glm::vec3(0.5f), glm::vec3(1.01f), - uvRegions, + wrapper.uvRegions, glm::vec4(1, 1, 1, 0), false, - wrapper.cullingBits + cullingBits ); break; case BlockModelType::AABB: { const auto& aabb = - (def.rotatable ? def.rt.hitboxes[vox->state.rotation] + (def.rotatable ? def.rt.hitboxes[wrapper.vox->state.rotation] : def.hitboxes).at(0); const auto& size = aabb.size(); - uvRegions[0].scale(size.z, size.y); - uvRegions[1].scale(size.z, size.y); - uvRegions[2].scale(size.x, size.z); - uvRegions[3].scale(size.x, size.z); - uvRegions[4].scale(size.x, size.y); - uvRegions[5].scale(size.x, size.y); batch->cube( glm::vec3(wrapper.position) + aabb.center(), size * glm::vec3(1.01f), - uvRegions, + wrapper.uvRegions, glm::vec4(1, 1, 1, 0), false, - wrapper.cullingBits + cullingBits ); break; } @@ -88,10 +73,60 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) { } } +void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { + for (int i = 0; i < 6; i++) { + if ((wrapper.cullingBits & (1 << i)) == 0) { + continue; + } + auto texRegion = util::get_texture_region(assets, wrapper.textureFaces[i], ""); + wrapper.texRegions[i] = texRegion; + wrapper.uvRegions[i] = texRegion.region; + + renderOrder.insert({texRegion.texture, &wrapper}); + } + wrapper.dirtySides = 0x0; + + const voxel* vox = chunks.get(wrapper.position); + if (vox == nullptr || vox->id == BLOCK_VOID) { + return; + } + const auto& def = level.content.getIndices()->blocks.require(vox->id); + switch (def.getModel(vox->state.userbits).type) { + case BlockModelType::AABB: { + const auto& aabb = + (def.rotatable ? def.rt.hitboxes[vox->state.rotation] + : def.hitboxes).at(0); + const auto& size = aabb.size(); + wrapper.uvRegions[0].scale(size.z, size.y); + wrapper.uvRegions[1].scale(size.z, size.y); + wrapper.uvRegions[2].scale(size.x, size.z); + wrapper.uvRegions[3].scale(size.x, size.z); + wrapper.uvRegions[4].scale(size.x, size.y); + wrapper.uvRegions[5].scale(size.x, size.y); + break; + } + default: + break; + } + wrapper.vox = vox; +} + void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { auto ctx = pctx.sub(); + + auto& shader = assets.require("entity"); + shader.use(); + shader.uniform1i("u_alphaClip", false); + for (const auto& [_, wrapper] : wrappers) { - draw(*wrapper); + if (wrapper->dirtySides) { + refreshWrapper(*wrapper); + } + } + + for (const auto& [texture, wrapper] : renderOrder) { + batch->setTexture(texture); + draw(*wrapper, texture); } batch->flush(); } @@ -114,5 +149,19 @@ BlockWrapper* BlockWrapsRenderer::get(u64id_t id) const { } void BlockWrapsRenderer::remove(u64id_t id) { + auto found = wrappers.find(id); + if (found == wrappers.end()) { + return; + } + auto wrapper = std::move(found->second); wrappers.erase(id); + + auto it = renderOrder.begin(); + while (it != renderOrder.end()) { + if (it->second == wrapper.get()) { + it = renderOrder.erase(it); + } else { + ++it; + } + } } diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index 2309aa434..faf593a7f 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -4,20 +4,28 @@ #include #include #include +#include +#include "assets/assets_util.hpp" #include "MainBatch.hpp" #include "typedefs.hpp" class Assets; class Player; class Level; +struct voxel; class Chunks; +class Texture; class DrawContext; struct BlockWrapper { glm::ivec3 position; std::array textureFaces {}; + util::TextureRegion texRegions[6] {}; + UVRegion uvRegions[6] {}; + const voxel* vox = nullptr; uint8_t cullingBits = 0xFF; + uint8_t dirtySides = 0xFF; }; class BlockWrapsRenderer { @@ -26,10 +34,13 @@ class BlockWrapsRenderer { const Chunks& chunks; std::unique_ptr batch; + std::multimap renderOrder; std::unordered_map> wrappers; u64id_t nextWrapper = 1; - void draw(const BlockWrapper& wrapper); + void draw(const BlockWrapper& wrapper, const Texture* texture); + + void refreshWrapper(BlockWrapper& wrapper); public: BlockWrapsRenderer( const Assets& assets, const Level& level, const Chunks& chunks diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index 6d6acb244..dc956eda8 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -40,11 +40,17 @@ static int l_set_faces(lua::State* L) { if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { for (int i = 0; i < wrapper->textureFaces.size(); i++) { if (lua::isnil(L, 2 + i)) { - wrapper->cullingBits &= ~(1 << i); - wrapper->textureFaces[i] = ""; + if (wrapper->cullingBits & (1 << i)) { + wrapper->cullingBits &= ~(1 << i); + wrapper->textureFaces[i] = ""; + wrapper->dirtySides |= (1 << i); + } } else { - wrapper->cullingBits |= (1 << i); - wrapper->textureFaces[i] = 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); + wrapper->textureFaces[i] = texture; + } } } } From 6d6d38c2180ae79d69498acdd3a525399579995a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 20 Dec 2025 22:33:47 +0300 Subject: [PATCH 05/13] fix block model change wrapper reaction --- src/graphics/render/BlockWrapsRenderer.cpp | 19 ++++++++++++++----- src/graphics/render/BlockWrapsRenderer.hpp | 4 +++- .../scripting/lua/libs/libblockwraps.cpp | 3 ++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index 497e2d2c7..c169bebfb 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -25,7 +25,7 @@ BlockWrapsRenderer::BlockWrapsRenderer( BlockWrapsRenderer::~BlockWrapsRenderer() = default; -void BlockWrapsRenderer::draw(const BlockWrapper& wrapper, const Texture* texture) { +void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { if (wrapper.cullingBits == 0x0) { return; } @@ -41,8 +41,15 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper, const Texture* textur return; } - const auto& def = level.content.getIndices()->blocks.require(wrapper.vox->id); - switch (def.getModel(wrapper.vox->state.userbits).type) { + // one frame can be invalid due to texture change but ok + const auto& def = + level.content.getIndices()->blocks.require(wrapper.vox->id); + + if (wrapper.modelType != def.getModel(wrapper.vox->state.userbits).type) { + wrapper.dirtySides = 0xFF; + refreshWrapper(wrapper); + } + switch (wrapper.modelType) { case BlockModelType::BLOCK: batch->cube( glm::vec3(wrapper.position) + glm::vec3(0.5f), @@ -78,7 +85,8 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { if ((wrapper.cullingBits & (1 << i)) == 0) { continue; } - auto texRegion = util::get_texture_region(assets, wrapper.textureFaces[i], ""); + auto texRegion = + util::get_texture_region(assets, wrapper.textureFaces[i], ""); wrapper.texRegions[i] = texRegion; wrapper.uvRegions[i] = texRegion.region; @@ -91,7 +99,8 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { return; } const auto& def = level.content.getIndices()->blocks.require(vox->id); - switch (def.getModel(vox->state.userbits).type) { + wrapper.modelType = def.getModel(vox->state.userbits).type; + switch (wrapper.modelType) { case BlockModelType::AABB: { const auto& aabb = (def.rotatable ? def.rt.hitboxes[vox->state.rotation] diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index faf593a7f..ebb4d0e8a 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -7,6 +7,7 @@ #include #include "assets/assets_util.hpp" +#include "voxels/Block.hpp" #include "MainBatch.hpp" #include "typedefs.hpp" @@ -24,6 +25,7 @@ struct BlockWrapper { util::TextureRegion texRegions[6] {}; UVRegion uvRegions[6] {}; const voxel* vox = nullptr; + BlockModelType modelType {}; uint8_t cullingBits = 0xFF; uint8_t dirtySides = 0xFF; }; @@ -38,7 +40,7 @@ class BlockWrapsRenderer { std::unordered_map> wrappers; u64id_t nextWrapper = 1; - void draw(const BlockWrapper& wrapper, const Texture* texture); + void draw(BlockWrapper& wrapper, const Texture* texture); void refreshWrapper(BlockWrapper& wrapper); public: diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index dc956eda8..30aaa60c6 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -47,7 +47,8 @@ static int l_set_faces(lua::State* L) { } } else { auto texture = lua::require_string(L, 2 + i);; - if ((wrapper->cullingBits & (1 << i)) == 0x0 || wrapper->textureFaces[i] != texture) { + if ((wrapper->cullingBits & (1 << i)) == 0x0 + || wrapper->textureFaces[i] != texture) { wrapper->cullingBits |= (1 << i); wrapper->textureFaces[i] = texture; } From 54d1398d1be8b52cc59196d91c13817b523e2582 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 20 Dec 2025 23:26:50 +0300 Subject: [PATCH 06/13] add Lightmap::extractNormalized --- src/graphics/render/BlocksRenderer.cpp | 5 +---- src/lighting/Lightmap.hpp | 10 ++++++++++ src/voxels/Chunks.cpp | 4 ++++ src/voxels/Chunks.hpp | 1 + 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 8466008da..5320edd73 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -452,10 +452,7 @@ glm::vec4 BlocksRenderer::pickLight(int x, int y, int z) const { if (isOpenForLight(x, y, z)) { light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z); - return glm::vec4(Lightmap::extract(light, 0), - Lightmap::extract(light, 1), - Lightmap::extract(light, 2), - Lightmap::extract(light, 3)) / 15.0f; + return Lightmap::extractNormalized(light); } else { return glm::vec4(0.0f); } diff --git a/src/lighting/Lightmap.hpp b/src/lighting/Lightmap.hpp index 858e37388..c13058904 100644 --- a/src/lighting/Lightmap.hpp +++ b/src/lighting/Lightmap.hpp @@ -5,6 +5,7 @@ #include #include +#include inline constexpr int LIGHTMAP_DATA_LEN = CHUNK_VOL/2; @@ -87,6 +88,15 @@ public: return (light >> (channel << 2)) & 0xF; } + static glm::vec4 extractNormalized(light_t light) { + return glm::vec4( + extract(light, 0) / 15.0f, + extract(light, 1) / 15.0f, + extract(light, 2) / 15.0f, + extract(light, 3) / 15.0f + ); + } + std::unique_ptr encode() const; void decode(const ubyte* src); diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 96c709639..1233f089c 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -100,6 +100,10 @@ bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) { return indices.blocks.require(v->id).obstacle; } +ubyte Chunks::getLight(const glm::ivec3& pos) const { + return getLight(pos.x, pos.y, pos.z); +} + ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) const { if (y < 0 || y >= CHUNK_H) { return 0; diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index 2448d8333..94fac08ce 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -76,6 +76,7 @@ public: return get(pos.x, pos.y, pos.z); } + ubyte getLight(const glm::ivec3& pos) const; light_t getLight(int32_t x, int32_t y, int32_t z) const; ubyte getLight(int32_t x, int32_t y, int32_t z, int channel) const; void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state); From dfdc7ebf6bd9e1b1b42c235022ae907c8f719f7d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 20 Dec 2025 23:51:22 +0300 Subject: [PATCH 07/13] add 'emission' block wrap property --- src/graphics/render/BlockWrapsRenderer.cpp | 25 +++++++++++++++------- src/graphics/render/BlockWrapsRenderer.hpp | 4 +++- src/graphics/render/ChunksRenderer.cpp | 5 ++--- src/graphics/render/MainBatch.cpp | 14 ++++++------ src/graphics/render/MainBatch.hpp | 2 +- src/voxels/Chunks.cpp | 2 +- src/voxels/Chunks.hpp | 2 +- 7 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index c169bebfb..c286e28ce 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -7,6 +7,7 @@ #include "graphics/core/Shader.hpp" #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" @@ -41,36 +42,45 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { return; } + const voxel* vox = chunks.get(wrapper.position); + if (vox == nullptr || vox->id == BLOCK_VOID) { + return; + } // one frame can be invalid due to texture change but ok const auto& def = - level.content.getIndices()->blocks.require(wrapper.vox->id); + level.content.getIndices()->blocks.require(vox->id); - if (wrapper.modelType != def.getModel(wrapper.vox->state.userbits).type) { + 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) { + light = Lightmap::extractNormalized(chunks.getLight(wrapper.position)); + light = wrapper.emission + (1.0f - light); + } switch (wrapper.modelType) { case BlockModelType::BLOCK: batch->cube( glm::vec3(wrapper.position) + glm::vec3(0.5f), glm::vec3(1.01f), wrapper.uvRegions, - glm::vec4(1, 1, 1, 0), - false, + light, + wrapper.emission, cullingBits ); break; case BlockModelType::AABB: { const auto& aabb = - (def.rotatable ? def.rt.hitboxes[wrapper.vox->state.rotation] + (def.rotatable ? def.rt.hitboxes[vox->state.rotation] : def.hitboxes).at(0); const auto& size = aabb.size(); batch->cube( glm::vec3(wrapper.position) + aabb.center(), size * glm::vec3(1.01f), wrapper.uvRegions, - glm::vec4(1, 1, 1, 0), - false, + light, + wrapper.emission, cullingBits ); break; @@ -117,7 +127,6 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { default: break; } - wrapper.vox = vox; } void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index ebb4d0e8a..2d14e4a93 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -22,9 +22,11 @@ class DrawContext; struct BlockWrapper { glm::ivec3 position; std::array textureFaces {}; + float emission = 1.0f; + + // --- render cache --- util::TextureRegion texRegions[6] {}; UVRegion uvRegions[6] {}; - const voxel* vox = nullptr; BlockModelType modelType {}; uint8_t cullingBits = 0xFF; uint8_t dirtySides = 0xFF; diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 8289967c1..78bf6f2e7 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -128,12 +128,11 @@ const Mesh* ChunksRenderer::render( chunk->flags.modified = false; if (important) { auto voxelsBuffer = prepareVoxelsVolume(*chunk); - inwork[key] = true; auto mesh = renderer->render(chunk.get(), *voxelsBuffer); - meshes[glm::ivec2(chunk->x, chunk->z)] = + meshes[key] = ChunkMesh {std::move(mesh.mesh), std::move(mesh.sortingMeshData)}; - return meshes[glm::ivec2(chunk->x, chunk->z)].mesh.get(); + return meshes[key].mesh.get(); } if (inwork.find(key) != inwork.end()) { return nullptr; diff --git a/src/graphics/render/MainBatch.cpp b/src/graphics/render/MainBatch.cpp index 2cc6e90ca..1498e1537 100644 --- a/src/graphics/render/MainBatch.cpp +++ b/src/graphics/render/MainBatch.cpp @@ -87,7 +87,7 @@ void MainBatch::cube( const glm::vec3& size, const UVRegion(&texfaces)[6], const glm::vec4& tint, - bool shading, + float emission, uint8_t cullingBits ) { const glm::vec3 X(1.0f, 0.0f, 0.0f); @@ -98,42 +98,42 @@ void MainBatch::cube( quad( coord + Z * size.z * 0.5f, X, Y, Z, glm::vec2(size.x, size.y), - (shading ? do_tint(0.8) * tint : tint), + do_tint((1.0f - emission) * 0.8 + emission) * tint, glm::vec3(1.0f), texfaces[5] ); if (cullingBits & 0x10) quad( coord - Z * size.z * 0.5f, -X, Y, -Z, glm::vec2(size.x, size.y), - (shading ? do_tint(0.9f) * tint : tint), + do_tint((1.0f - emission) * 0.9 + emission) * tint, glm::vec3(1.0f), texfaces[4] ); if (cullingBits & 0x8) quad( coord + Y * size.y * 0.5f, -X, Z, Y, glm::vec2(size.x, size.z), - (shading ? do_tint(1.0f) * tint : tint), + do_tint((1.0f - emission) * 1.0 + emission) * tint, glm::vec3(1.0f), texfaces[3] ); if (cullingBits & 0x4) quad( coord - Y * size.y * 0.5f, X, Z, -Y, glm::vec2(size.x, size.z), - (shading ? do_tint(0.7f) * tint : tint), + do_tint((1.0f - emission) * 0.7 + emission) * tint, glm::vec3(1.0f), texfaces[2] ); if (cullingBits & 0x2) quad( coord + X * size.x * 0.5f, -Z, Y, X, glm::vec2(size.z, size.y), - (shading ? do_tint(0.8f) * tint : tint), + do_tint((1.0f - emission) * 0.8 + emission) * tint, glm::vec3(1.0f), texfaces[1] ); if (cullingBits & 0x1) quad( coord - X * size.x * 0.5f, Z, Y, -X, glm::vec2(size.z, size.y), - (shading ? do_tint(0.9f) * tint : tint), + do_tint((1.0f - emission) * 0.9 + emission) * tint, glm::vec3(1.0f), texfaces[0] ); } diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp index 2bb98cae8..da711b075 100644 --- a/src/graphics/render/MainBatch.hpp +++ b/src/graphics/render/MainBatch.hpp @@ -152,7 +152,7 @@ public: const glm::vec3& size, const UVRegion(&texfaces)[6], const glm::vec4& tint, - bool shading, + float emission, uint8_t cullingBits = 0xFF ); }; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 1233f089c..a4b693829 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -100,7 +100,7 @@ bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) { return indices.blocks.require(v->id).obstacle; } -ubyte Chunks::getLight(const glm::ivec3& pos) const { +light_t Chunks::getLight(const glm::ivec3& pos) const { return getLight(pos.x, pos.y, pos.z); } diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index 94fac08ce..e185ce584 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -76,7 +76,7 @@ public: return get(pos.x, pos.y, pos.z); } - ubyte getLight(const glm::ivec3& pos) const; + light_t getLight(const glm::ivec3& pos) const; light_t getLight(int32_t x, int32_t y, int32_t z) const; ubyte getLight(int32_t x, int32_t y, int32_t z, int channel) const; void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state); From 4d950c974e0bc30e22f178f1e525f526b6ca8496 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 21 Dec 2025 00:28:41 +0300 Subject: [PATCH 08/13] add 'emission' argument to gfx.blockwraps.wrap --- src/graphics/render/BlockWrapsRenderer.cpp | 10 +++++++--- src/graphics/render/BlockWrapsRenderer.hpp | 6 ++++-- src/logic/scripting/lua/libs/libblockwraps.cpp | 3 ++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index c286e28ce..edf2625bf 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -57,7 +57,9 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { glm::vec4 light(1, 1, 1, 0); if (wrapper.emission < 1.0f) { light = Lightmap::extractNormalized(chunks.getLight(wrapper.position)); - light = wrapper.emission + (1.0f - light); + light.r += wrapper.emission; + light.g += wrapper.emission; + light.b += wrapper.emission; } switch (wrapper.modelType) { case BlockModelType::BLOCK: @@ -150,11 +152,13 @@ void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { } u64id_t BlockWrapsRenderer::add( - const glm::ivec3& position, const std::string& texture + const glm::ivec3& position, const std::string& texture, float emission ) { u64id_t id = nextWrapper++; wrappers[id] = std::make_unique(BlockWrapper { - position, {texture, texture, texture, texture, texture, texture}}); + position, + {texture, texture, texture, texture, texture, texture}, + emission}); return id; } diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index 2d14e4a93..84f7f5b91 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -22,7 +22,7 @@ class DrawContext; struct BlockWrapper { glm::ivec3 position; std::array textureFaces {}; - float emission = 1.0f; + float emission = 0.0f; // --- render cache --- util::TextureRegion texRegions[6] {}; @@ -53,7 +53,9 @@ public: void draw(const DrawContext& ctx, const Player& player); - u64id_t add(const glm::ivec3& position, const std::string& texture); + u64id_t add( + const glm::ivec3& position, const std::string& texture, float emission + ); BlockWrapper* get(u64id_t id) const; diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index 30aaa60c6..d4f937ac5 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -9,9 +9,10 @@ using namespace scripting; static int l_wrap(lua::State* L) { auto position = lua::tovec3(L, 1); std::string texture = lua::require_string(L, 2); + float emission = lua::isnumber(L, 3) ? lua::tonumber(L, 3) : 1.0f; return lua::pushinteger( - L, renderer->blockWraps->add(position, std::move(texture)) + L, renderer->blockWraps->add(position, std::move(texture), emission) ); } From c3ab4a160debfb47bcc919bdc7860ffade97d2cb Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 21 Dec 2025 16:11:18 +0300 Subject: [PATCH 09/13] update libgfx-blockwraps.md --- .../scripting/builtins/libgfx-blockwraps.md | 24 ++++++++++++++++- .../scripting/builtins/libgfx-blockwraps.md | 26 +++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/doc/en/scripting/builtins/libgfx-blockwraps.md b/doc/en/scripting/builtins/libgfx-blockwraps.md index e03374dd7..9ab0d27d6 100644 --- a/doc/en/scripting/builtins/libgfx-blockwraps.md +++ b/doc/en/scripting/builtins/libgfx-blockwraps.md @@ -7,7 +7,14 @@ Block wrappers are introduced to implement block destruction animation and can b ```lua -- Creates a wrapper at the specified position, with the specified texture. -- Returns the wrapper id. -gfx.blockwraps.wrap(position: vec3, texture: str) --> int +gfx.blockwraps.wrap( + -- block position + position: vec3, + -- wrap texture + texture: string, + -- emission [0.0; 1.0] + [optional] emission: number = 1.0 +) -> int -- Removes the wrapper, if it exists. gfx.blockwraps.unwrap(id: int) @@ -17,6 +24,21 @@ gfx.blockwraps.set_pos(id: int, position: vec3) -- Changes the texture of the wrapper, if it exists. gfx.blockwraps.set_texture(id: int, texture: str) + +-- Sets the face textures (-X, +X, -Y, +Y, -Z, +Z). +-- - nil - disables face rendering. +-- - "" - monotone texture. +gfx.blockwraps.set_faces( + -- wrapper id + id: int, + -- face texture 1 (-X) + face1?: string, + -- face texture 2 (+X) + face2?: string, + ... + -- face texture 6 (+Z) + face6?: string +) ``` Wrappers are not automatically removed without calling `unwrap`. diff --git a/doc/ru/scripting/builtins/libgfx-blockwraps.md b/doc/ru/scripting/builtins/libgfx-blockwraps.md index 645df7ec9..aaecfebe6 100644 --- a/doc/ru/scripting/builtins/libgfx-blockwraps.md +++ b/doc/ru/scripting/builtins/libgfx-blockwraps.md @@ -8,7 +8,14 @@ ```lua -- Создаёт обертку на указанной позиции, с указанной текстурой. -- Возвращает id обёртки. -gfx.blockwraps.wrap(position: vec3, texture: string) -> int +gfx.blockwraps.wrap( + -- Позиция блока + position: vec3, + -- Текстура обёртки + texture: string, + -- Излучение [0.0; 1.0] + [опционально] emission: number = 1.0 +) -> int -- Удаляет обертку, если она существует. gfx.blockwraps.unwrap(id: int) @@ -18,6 +25,21 @@ gfx.blockwraps.set_pos(id: int, position: vec3) -- Меняет текстуру обёртки, если она существует. gfx.blockwraps.set_texture(id: int, texture: string) + +-- Устанавливает текстуры сторон (-X, +X, -Y, +Y, -Z, +Z). +-- - nil - отключает отображение стороны. +-- - "" - монотонная текстура. +gfx.blockwraps.set_faces( + -- id обёртки + id: int, + -- текстура стороны 1 (-X) + face1?: string, + -- текстура стороны 2 (+X) + face2?: string, + ... + -- текстура стороны 6 (+Z) + face6?: string +) ``` -Обертки не удаляются автоматически без вызова `unwrap`. \ No newline at end of file +Обертки не удаляются автоматически без вызова `unwrap`. From e423c746280c690ab26a217b1e8668253cdd1372 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 21 Dec 2025 16:16:08 +0300 Subject: [PATCH 10/13] fix gfx.blockwraps.set_texture --- src/logic/scripting/lua/libs/libblockwraps.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index d4f937ac5..1868aca53 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -33,6 +33,7 @@ static int l_set_texture(lua::State* L) { for (int i = 0; i < wrapper->textureFaces.size(); i++) { wrapper->textureFaces[i] = lua::require_string(L, 2); } + wrapper->dirtySides = 0xFF; } return 0; } From c47432c979ab83ad9b7659f3da58acffb030dd6c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 21 Dec 2025 16:44:12 +0300 Subject: [PATCH 11/13] add gfx.blockwraps.set_tints --- src/graphics/render/BlockWrapsRenderer.cpp | 8 +++++- src/graphics/render/BlockWrapsRenderer.hpp | 17 +++++++----- src/graphics/render/MainBatch.cpp | 27 ++++++++++--------- src/graphics/render/MainBatch.hpp | 3 ++- .../scripting/lua/libs/libblockwraps.cpp | 21 ++++++++++++++- 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index edf2625bf..24a7955b8 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -68,6 +68,7 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { glm::vec3(1.01f), wrapper.uvRegions, light, + wrapper.tints.data(), wrapper.emission, cullingBits ); @@ -82,6 +83,7 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { size * glm::vec3(1.01f), wrapper.uvRegions, light, + wrapper.tints.data(), wrapper.emission, cullingBits ); @@ -152,12 +154,16 @@ void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { } u64id_t BlockWrapsRenderer::add( - const glm::ivec3& position, const std::string& texture, float emission + const glm::ivec3& position, + const std::string& texture, + const glm::vec3& tint, + float emission ) { u64id_t id = nextWrapper++; wrappers[id] = std::make_unique(BlockWrapper { position, {texture, texture, texture, texture, texture, texture}, + {tint, tint, tint, tint, tint, tint}, emission}); return id; } diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index 84f7f5b91..f19bf6b66 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -1,15 +1,16 @@ #pragma once +#include "assets/assets_util.hpp" +#include "voxels/Block.hpp" +#include "MainBatch.hpp" +#include "typedefs.hpp" + #include #include #include #include #include - -#include "assets/assets_util.hpp" -#include "voxels/Block.hpp" -#include "MainBatch.hpp" -#include "typedefs.hpp" +#include class Assets; class Player; @@ -22,6 +23,7 @@ class DrawContext; struct BlockWrapper { glm::ivec3 position; std::array textureFaces {}; + std::array tints {}; float emission = 0.0f; // --- render cache --- @@ -54,7 +56,10 @@ public: void draw(const DrawContext& ctx, const Player& player); u64id_t add( - const glm::ivec3& position, const std::string& texture, float emission + const glm::ivec3& position, + const std::string& texture, + const glm::vec3& tint, + float emission ); BlockWrapper* get(u64id_t id) const; diff --git a/src/graphics/render/MainBatch.cpp b/src/graphics/render/MainBatch.cpp index 1498e1537..5b08ffe04 100644 --- a/src/graphics/render/MainBatch.cpp +++ b/src/graphics/render/MainBatch.cpp @@ -86,7 +86,8 @@ void MainBatch::cube( const glm::vec3& coord, const glm::vec3& size, const UVRegion(&texfaces)[6], - const glm::vec4& tint, + const glm::vec4& lights, + const glm::vec3 tints[], float emission, uint8_t cullingBits ) { @@ -98,42 +99,42 @@ void MainBatch::cube( quad( coord + Z * size.z * 0.5f, X, Y, Z, glm::vec2(size.x, size.y), - do_tint((1.0f - emission) * 0.8 + emission) * tint, - glm::vec3(1.0f), texfaces[5] + do_tint((1.0f - emission) * 0.8 + emission) * lights, + tints[5], texfaces[5] ); if (cullingBits & 0x10) quad( coord - Z * size.z * 0.5f, -X, Y, -Z, glm::vec2(size.x, size.y), - do_tint((1.0f - emission) * 0.9 + emission) * tint, - glm::vec3(1.0f), texfaces[4] + do_tint((1.0f - emission) * 0.9 + emission) * lights, + tints[4], texfaces[4] ); if (cullingBits & 0x8) quad( coord + Y * size.y * 0.5f, -X, Z, Y, glm::vec2(size.x, size.z), - do_tint((1.0f - emission) * 1.0 + emission) * tint, - glm::vec3(1.0f), texfaces[3] + do_tint((1.0f - emission) * 1.0 + emission) * lights, + tints[3], texfaces[3] ); if (cullingBits & 0x4) quad( coord - Y * size.y * 0.5f, X, Z, -Y, glm::vec2(size.x, size.z), - do_tint((1.0f - emission) * 0.7 + emission) * tint, - glm::vec3(1.0f), texfaces[2] + do_tint((1.0f - emission) * 0.7 + emission) * lights, + tints[2], texfaces[2] ); if (cullingBits & 0x2) quad( coord + X * size.x * 0.5f, -Z, Y, X, glm::vec2(size.z, size.y), - do_tint((1.0f - emission) * 0.8 + emission) * tint, - glm::vec3(1.0f), texfaces[1] + do_tint((1.0f - emission) * 0.8 + emission) * lights, + tints[1], texfaces[1] ); if (cullingBits & 0x1) quad( coord - X * size.x * 0.5f, Z, Y, -X, glm::vec2(size.z, size.y), - do_tint((1.0f - emission) * 0.9 + emission) * tint, - glm::vec3(1.0f), texfaces[0] + do_tint((1.0f - emission) * 0.9 + emission) * lights, + tints[0], texfaces[0] ); } diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp index da711b075..8ad119199 100644 --- a/src/graphics/render/MainBatch.hpp +++ b/src/graphics/render/MainBatch.hpp @@ -151,7 +151,8 @@ public: const glm::vec3& coord, const glm::vec3& size, const UVRegion(&texfaces)[6], - const glm::vec4& tint, + const glm::vec4& lights, + const glm::vec3 tints[], float emission, uint8_t cullingBits = 0xFF ); diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index 1868aca53..5b28f7dbb 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -10,9 +10,13 @@ static int l_wrap(lua::State* L) { auto position = lua::tovec3(L, 1); std::string texture = lua::require_string(L, 2); float emission = lua::isnumber(L, 3) ? lua::tonumber(L, 3) : 1.0f; + glm::vec3 tint = lua::istable(L, 4) ? lua::tovec3(L, 4) : glm::vec3(1.0f); return lua::pushinteger( - L, renderer->blockWraps->add(position, std::move(texture), emission) + L, + renderer->blockWraps->add( + position, std::move(texture), std::move(tint), emission + ) ); } @@ -60,11 +64,26 @@ static int l_set_faces(lua::State* L) { return 0; } +static int l_set_tints(lua::State* L) { + if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { + for (int i = 0; i < wrapper->textureFaces.size(); i++) { + if (lua::isnil(L, 2 + i)) { + wrapper->tints[i] = glm::vec3(1.0f); + } else { + wrapper->tints[i] = lua::tovec3(L, 2 + i); + } + } + wrapper->dirtySides = 0xFF; + } + return 0; +} + const luaL_Reg blockwrapslib[] = { {"wrap", lua::wrap}, {"unwrap", lua::wrap}, {"set_pos", lua::wrap}, {"set_texture", lua::wrap}, {"set_faces", lua::wrap}, + {"set_tints", lua::wrap}, {nullptr, nullptr} }; From 7a83f38c91c5d2793fb43d911fe9975d5724e096 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 21 Dec 2025 16:46:36 +0300 Subject: [PATCH 12/13] update doc/*/scripting/builtins/libgfx-blockwraps.md --- doc/en/scripting/builtins/libgfx-blockwraps.md | 14 ++++++++++++++ doc/ru/scripting/builtins/libgfx-blockwraps.md | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/doc/en/scripting/builtins/libgfx-blockwraps.md b/doc/en/scripting/builtins/libgfx-blockwraps.md index 9ab0d27d6..3702f2e24 100644 --- a/doc/en/scripting/builtins/libgfx-blockwraps.md +++ b/doc/en/scripting/builtins/libgfx-blockwraps.md @@ -39,6 +39,20 @@ gfx.blockwraps.set_faces( -- face texture 6 (+Z) face6?: string ) + +-- Sets the tint of the sides (-X, +X, -Y, +Y, -Z, +Z). +-- RGB [0.0; 1.0] +gfx.blockwraps.set_tints( + -- wrapper id + id: int, + -- side 1 color (-X) + face1?: vec3, + -- side 2 color (+X) + face2?: vec3, + ... + -- side 6 color (+Z) + face6?: vec3 +) ``` Wrappers are not automatically removed without calling `unwrap`. diff --git a/doc/ru/scripting/builtins/libgfx-blockwraps.md b/doc/ru/scripting/builtins/libgfx-blockwraps.md index aaecfebe6..ca39e3ed9 100644 --- a/doc/ru/scripting/builtins/libgfx-blockwraps.md +++ b/doc/ru/scripting/builtins/libgfx-blockwraps.md @@ -40,6 +40,20 @@ gfx.blockwraps.set_faces( -- текстура стороны 6 (+Z) face6?: string ) + +-- Устанавливает окраску сторон (-X, +X, -Y, +Y, -Z, +Z). +-- RGB [0.0; 1.0] +gfx.blockwraps.set_tints( + -- id обёртки + id: int, + -- цвет стороны 1 (-X) + face1?: vec3, + -- цвет стороны 2 (+X) + face2?: vec3, + ... + -- цвет стороны 6 (+Z) + face6?: vec3 +) ``` Обертки не удаляются автоматически без вызова `unwrap`. From e9b6fe6204a64705f822f951dc509e0ea7493a81 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 21 Dec 2025 17:04:03 +0300 Subject: [PATCH 13/13] fix doc/en/scripting/builtins/libgfx-blockwraps.md --- doc/en/scripting/builtins/libgfx-blockwraps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/scripting/builtins/libgfx-blockwraps.md b/doc/en/scripting/builtins/libgfx-blockwraps.md index 3702f2e24..7c99210ef 100644 --- a/doc/en/scripting/builtins/libgfx-blockwraps.md +++ b/doc/en/scripting/builtins/libgfx-blockwraps.md @@ -55,4 +55,4 @@ gfx.blockwraps.set_tints( ) ``` -Wrappers are not automatically removed without calling `unwrap`. +Wrappers will not be automatically removed without calling `unwrap`.