Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/client/attachable/Geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,13 +400,14 @@ namespace perlin::attachable {
}
}
for (int i = 0; i < 6; i++) {
if (!c.boxUv && !c.faces[i].present)
continue;
int fi = i;
const bool mirrored = c.mirror != mirrorTextures;
bool flip = mirrored;
if (mirrored && i < 2)
fi = 1 - i;
// the x mirror moves east/west to the other side: a face the cube lists sits on that other side
if (!c.boxUv && !c.faces[fi].present)
continue;
const FaceDef& f = faces[i];
const glm::vec2 o = uvOrigin[fi], s = uvSize[fi];
glm::vec2 a = o, b = o + glm::vec2(s.x, 0), cc = o + s, dd = o + glm::vec2(0, s.y);
Expand Down
4 changes: 4 additions & 0 deletions src/client/entity/EntityAssets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ namespace perlin::entity {
if (entry.IsObject())
for (const auto& [pattern, expr] : entry.object)
rc.parts.push_back({LowerCase(pattern), ParseValue(expr)});
if (const Json* il = def.Find("ignore_lighting"); il && il->IsBool())
rc.ignoreLighting = il->boolean;
if (const Json* lm = def.Find("light_color_multiplier"); lm && lm->IsNumber())
rc.lightMultiplier = static_cast<float>(lm->number);
if (const Json* c = def.Find("color"); c && c->IsObject()) {
rc.hasColor = true;
static const char* kKeys[4] = {"r", "g", "b", "a"};
Expand Down
3 changes: 3 additions & 0 deletions src/client/entity/EntityAssets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ namespace perlin::entity {
ExprPtr color[4];
bool hasColor = false;
bool translucent = false;
// ignore_lighting: drawn at full brightness whatever the world light where the actor stands
bool ignoreLighting = false;
float lightMultiplier = 1.0f;
};

class EntityAssets {
Expand Down
14 changes: 12 additions & 2 deletions src/client/entity/EntityRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,8 @@ namespace perlin::entity {
}
}
layer.translucent = rc->translucent;
layer.ignoreLighting = rc->ignoreLighting;
layer.lightMultiplier = rc->lightMultiplier;
for (const std::string& group : groups) {
const bool single = groups.size() == 1;
const attachable::BoneFilter groupFilter =
Expand Down Expand Up @@ -1412,12 +1414,13 @@ namespace perlin::entity {
const float layerHurt = layer.material.hurtTint ? hurt : 0.0f;
const bool fullbright = layer.material.emissive == 2;
const glm::vec3 tint(layer.tint[0], layer.tint[1], layer.tint[2]);
const glm::vec3 layerLight = layer.ignoreLighting ? glm::vec3(layer.lightMultiplier) : light;
for (const attachable::Quad& q : layer.quads) {
const glm::vec3 n = rot * q.n;
const float lit = std::min(
1.0f, (std::max(0.0f, glm::dot(n, l0)) + std::max(0.0f, glm::dot(n, l1))) * 0.6f + 0.4f);
const uint32_t color = fullbright || packLit ? PackColor(tint, layer.tint[3])
: PackColor(light * lit * tint, layer.tint[3]);
: PackColor(layerLight * lit * tint, layer.tint[3]);
const uint32_t base = static_cast<uint32_t>(vertices.size());
for (int i = 0; i < 4; i++)
vertices.push_back({q.p[i].x, q.p[i].y, q.p[i].z, color, q.uv[i].x, q.uv[i].y});
Expand Down Expand Up @@ -1454,7 +1457,7 @@ namespace perlin::entity {
draw.material = DrawMaterial::Entity;
draw.player = e.isPlayer;
draw.entityType = e.type.c_str();
if (fullbright) {
if (fullbright || layer.ignoreLighting) {
draw.blockLight = 15;
draw.skyLight = 15;
} else if (levels.x >= 0) {
Expand All @@ -1472,6 +1475,13 @@ namespace perlin::entity {
draw.depthWrite = layer.material.depthWrite && draw.blend != 2;
draw.depth = layer.material.depthTest;
draw.depthFunc = layer.material.depthFunc;
// one-sided materials (no DisableCulling) hide faces seen from behind: some packs build a background
// box from inward-facing planes that must not cover the model; the world mirrors model z, which
// turns the faces' winding around
CullMode cull = layer.material.noCull ? CullMode::None : layer.material.cull;
if (cull != CullMode::None && glm::determinant(glm::mat3(model)) < 0.0f)
cull = cull == CullMode::Back ? CullMode::Front : CullMode::Back;
draw.cull = cull;
draw.colorWrite = layer.material.colorWrite;
draw.alphaWrite = layer.material.alphaWrite;
if (layer.material.customBlend && layer.material.blend != Blend::AlphaTest &&
Expand Down
2 changes: 2 additions & 0 deletions src/client/entity/EntityRenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ namespace perlin::entity {
std::string texture;
bool translucent = false;
float tint[4] = {1, 1, 1, 1};
bool ignoreLighting = false;
float lightMultiplier = 1.0f;
MaterialInfo material;
uint32_t maskRgb = 0xFFFFFF;
// entity's own model; invisibility hides it, keeps armor and attached items
Expand Down
Loading