Skip to content
Permalink
Browse files

Render nodeboxes with opaque material if possible (#10122)

  • Loading branch information
sfan5 committed Aug 12, 2020
1 parent 1c38027 commit fff03931871b68e092e12bfce9056f760e8ec9dd
Showing with 68 additions and 3 deletions.
  1. +2 −0 doc/lua_api.txt
  2. +54 −3 src/nodedef.cpp
  3. +12 −0 src/nodedef.h
@@ -7065,6 +7065,8 @@ Used by `minetest.register_node`.

use_texture_alpha = false,
-- Use texture's alpha channel
-- If this is set to false, the node will be rendered fully opaque
-- regardless of any texture transparency.

palette = "palette.png",
-- The node's `param2` is used to select a pixel from the image.
@@ -695,9 +695,54 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer,
}
}
}
#endif

#ifndef SERVER
bool ContentFeatures::textureAlphaCheck(ITextureSource *tsrc, const TileDef *tiles, int length)
{
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;
seen.insert(tiles[i].name);

// Load the texture and see if there's any transparent pixels
video::ITexture *texture = tsrc->getTexture(tiles[i].name);
video::IImage *image = driver->createImage(texture,
core::position2d<s32>(0, 0), texture->getOriginalSize());
if (!image)
continue;
core::dimension2d<u32> dim = image->getDimension();
bool ok = true;
for (u16 x = 0; x < dim.Width; x++) {
for (u16 y = 0; y < dim.Height; y++) {
if (image->getPixel(x, y).getAlpha() < 255) {
ok = false;
goto break_loop;
}
}
}

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;
}
}
return false;
}

bool isWorldAligned(AlignStyle style, WorldAlignMode mode, NodeDrawType drawtype)
{
if (style == ALIGN_STYLE_WORLD)
@@ -814,13 +859,19 @@ 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)
material_type = TILE_MATERIAL_WAVING_PLANTS;
else if (waving == 2)
material_type = TILE_MATERIAL_WAVING_LEAVES;
else if (waving == 3)
material_type = TILE_MATERIAL_WAVING_LIQUID_BASIC;
material_type = (alpha == 255) ? TILE_MATERIAL_WAVING_LIQUID_OPAQUE :
TILE_MATERIAL_WAVING_LIQUID_BASIC;
else if (alpha == 255)
material_type = TILE_MATERIAL_OPAQUE;
break;
case NDT_TORCHLIKE:
case NDT_SIGNLIKE:
@@ -418,6 +418,7 @@ struct ContentFeatures
void reset();
void serialize(std::ostream &os, u16 protocol_version) const;
void deSerialize(std::istream &is);

/*!
* Since vertex alpha is no longer supported, this method
* adds opacity directly to the texture pixels.
@@ -427,6 +428,17 @@ struct ContentFeatures
*/
void correctAlpha(TileDef *tiles, int length);

#ifndef SERVER
/*
* Checks if any tile texture has any transparent pixels.
* Prints a warning and returns true if that is the case, false otherwise.
* This is supposed to be used for use_texture_alpha backwards compatibility.
*/
bool textureAlphaCheck(ITextureSource *tsrc, const TileDef *tiles,
int length);
#endif


/*
Some handy methods
*/

0 comments on commit fff0393

Please sign in to comment.
You can’t perform that action at this time.