1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Rework use_texture_alpha to provide three opaque/clip/blend modes

The change that turns nodeboxes and meshes opaque when possible is kept,
as is the compatibility code that warns modders to adjust their nodedefs.
This commit is contained in:
sfan5 2021-01-17 01:56:50 +01:00
parent edd8c3c664
commit 83229921e5
8 changed files with 164 additions and 66 deletions

View file

@ -360,7 +360,7 @@ void ContentFeatures::reset()
i = TileDef();
for (auto &j : tiledef_special)
j = TileDef();
alpha = 255;
alpha = ALPHAMODE_OPAQUE;
post_effect_color = video::SColor(0, 0, 0, 0);
param_type = CPT_NONE;
param_type_2 = CPT2_NONE;
@ -405,6 +405,31 @@ void ContentFeatures::reset()
node_dig_prediction = "air";
}
void ContentFeatures::setAlphaFromLegacy(u8 legacy_alpha)
{
// No special handling for nodebox/mesh here as it doesn't make sense to
// throw warnings when the server is too old to support the "correct" way
switch (drawtype) {
case NDT_NORMAL:
alpha = legacy_alpha == 255 ? ALPHAMODE_OPAQUE : ALPHAMODE_CLIP;
break;
case NDT_LIQUID:
case NDT_FLOWINGLIQUID:
alpha = legacy_alpha == 255 ? ALPHAMODE_OPAQUE : ALPHAMODE_BLEND;
break;
default:
alpha = legacy_alpha == 255 ? ALPHAMODE_CLIP : ALPHAMODE_BLEND;
break;
}
}
u8 ContentFeatures::getAlphaForLegacy() const
{
// This is so simple only because 255 and 0 mean wildly different things
// depending on drawtype...
return alpha == ALPHAMODE_OPAQUE ? 255 : 0;
}
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
{
const u8 version = CONTENTFEATURES_VERSION;
@ -433,7 +458,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
for (const TileDef &td : tiledef_special) {
td.serialize(os, protocol_version);
}
writeU8(os, alpha);
writeU8(os, getAlphaForLegacy());
writeU8(os, color.getRed());
writeU8(os, color.getGreen());
writeU8(os, color.getBlue());
@ -489,6 +514,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
os << serializeString16(node_dig_prediction);
writeU8(os, leveled_max);
writeU8(os, alpha);
}
void ContentFeatures::deSerialize(std::istream &is)
@ -524,7 +550,7 @@ void ContentFeatures::deSerialize(std::istream &is)
throw SerializationError("unsupported CF_SPECIAL_COUNT");
for (TileDef &td : tiledef_special)
td.deSerialize(is, version, drawtype);
alpha = readU8(is);
setAlphaFromLegacy(readU8(is));
color.setRed(readU8(is));
color.setGreen(readU8(is));
color.setBlue(readU8(is));
@ -582,10 +608,16 @@ void ContentFeatures::deSerialize(std::istream &is)
try {
node_dig_prediction = deSerializeString16(is);
u8 tmp_leveled_max = readU8(is);
u8 tmp = readU8(is);
if (is.eof()) /* readU8 doesn't throw exceptions so we have to do this */
throw SerializationError("");
leveled_max = tmp_leveled_max;
leveled_max = tmp;
tmp = readU8(is);
if (is.eof())
throw SerializationError("");
alpha = static_cast<enum AlphaMode>(tmp);
} catch(SerializationError &e) {};
}
@ -677,6 +709,7 @@ bool ContentFeatures::textureAlphaCheck(ITextureSource *tsrc, const TileDef *til
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
static thread_local bool long_warning_printed = false;
std::set<std::string> seen;
for (int i = 0; i < length; i++) {
if (seen.find(tiles[i].name) != seen.end())
continue;
@ -701,20 +734,21 @@ bool ContentFeatures::textureAlphaCheck(ITextureSource *tsrc, const TileDef *til
break_loop:
image->drop();
if (!ok) {
warningstream << "Texture \"" << tiles[i].name << "\" of "
<< name << " has transparent pixels, assuming "
"use_texture_alpha = true." << std::endl;
if (!long_warning_printed) {
warningstream << " This warning can be a false-positive if "
"unused pixels in the texture are transparent. However if "
"it is meant to be transparent, you *MUST* update the "
"nodedef and set use_texture_alpha = true! This compatibility "
"code will be removed in a few releases." << std::endl;
long_warning_printed = true;
}
return true;
if (ok)
continue;
warningstream << "Texture \"" << tiles[i].name << "\" of "
<< name << " has transparency, assuming "
"use_texture_alpha = \"clip\"." << std::endl;
if (!long_warning_printed) {
warningstream << " This warning can be a false-positive if "
"unused pixels in the texture are transparent. However if "
"it is meant to be transparent, you *MUST* update the "
"nodedef and set use_texture_alpha = \"clip\"! This "
"compatibility code will be removed in a few releases."
<< std::endl;
long_warning_printed = true;
}
return true;
}
return false;
}
@ -759,14 +793,18 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
bool is_liquid = false;
MaterialType material_type = (alpha == 255) ?
TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
if (alpha == ALPHAMODE_LEGACY_COMPAT) {
// Before working with the alpha mode, resolve any legacy kludges
alpha = textureAlphaCheck(tsrc, tdef, 6) ? ALPHAMODE_CLIP : ALPHAMODE_OPAQUE;
}
MaterialType material_type = alpha == ALPHAMODE_OPAQUE ?
TILE_MATERIAL_OPAQUE : (alpha == ALPHAMODE_CLIP ? TILE_MATERIAL_BASIC :
TILE_MATERIAL_ALPHA);
switch (drawtype) {
default:
case NDT_NORMAL:
material_type = (alpha == 255) ?
TILE_MATERIAL_OPAQUE : TILE_MATERIAL_ALPHA;
solidness = 2;
break;
case NDT_AIRLIKE:
@ -774,14 +812,14 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
break;
case NDT_LIQUID:
if (tsettings.opaque_water)
alpha = 255;
alpha = ALPHAMODE_OPAQUE;
solidness = 1;
is_liquid = true;
break;
case NDT_FLOWINGLIQUID:
solidness = 0;
if (tsettings.opaque_water)
alpha = 255;
alpha = ALPHAMODE_OPAQUE;
is_liquid = true;
break;
case NDT_GLASSLIKE:
@ -833,19 +871,16 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
break;
case NDT_MESH:
case NDT_NODEBOX:
if (alpha == 255 && textureAlphaCheck(tsrc, tdef, 6))
alpha = 0;
solidness = 0;
if (waving == 1)
if (waving == 1) {
material_type = TILE_MATERIAL_WAVING_PLANTS;
else if (waving == 2)
} else if (waving == 2) {
material_type = TILE_MATERIAL_WAVING_LEAVES;
else if (waving == 3)
material_type = (alpha == 255) ? TILE_MATERIAL_WAVING_LIQUID_OPAQUE :
TILE_MATERIAL_WAVING_LIQUID_BASIC;
else if (alpha == 255)
material_type = TILE_MATERIAL_OPAQUE;
} else if (waving == 3) {
material_type = alpha == ALPHAMODE_OPAQUE ?
TILE_MATERIAL_WAVING_LIQUID_OPAQUE : (alpha == ALPHAMODE_CLIP ?
TILE_MATERIAL_WAVING_LIQUID_BASIC : TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
}
break;
case NDT_TORCHLIKE:
case NDT_SIGNLIKE:
@ -860,10 +895,11 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
if (is_liquid) {
if (waving == 3) {
material_type = (alpha == 255) ? TILE_MATERIAL_WAVING_LIQUID_OPAQUE :
TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT;
material_type = alpha == ALPHAMODE_OPAQUE ?
TILE_MATERIAL_WAVING_LIQUID_OPAQUE : (alpha == ALPHAMODE_CLIP ?
TILE_MATERIAL_WAVING_LIQUID_BASIC : TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
} else {
material_type = (alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE :
material_type = alpha == ALPHAMODE_OPAQUE ? TILE_MATERIAL_LIQUID_OPAQUE :
TILE_MATERIAL_LIQUID_TRANSPARENT;
}
}