Merge pull request #975 from MihailRis/skeleton-bones-opacity

skeleton bones opacity
This commit is contained in:
MihailRis 2026-09-17 00:13:06 +03:00 • committed by GitHub
commit 80e45d7f49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 178 additions and 123 deletions

View file

@ -190,10 +190,14 @@ rig:is_visible([optional] index: int) -> bool
rig:set_visible([optional] index: int, status: bool) rig:set_visible([optional] index: int, status: bool)
-- Returns the color of the entity -- Returns the color of the entity
rig:get_color() -> vec3 rig:get_color() -> vec4
-- Return the color of the bone by index
rig:get_color(index: int) -> vec4
-- Sets the color of the entity -- Sets the color of the entity
rig:set_color(color: vec3) rig:set_color(color: vec3 | vec4)
-- Sets the color of the bone by index
rig:set_color(color: vec3 | vec4, index: int)
``` ```
> [!WARNING] > [!WARNING]

View file

@ -179,10 +179,14 @@ rig:is_visible([optional] index: int) -> bool
rig:set_visible([optional] index: int, status: bool) rig:set_visible([optional] index: int, status: bool)
-- Возвращает цвет сущности -- Возвращает цвет сущности
rig:get_color() -> vec3 rig:get_color() -> vec4
-- Возвращает цвет кости по индексу
rig:get_color(index: int) -> vec4
-- Устанавливает цвет сущности -- Устанавливает цвет сущности
rig:set_color(color: vec3) rig:set_color(color: vec3 | vec4)
-- Устанавливает цвет кости по индексу
rig:set_color(color: vec3 | vec4, index: int)
``` ```
## Пользовательские компоненты ## Пользовательские компоненты

View file

@ -58,8 +58,8 @@ local Skeleton = {__index={
index=function(self, s) return __skeleton.index(self.eid, s) end, index=function(self, s) return __skeleton.index(self.eid, s) end,
is_visible=function(self, i) return __skeleton.is_visible(self.eid, i) end, is_visible=function(self, i) return __skeleton.is_visible(self.eid, i) end,
set_visible=function(self, i, b) return __skeleton.set_visible(self.eid, i, b) end, set_visible=function(self, i, b) return __skeleton.set_visible(self.eid, i, b) end,
get_color=function(self) return __skeleton.get_color(self.eid) end, get_color=function(self, ...) return __skeleton.get_color(self.eid, ...) end,
set_color=function(self, color) return __skeleton.set_color(self.eid, color) end, set_color=function(self, color, ...) return __skeleton.set_color(self.eid, color, ...) end,
set_interpolated=function(self, b) return __skeleton.set_interpolated(self.eid, b) end, set_interpolated=function(self, b) return __skeleton.set_interpolated(self.eid, b) end,
}} }}

View file

@ -2,7 +2,7 @@
layout (location = 0) in vec3 v_position; layout (location = 0) in vec3 v_position;
layout (location = 1) in vec2 v_texCoord; layout (location = 1) in vec2 v_texCoord;
layout (location = 2) in vec3 v_color; layout (location = 2) in vec4 v_color;
layout (location = 3) in vec4 v_light; layout (location = 3) in vec4 v_light;
layout (location = 4) in vec4 v_normal; layout (location = 4) in vec4 v_normal;
@ -29,8 +29,8 @@ void main() {
a_dir = a_modelpos.xyz - u_cameraPos; a_dir = a_modelpos.xyz - u_cameraPos;
vec3 skyLightColor = pick_sky_color(u_skybox, u_dayTime, u_minSkyLight); vec3 skyLightColor = pick_sky_color(u_skybox, u_dayTime, u_minSkyLight);
a_color.rgb = max(a_color.rgb, skyLightColor.rgb * v_light.a) * v_color; a_color.rgb = max(a_color.rgb, skyLightColor.rgb * v_light.a) * v_color.rgb;
a_color.a = u_opacity; a_color.a = u_opacity * v_color.a;
mat4 viewmodel = u_view * u_model; mat4 viewmodel = u_view * u_model;
a_distance = length(viewmodel * vec4(pos3d, 0.0)); a_distance = length(viewmodel * vec4(pos3d, 0.0));

View file

@ -46,7 +46,8 @@ Skeleton::Skeleton(std::shared_ptr<const SkeletonConfig> config)
flags(config ? config->getBones().size() : 0), flags(config ? config->getBones().size() : 0),
textures(), textures(),
modelOverrides(config ? config->getBones().size() : 0), modelOverrides(config ? config->getBones().size() : 0),
visible(true) { visible(true),
boneTints(config ? config->getBones().size() : 0, glm::vec4(1.0f)) {
if (config == nullptr) { if (config == nullptr) {
return; return;
} }
@ -99,6 +100,7 @@ void Skeleton::setConfig(std::shared_ptr<const SkeletonConfig> rigConfig) {
modelOverrides.resize(bonesCount); modelOverrides.resize(bonesCount);
flags.resize(bonesCount); flags.resize(bonesCount);
boneTints.resize(bonesCount, glm::vec4(1.0f));
for (size_t i = 0; i < bonesCount; i++) { for (size_t i = 0; i < bonesCount; i++) {
flags[i].visible = true; flags[i].visible = true;
@ -204,7 +206,7 @@ void SkeletonConfig::render(
if (model) { if (model) {
batch.draw( batch.draw(
skeleton.calculated.matrices[i], skeleton.calculated.matrices[i],
skeleton.tint, skeleton.tint * skeleton.boneTints[i],
model, model,
&skeleton.textures &skeleton.textures
); );

View file

@ -85,7 +85,8 @@ namespace rigging {
std::unordered_map<std::string, std::string> textures; std::unordered_map<std::string, std::string> textures;
std::vector<ModelReference> modelOverrides; std::vector<ModelReference> modelOverrides;
bool visible; bool visible;
glm::vec3 tint {1.0f, 1.0f, 1.0f}; glm::vec4 tint {1.0f, 1.0f, 1.0f, 1.0f};
std::vector<glm::vec4> boneTints;
util::VecInterpolation<3, float> interpolation {false}; util::VecInterpolation<3, float> interpolation {false};

View file

@ -161,7 +161,7 @@ void BlockWrapsRenderer::draw(const DrawContext& pctx) {
u64id_t BlockWrapsRenderer::add( u64id_t BlockWrapsRenderer::add(
const glm::ivec3& position, const glm::ivec3& position,
const std::string& texture, const std::string& texture,
const glm::vec3& tint, const glm::vec4& tint,
float emission float emission
) { ) {
u64id_t id = nextWrapper++; u64id_t id = nextWrapper++;

View file

@ -20,7 +20,7 @@ class DrawContext;
struct BlockWrapper { struct BlockWrapper {
glm::ivec3 position; glm::ivec3 position;
std::array<std::string, 6> textureFaces {}; std::array<std::string, 6> textureFaces {};
std::array<glm::vec3, 6> tints {}; std::array<glm::vec4, 6> tints {};
float emission = 0.0f; float emission = 0.0f;
// --- render cache --- // --- render cache ---
@ -56,7 +56,7 @@ public:
u64id_t add( u64id_t add(
const glm::ivec3& position, const glm::ivec3& position,
const std::string& texture, const std::string& texture,
const glm::vec3& tint, const glm::vec4& tint,
float emission float emission
); );

View file

@ -82,12 +82,75 @@ inline glm::vec4 do_tint(float value) {
return {value, value, value, 1.0f}; return {value, value, value, 1.0f};
} }
void MainBatch::quad(
const glm::vec3& pos,
const glm::vec3& right,
const glm::vec3& up,
const glm::vec3& normal,
const glm::vec2& size,
const glm::vec4& light,
const glm::vec4& tint,
const UVRegion& subregion,
float emission
) {
prepare(6);
vertex(
pos - right * size.x * 0.5f - up * size.y * 0.5f,
{subregion.u1, subregion.v1},
light,
tint,
normal,
emission
);
vertex(
pos + right * size.x * 0.5f - up * size.y * 0.5f,
{subregion.u2, subregion.v1},
light,
tint,
normal,
emission
);
vertex(
pos + right * size.x * 0.5f + up * size.y * 0.5f,
{subregion.u2, subregion.v2},
light,
tint,
normal,
emission
);
vertex(
pos - right * size.x * 0.5f - up * size.y * 0.5f,
{subregion.u1, subregion.v1},
light,
tint,
normal,
emission
);
vertex(
pos + right * size.x * 0.5f + up * size.y * 0.5f,
{subregion.u2, subregion.v2},
light,
tint,
normal,
emission
);
vertex(
pos - right * size.x * 0.5f + up * size.y * 0.5f,
{subregion.u1, subregion.v2},
light,
tint,
normal,
emission
);
}
void MainBatch::cube( void MainBatch::cube(
const glm::vec3& coord, const glm::vec3& coord,
const glm::vec3& size, const glm::vec3& size,
const UVRegion(&texfaces)[6], const UVRegion(&texfaces)[6],
const glm::vec4& lights, const glm::vec4& lights,
const glm::vec3 tints[], const glm::vec4 tints[],
float emission, float emission,
uint8_t cullingBits uint8_t cullingBits
) { ) {

View file

@ -17,30 +17,20 @@ class Chunks;
struct MainBatchVertex { struct MainBatchVertex {
glm::vec3 position; glm::vec3 position;
glm::vec2 uv; glm::vec2 uv;
glm::vec3 tint; glm::vec4 tint;
std::array<uint8_t, 4> color; std::array<uint8_t, 4> color;
std::array<uint8_t, 4> normal; std::array<uint8_t, 4> normal;
static constexpr VertexAttribute ATTRIBUTES[] = { static constexpr VertexAttribute ATTRIBUTES[] = {
{VertexAttribute::Type::FLOAT, false, 3}, {VertexAttribute::Type::FLOAT, false, 3},
{VertexAttribute::Type::FLOAT, false, 2}, {VertexAttribute::Type::FLOAT, false, 2},
{VertexAttribute::Type::FLOAT, false, 3}, {VertexAttribute::Type::FLOAT, false, 4},
{VertexAttribute::Type::UNSIGNED_BYTE, true, 4}, {VertexAttribute::Type::UNSIGNED_BYTE, true, 4},
{VertexAttribute::Type::UNSIGNED_BYTE, true, 4}, {VertexAttribute::Type::UNSIGNED_BYTE, true, 4},
{{}, 0}}; {{}, 0}};
}; };
class MainBatch { class MainBatch {
std::unique_ptr<MainBatchVertex[]> const buffer;
size_t const capacity;
size_t index;
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
std::unique_ptr<Mesh<MainBatchVertex>> mesh;
std::unique_ptr<Texture> blank;
const Texture* texture = nullptr;
public: public:
/// xyz, uv, color, compressed lights /// xyz, uv, color, compressed lights
@ -63,7 +53,7 @@ public:
const glm::vec3& pos, const glm::vec3& pos,
const glm::vec2& uv, const glm::vec2& uv,
const glm::vec4& light, const glm::vec4& light,
const glm::vec3& tint, const glm::vec4& tint,
const glm::vec3& normal, const glm::vec3& normal,
float emission float emission
) { ) {
@ -84,76 +74,36 @@ public:
index++; index++;
} }
inline void quad( void quad(
const glm::vec3& pos, const glm::vec3& pos,
const glm::vec3& right, const glm::vec3& right,
const glm::vec3& up, const glm::vec3& up,
const glm::vec3& normal, const glm::vec3& normal,
const glm::vec2& size, const glm::vec2& size,
const glm::vec4& light, const glm::vec4& light,
const glm::vec3& tint, const glm::vec4& tint,
const UVRegion& subregion, const UVRegion& subregion,
float emission = 0.0f float emission = 0.0f
) { );
prepare(6);
vertex(
pos - right * size.x * 0.5f - up * size.y * 0.5f,
{subregion.u1, subregion.v1},
light,
tint,
normal,
emission
);
vertex(
pos + right * size.x * 0.5f - up * size.y * 0.5f,
{subregion.u2, subregion.v1},
light,
tint,
normal,
emission
);
vertex(
pos + right * size.x * 0.5f + up * size.y * 0.5f,
{subregion.u2, subregion.v2},
light,
tint,
normal,
emission
);
vertex(
pos - right * size.x * 0.5f - up * size.y * 0.5f,
{subregion.u1, subregion.v1},
light,
tint,
normal,
emission
);
vertex(
pos + right * size.x * 0.5f + up * size.y * 0.5f,
{subregion.u2, subregion.v2},
light,
tint,
normal,
emission
);
vertex(
pos - right * size.x * 0.5f + up * size.y * 0.5f,
{subregion.u1, subregion.v2},
light,
tint,
normal,
emission
);
}
void cube( void cube(
const glm::vec3& coord, const glm::vec3& coord,
const glm::vec3& size, const glm::vec3& size,
const UVRegion(&texfaces)[6], const UVRegion(&texfaces)[6],
const glm::vec4& lights, const glm::vec4& lights,
const glm::vec3 tints[], const glm::vec4 tints[],
float emission, float emission,
uint8_t cullingBits = 0xFF uint8_t cullingBits = 0xFF
); );
private:
std::unique_ptr<MainBatchVertex[]> const buffer;
size_t const capacity;
size_t index;
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
std::unique_ptr<Mesh<MainBatchVertex>> mesh;
std::unique_ptr<Texture> blank;
const Texture* texture = nullptr;
}; };

View file

@ -61,8 +61,8 @@ void ModelBatch::draw(
const model::Mesh& mesh, const model::Mesh& mesh,
const glm::mat4& matrix, const glm::mat4& matrix,
const glm::mat3& rotation, const glm::mat3& rotation,
glm::vec3 tint, const glm::vec4& tint,
const texture_names_map* varTextures, const TextureNamesMap* varTextures,
bool backlight bool backlight
) { ) {
setTexture(mesh.texture, varTextures); setTexture(mesh.texture, varTextures);
@ -97,10 +97,12 @@ void ModelBatch::draw(
} }
} }
void ModelBatch::draw(glm::mat4 matrix, void ModelBatch::draw(
glm::vec3 tint, const glm::mat4& matrix,
const model::Model* model, const glm::vec4& tint,
const texture_names_map* varTextures) { const model::Model* model,
const TextureNamesMap* varTextures
) {
for (const auto& mesh : model->meshes) { for (const auto& mesh : model->meshes) {
entries.push_back({ entries.push_back({
matrix, extract_rotation(matrix), tint, &mesh, varTextures matrix, extract_rotation(matrix), tint, &mesh, varTextures
@ -134,7 +136,7 @@ void ModelBatch::setLightsOffset(const glm::vec3& offset) {
} }
void ModelBatch::setTexture(const std::string& name, void ModelBatch::setTexture(const std::string& name,
const texture_names_map* varTextures) { const TextureNamesMap* varTextures) {
if (varTextures && !name.empty() && name.at(0) == '$') { if (varTextures && !name.empty() && name.at(0) == '$') {
const auto& found = varTextures->find(name); const auto& found = varTextures->find(name);
if (found == varTextures->end()) { if (found == varTextures->end()) {

View file

@ -18,9 +18,28 @@ namespace model {
struct Model; struct Model;
} }
using texture_names_map = std::unordered_map<std::string, std::string>; using TextureNamesMap = std::unordered_map<std::string, std::string>;
class ModelBatch { class ModelBatch {
public:
ModelBatch(
size_t capacity,
const Assets& assets,
const Chunks& chunks,
const EngineSettings& settings
);
~ModelBatch();
void draw(
const glm::mat4& matrix,
const glm::vec4& tint,
const model::Model* model,
const TextureNamesMap* varTextures
);
void render();
void setLightsOffset(const glm::vec3& offset);
private:
const Assets& assets; const Assets& assets;
const Chunks& chunks; const Chunks& chunks;
@ -31,38 +50,24 @@ class ModelBatch {
std::unique_ptr<MainBatch> batch; std::unique_ptr<MainBatch> batch;
void draw(const model::Mesh& mesh, void draw(
const glm::mat4& matrix, const model::Mesh& mesh,
const glm::mat3& rotation, const glm::mat4& matrix,
glm::vec3 tint, const glm::mat3& rotation,
const texture_names_map* varTextures, const glm::vec4& tint,
bool backlight); const TextureNamesMap* varTextures,
bool backlight
);
void setTexture(const std::string& name, void setTexture(const std::string& name,
const texture_names_map* varTextures); const TextureNamesMap* varTextures);
struct DrawEntry { struct DrawEntry {
glm::mat4 matrix; glm::mat4 matrix;
glm::mat3 rotation; glm::mat3 rotation;
glm::vec3 tint; glm::vec4 tint;
const model::Mesh* mesh; const model::Mesh* mesh;
const texture_names_map* varTextures; const TextureNamesMap* varTextures;
}; };
std::vector<DrawEntry> entries; std::vector<DrawEntry> entries;
public:
ModelBatch(
size_t capacity,
const Assets& assets,
const Chunks& chunks,
const EngineSettings& settings
);
~ModelBatch();
void draw(glm::mat4 matrix,
glm::vec3 tint,
const model::Model* model,
const texture_names_map* varTextures);
void render();
void setLightsOffset(const glm::vec3& offset);
}; };

View file

@ -160,7 +160,7 @@ void ParticlesRenderer::renderParticle(
-camera.front, -camera.front,
preset.size * scale, preset.size * scale,
light, light,
glm::vec3(1.0f), glm::vec4(1.0f),
particle.region, particle.region,
preset.lighting ? 0.0f : 1.0f preset.lighting ? 0.0f : 1.0f
); );

View file

@ -151,7 +151,7 @@ void PrecipitationRenderer::render(
glm::cross(glm::vec3(0, 1, 0), face.right), glm::cross(glm::vec3(0, 1, 0), face.right),
FACE_SIZE, FACE_SIZE,
light_at(chunks, pos.x, y, pos.z), light_at(chunks, pos.x, y, pos.z),
glm::vec3(1.0f), glm::vec4(1.0f),
calc_uv(pos, face.right, timer, weather) calc_uv(pos, face.right, timer, weather)
); );
} }

View file

@ -147,8 +147,19 @@ static int l_set_visible(lua::State* L) {
return 0; return 0;
} }
static glm::vec4 to_color(lua::State* L, int idx) {
if (lua::objlen(L, idx) > 3) {
return lua::tovec4(L, idx);
}
return glm::vec4(lua::tovec3(L, idx), 1.0f);
}
static int l_get_color(lua::State* L) { static int l_get_color(lua::State* L) {
if (auto skeleton = get_skeleton(L)) { if (auto skeleton = get_skeleton(L)) {
if (lua::isnumber(L, 2)) {
auto index = index_range_check(*skeleton, lua::tointeger(L, 2));
return lua::pushvec(L, skeleton->boneTints[index]);
}
return lua::pushvec(L, skeleton->tint); return lua::pushvec(L, skeleton->tint);
} }
return 0; return 0;
@ -156,7 +167,13 @@ static int l_get_color(lua::State* L) {
static int l_set_color(lua::State* L) { static int l_set_color(lua::State* L) {
if (auto skeleton = get_skeleton(L)) { if (auto skeleton = get_skeleton(L)) {
skeleton->tint = lua::tovec3(L, 2); auto color = to_color(L, 2);
if (lua::isnumber(L, 3)) {
auto index = index_range_check(*skeleton, lua::tointeger(L, 3));
skeleton->boneTints[index] = color;
} else {
skeleton->tint = color;
}
} }
return 0; return 0;
} }

View file

@ -10,7 +10,11 @@ static int l_wrap(lua::State* L) {
auto position = lua::tovec3(L, 1); auto position = lua::tovec3(L, 1);
std::string texture = lua::require_string(L, 2); std::string texture = lua::require_string(L, 2);
float emission = lua::isnumber(L, 3) ? lua::tonumber(L, 3) : 1.0f; 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); glm::vec4 tint =
lua::istable(L, 4)
? (lua::objlen(L, 4) > 3 ? lua::tovec4(L, 4)
: glm::vec4(lua::tovec3(L, 4), 1.0f))
: glm::vec4(1.0f);
return lua::pushinteger( return lua::pushinteger(
L, L,
@ -72,9 +76,12 @@ static int l_set_tints(lua::State* L) {
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
for (int i = 0; i < wrapper->textureFaces.size(); i++) { for (int i = 0; i < wrapper->textureFaces.size(); i++) {
if (lua::isnil(L, 2 + i)) { if (lua::isnil(L, 2 + i)) {
wrapper->tints[i] = glm::vec3(1.0f); wrapper->tints[i] = glm::vec4(1.0f);
} else { } else {
wrapper->tints[i] = lua::tovec3(L, 2 + i); wrapper->tints[i] =
lua::objlen(L, 2 + i) > 3
? lua::tovec4(L, 2 + i)
: glm::vec4(lua::tovec3(L, 2 + i), 1.0f);
} }
} }
} }