diff --git a/games/devtest/mods/basenodes/init.lua b/games/devtest/mods/basenodes/init.lua index 249c7fbd8..50143b9a6 100644 --- a/games/devtest/mods/basenodes/init.lua +++ b/games/devtest/mods/basenodes/init.lua @@ -157,7 +157,7 @@ minetest.register_node("basenodes:water_flowing", { "Drowning damage: 1", drawtype = "flowingliquid", waving = 3, - tiles = {"default_water_flowing.png"}, + tiles = {"default_water_flowing.png"..WATER_ALPHA}, special_tiles = { {name = "default_water_flowing.png"..WATER_ALPHA, backface_culling = false}, diff --git a/games/devtest/mods/testitems/init.lua b/games/devtest/mods/testitems/init.lua index bde9cc6d9..54bbf600e 100644 --- a/games/devtest/mods/testitems/init.lua +++ b/games/devtest/mods/testitems/init.lua @@ -105,3 +105,9 @@ minetest.register_craftitem("testitems:telescope_stick", { return itemstack end, }) + +minetest.register_craftitem("testitems:translucent_item", { + description = S("Translucent item (translucent inventory & wield image)"), + inventory_image = "testitems_translucent.png", + wield_image = "testitems_translucent.png", +}) \ No newline at end of file diff --git a/games/devtest/mods/testitems/textures/testitems_translucent.png b/games/devtest/mods/testitems/textures/testitems_translucent.png new file mode 100644 index 000000000..71f8649a6 Binary files /dev/null and b/games/devtest/mods/testitems/textures/testitems_translucent.png differ diff --git a/games/devtest/mods/testnodes/performance_test_nodes.lua b/games/devtest/mods/testnodes/performance_test_nodes.lua index 3eaed614b..ee3c1578c 100644 --- a/games/devtest/mods/testnodes/performance_test_nodes.lua +++ b/games/devtest/mods/testnodes/performance_test_nodes.lua @@ -2,29 +2,22 @@ local S = minetest.get_translator("testnodes") --- Complex mesh -minetest.register_node("testnodes:performance_mesh_clip", { - description = S("Performance Test Node") .. "\n" .. S("Marble with 'clip' transparency"), - drawtype = "mesh", - mesh = "testnodes_marble_glass.obj", - tiles = {"testnodes_marble_glass.png"}, - paramtype = "light", - use_texture_alpha = "clip", +for use_texture_alpha, description in pairs({ + opaque = S("Marble with 'opaque' transparency"), + clip = S("Marble with 'clip' transparency"), + blend = S("Marble with 'blend' transparency"), +}) do + minetest.register_node("testnodes:performance_mesh_" .. use_texture_alpha, { + description = S("Performance Test Node") .. "\n" .. description, + drawtype = "mesh", + mesh = "testnodes_marble_glass.obj", + tiles = {"testnodes_marble_glass.png"}, + paramtype = "light", + use_texture_alpha = use_texture_alpha, - groups = {dig_immediate=3}, -}) - --- Complex mesh, alpha blending -minetest.register_node("testnodes:performance_mesh_blend", { - description = S("Performance Test Node") .. "\n" .. S("Marble with 'blend' transparency"), - drawtype = "mesh", - mesh = "testnodes_marble_glass.obj", - tiles = {"testnodes_marble_glass.png"}, - paramtype = "light", - use_texture_alpha = "blend", - - groups = {dig_immediate=3}, -}) + groups = {dig_immediate=3}, + }) +end -- Overlay minetest.register_node("testnodes:performance_overlay_clip", { diff --git a/src/client/hud.cpp b/src/client/hud.cpp index c5e71b853..f02a1e561 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -1145,7 +1145,6 @@ void drawItemStack( } video::SMaterial &material = buf->getMaterial(); - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; material.Lighting = false; driver->setMaterial(material); driver->drawMeshBuffer(buf); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index dae53ff96..6b9f2698c 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -526,26 +526,7 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, shaderinfo.name = name; shaderinfo.material_type = material_type; shaderinfo.drawtype = drawtype; - switch (material_type) { - case TILE_MATERIAL_OPAQUE: - case TILE_MATERIAL_LIQUID_OPAQUE: - case TILE_MATERIAL_WAVING_LIQUID_OPAQUE: - shaderinfo.base_material = video::EMT_SOLID; - break; - case TILE_MATERIAL_ALPHA: - case TILE_MATERIAL_PLAIN_ALPHA: - case TILE_MATERIAL_LIQUID_TRANSPARENT: - case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT: - shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - break; - case TILE_MATERIAL_BASIC: - case TILE_MATERIAL_PLAIN: - case TILE_MATERIAL_WAVING_LEAVES: - case TILE_MATERIAL_WAVING_PLANTS: - case TILE_MATERIAL_WAVING_LIQUID_BASIC: - shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - break; - } + shaderinfo.base_material = MaterialType_to_irr(material_type); shaderinfo.material = shaderinfo.base_material; bool enable_shaders = g_settings->getBool("enable_shaders"); diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 1870547da..3f8db6235 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -18,31 +18,54 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "tile.h" +#include "EMaterialTypes.h" +#include "SMaterial.h" -// Sets everything else except the texture in the material -void TileLayer::applyMaterialOptions(video::SMaterial &material) const +void MaterialType_to_irr(MaterialType material_type, + video::E_MATERIAL_TYPE &irr_mat_type, f32 &irr_mat_param) { switch (material_type) { case TILE_MATERIAL_OPAQUE: case TILE_MATERIAL_LIQUID_OPAQUE: case TILE_MATERIAL_WAVING_LIQUID_OPAQUE: - material.MaterialType = video::EMT_SOLID; + irr_mat_type = video::EMT_SOLID; + irr_mat_param = 0.0f; + break; + case TILE_MATERIAL_ALPHA: + case TILE_MATERIAL_PLAIN_ALPHA: + case TILE_MATERIAL_LIQUID_TRANSPARENT: + case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT: + default: + irr_mat_type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + irr_mat_param = 0.0f; break; case TILE_MATERIAL_BASIC: + case TILE_MATERIAL_PLAIN: case TILE_MATERIAL_WAVING_LEAVES: case TILE_MATERIAL_WAVING_PLANTS: case TILE_MATERIAL_WAVING_LIQUID_BASIC: - material.MaterialTypeParam = 0.5; - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - break; - case TILE_MATERIAL_ALPHA: - case TILE_MATERIAL_LIQUID_TRANSPARENT: - case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT: - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - break; - default: + irr_mat_type = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + irr_mat_param = 0.5f; break; } +} + +video::E_MATERIAL_TYPE MaterialType_to_irr(MaterialType material_type) { + video::E_MATERIAL_TYPE res; + f32 unused; + MaterialType_to_irr(material_type, res, unused); + return res; +} + +void MaterialType_to_irr(MaterialType material_type, video::SMaterial &material) { + MaterialType_to_irr(material_type, + material.MaterialType, material.MaterialTypeParam); +} + +// Sets everything else except the texture in the material +void TileLayer::applyMaterialOptions(video::SMaterial &material) const +{ + MaterialType_to_irr(static_cast(material_type), material); material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0; if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) { material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; diff --git a/src/client/tile.h b/src/client/tile.h index d761eefdd..ddb0b5fcb 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "EMaterialTypes.h" #include "irrlichttypes.h" #include #include @@ -39,6 +40,11 @@ enum MaterialType{ TILE_MATERIAL_PLAIN_ALPHA }; +void MaterialType_to_irr(MaterialType material_type, + video::E_MATERIAL_TYPE &irr_mat_type, f32 &irr_mat_param); +video::E_MATERIAL_TYPE MaterialType_to_irr(MaterialType material_type); +void MaterialType_to_irr(MaterialType material_type, video::SMaterial &mat); + // Material flags // Should backface culling be enabled? #define MATERIAL_FLAG_BACKFACE_CULLING 0x01 diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 66f89efb1..5ca794041 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -18,8 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "wieldmesh.h" +#include "EMaterialTypes.h" +#include "SMaterial.h" #include "settings.h" -#include "shader.h" #include "inventory.h" #include "client.h" #include "itemdef.h" @@ -29,7 +30,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock_mesh.h" #include "client/meshgen/collector.h" #include "client/tile.h" -#include "log.h" #include "util/numeric.h" #include #include @@ -41,6 +41,56 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MIN_EXTRUSION_MESH_RESOLUTION 16 #define MAX_EXTRUSION_MESH_RESOLUTION 512 +/*! + * Applies overlays, textures and optionally materials to the given mesh and + * extracts tile colors for colorization. + * \param mattype overrides the buffer's material type, but can also + * be NULL to leave the original material. + * \param colors returns the colors of the mesh buffers in the mesh. + */ +static void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, + std::vector *colors) +{ + const u32 mc = mesh->getMeshBufferCount(); + // Allocate colors for existing buffers + colors->clear(); + colors->resize(mc); + + for (u32 i = 0; i < mc; ++i) { + const TileSpec *tile = &(f.tiles[i]); + scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); + for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { + const TileLayer *layer = &tile->layers[layernum]; + if (layer->texture_id == 0) + continue; + if (layernum != 0) { + scene::IMeshBuffer *copy = cloneMeshBuffer(buf); + copy->getMaterial() = buf->getMaterial(); + mesh->addMeshBuffer(copy); + copy->drop(); + buf = copy; + colors->emplace_back(layer->has_color, layer->color); + } else { + (*colors)[i] = ItemPartColor(layer->has_color, layer->color); + } + + video::SMaterial &material = buf->getMaterial(); + if (layer->animation_frame_count > 1) { + const FrameSpec &animation_frame = (*layer->frames)[0]; + material.setTexture(0, animation_frame.texture); + } else { + material.setTexture(0, layer->texture); + } + + if (tile->world_aligned) { + u32 n = buf->getVertexCount(); + for (u32 k = 0; k != n; ++k) + buf->getTCoords(k) /= layer->scale; + } + } + } +} + static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y) { const f32 r = 0.5; @@ -193,10 +243,55 @@ class ExtrusionMeshCache: public IReferenceCounted static ExtrusionMeshCache *g_extrusion_mesh_cache = nullptr; +static scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, + const std::string &imagename, const std::string &overlay_name) +{ + // check textures + video::ITexture *texture = tsrc->getTextureForMesh(imagename); + if (!texture) { + return NULL; + } + video::ITexture *overlay_texture = + (overlay_name.empty()) ? NULL : tsrc->getTexture(overlay_name); + + // get mesh + core::dimension2d dim = texture->getSize(); + scene::IMesh *original = g_extrusion_mesh_cache->create(dim); + scene::SMesh *mesh = cloneMesh(original); + original->drop(); + + //set texture + mesh->getMeshBuffer(0)->getMaterial().setTexture(0, + tsrc->getTexture(imagename)); + if (overlay_texture) { + scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0)); + copy->getMaterial().setTexture(0, overlay_texture); + mesh->addMeshBuffer(copy); + copy->drop(); + } + // Customize materials + for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) { + video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial(); + material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; + material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; + material.forEachTexture([] (auto &tex) { + tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; + tex.MagFilter = video::ETMAGF_NEAREST; + }); + material.BackfaceCulling = true; + material.Lighting = false; + material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + material.MaterialTypeParam = 0.0f; // render everything with alpha > 0 + material.ZWriteEnable = video::EZW_ON; + } + scaleMesh(mesh, v3f(2.0, 2.0, 2.0)); + + return mesh; +} WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting): scene::ISceneNode(mgr->getRootSceneNode(), mgr, id), - m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF), + m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL), m_lighting(lighting) { m_enable_shaders = g_settings->getBool("enable_shaders"); @@ -248,7 +343,17 @@ void WieldMeshSceneNode::setCube(const ContentFeatures &f, scene::IMesh *cubemesh = g_extrusion_mesh_cache->createCube(); scene::SMesh *copy = cloneMesh(cubemesh); cubemesh->drop(); - postProcessNodeMesh(copy, f, false, true, &m_material_type, &m_colors, true); + postProcessNodeMesh(copy, f, &m_colors); + + // Customize materials + for (u32 i = 0; i < cubemesh->getMeshBufferCount(); ++i) { + // It suffices to look at the first layer; + // a special overlay layer needs to be consistent with it - + // otherwise we would be overwriting the material options of the fist layer + scene::IMeshBuffer *buf = cubemesh->getMeshBuffer(i); + f.tiles[i].layers[0].applyMaterialOptions(buf->getMaterial()); + } + changeToMesh(copy); copy->drop(); m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR); @@ -295,7 +400,8 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; material.MaterialType = m_material_type; - material.MaterialTypeParam = 0.5f; + material.MaterialTypeParam = m_material_type_param; + material.ZWriteEnable = video::EZW_ON; material.BackfaceCulling = true; // Enable bi/trilinear filtering only for high resolution textures bool bilinear_filter = dim.Width > 32 && m_bilinear_filter; @@ -350,13 +456,11 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, } scene::SMeshBuffer *buf = new scene::SMeshBuffer(); buf->Material.setTexture(0, p.layer.texture); - p.layer.applyMaterialOptions(buf->Material); mesh->addMeshBuffer(buf); buf->append(&p.vertices[0], p.vertices.size(), &p.indices[0], p.indices.size()); buf->drop(); - colors->push_back( - ItemPartColor(p.layer.has_color, p.layer.color)); + colors->emplace_back(p.layer.has_color, p.layer.color); } return mesh; } @@ -365,7 +469,6 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che { ITextureSource *tsrc = client->getTextureSource(); IItemDefManager *idef = client->getItemDefManager(); - IShaderSource *shdrsrc = client->getShaderSource(); const NodeDefManager *ndef = client->getNodeDefManager(); const ItemDefinition &def = item.getDefinition(idef); const ContentFeatures &f = ndef->get(def.name); @@ -373,8 +476,16 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che scene::SMesh *mesh = nullptr; + const auto material_type = def.type == ITEM_NODE + ? f.getMaterialType() : TILE_MATERIAL_ALPHA; + MaterialType_to_irr(material_type, m_material_type, m_material_type_param); if (m_enable_shaders) { - u32 shader_id = shdrsrc->getShader("object_shader", TILE_MATERIAL_BASIC, NDT_NORMAL); + IShaderSource *shdrsrc = client->getShaderSource(); + u32 shader_id = shdrsrc->getShader("object_shader", + material_type, def.type == ITEM_NODE ? f.drawtype : NDT_MESH); + // The shader gives a material ID (different from our material type) back. + // Strictly speaking, "m_material type" is a misnomer, + // since either a material type or ID is stored. m_material_type = shdrsrc->getShaderInfo(shader_id).material; } @@ -463,7 +574,8 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che for (u32 i = 0; i < material_count; ++i) { video::SMaterial &material = m_meshnode->getMaterial(i); material.MaterialType = m_material_type; - material.MaterialTypeParam = 0.5f; + material.MaterialTypeParam = m_material_type_param; + material.ZWriteEnable = video::EZW_ON; material.BackfaceCulling = cull_backface; material.forEachTexture([this] (auto &tex) { setMaterialFilters(tex, m_bilinear_filter, m_trilinear_filter, @@ -624,8 +736,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) } else scaleMesh(mesh, v3f(1.2, 1.2, 1.2)); // add overlays - postProcessNodeMesh(mesh, f, false, false, nullptr, - &result->buffer_colors, true); + postProcessNodeMesh(mesh, f, &result->buffer_colors); if (f.drawtype == NDT_ALLFACES) scaleMesh(mesh, v3f(f.visual_scale)); break; @@ -664,14 +775,17 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); video::SMaterial &material = buf->getMaterial(); - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - material.MaterialTypeParam = 0.5f; + // Note: This overwrites material types / type params + // of plantlike extrusion meshes for alpha blending consistency. + // It suffices to look at the first layer; overlays need to be consistent. + f.tiles[i].layers[0].applyMaterialOptions(material); + material.ZWriteEnable = video::EZW_ON; material.forEachTexture([] (auto &tex) { tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; tex.MagFilter = video::ETMAGF_NEAREST; }); material.BackfaceCulling = cull_backface; - material.Lighting = false; + material.Lighting = false; // no lighting in the inventory } rotateMeshXZby(mesh, -45); @@ -685,109 +799,3 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) } result->mesh = mesh; } - - - -scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, - const std::string &imagename, const std::string &overlay_name) -{ - // check textures - video::ITexture *texture = tsrc->getTextureForMesh(imagename); - if (!texture) { - return NULL; - } - video::ITexture *overlay_texture = - (overlay_name.empty()) ? NULL : tsrc->getTexture(overlay_name); - - // get mesh - core::dimension2d dim = texture->getSize(); - scene::IMesh *original = g_extrusion_mesh_cache->create(dim); - scene::SMesh *mesh = cloneMesh(original); - original->drop(); - - //set texture - mesh->getMeshBuffer(0)->getMaterial().setTexture(0, - tsrc->getTexture(imagename)); - if (overlay_texture) { - scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0)); - copy->getMaterial().setTexture(0, overlay_texture); - mesh->addMeshBuffer(copy); - copy->drop(); - } - // Customize materials - for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) { - video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial(); - material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; - material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; - material.forEachTexture([] (auto &tex) { - tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; - tex.MagFilter = video::ETMAGF_NEAREST; - }); - material.BackfaceCulling = true; - material.Lighting = false; - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - material.MaterialTypeParam = 0.5f; - } - scaleMesh(mesh, v3f(2.0, 2.0, 2.0)); - - return mesh; -} - -void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, - bool use_shaders, bool set_material, const video::E_MATERIAL_TYPE *mattype, - std::vector *colors, bool apply_scale) -{ - const u32 mc = mesh->getMeshBufferCount(); - // Allocate colors for existing buffers - colors->clear(); - colors->resize(mc); - - for (u32 i = 0; i < mc; ++i) { - const TileSpec *tile = &(f.tiles[i]); - scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); - for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { - const TileLayer *layer = &tile->layers[layernum]; - if (layer->texture_id == 0) - continue; - if (layernum != 0) { - scene::IMeshBuffer *copy = cloneMeshBuffer(buf); - copy->getMaterial() = buf->getMaterial(); - mesh->addMeshBuffer(copy); - copy->drop(); - buf = copy; - colors->emplace_back(layer->has_color, layer->color); - } else { - (*colors)[i] = ItemPartColor(layer->has_color, layer->color); - } - - video::SMaterial &material = buf->getMaterial(); - if (set_material) - layer->applyMaterialOptions(material); - if (mattype) { - material.MaterialType = *mattype; - } - if (layer->animation_frame_count > 1) { - const FrameSpec &animation_frame = (*layer->frames)[0]; - material.setTexture(0, animation_frame.texture); - } else { - material.setTexture(0, layer->texture); - } - if (use_shaders) { - if (layer->normal_texture) { - if (layer->animation_frame_count > 1) { - const FrameSpec &animation_frame = (*layer->frames)[0]; - material.setTexture(1, animation_frame.normal_texture); - } else - material.setTexture(1, layer->normal_texture); - } - material.setTexture(2, layer->flags_texture); - } - - if (apply_scale && tile->world_aligned) { - u32 n = buf->getVertexCount(); - for (u32 k = 0; k != n; ++k) - buf->getTCoords(k) /= layer->scale; - } - } - } -} diff --git a/src/client/wieldmesh.h b/src/client/wieldmesh.h index 6358a6665..7e3c8ce4d 100644 --- a/src/client/wieldmesh.h +++ b/src/client/wieldmesh.h @@ -118,6 +118,7 @@ class WieldMeshSceneNode : public scene::ISceneNode // Child scene node with the current wield mesh scene::IMeshSceneNode *m_meshnode = nullptr; video::E_MATERIAL_TYPE m_material_type; + f32 m_material_type_param = 0.0f; // True if SMaterial::Lighting should be enabled. bool m_lighting; @@ -146,17 +147,3 @@ class WieldMeshSceneNode : public scene::ISceneNode }; void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result); - -scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename, - const std::string &overlay_name); - -/*! - * Applies overlays, textures and optionally materials to the given mesh and - * extracts tile colors for colorization. - * \param mattype overrides the buffer's material type, but can also - * be NULL to leave the original material. - * \param colors returns the colors of the mesh buffers in the mesh. - */ -void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, bool use_shaders, - bool set_material, const video::E_MATERIAL_TYPE *mattype, - std::vector *colors, bool apply_scale = false); diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 2914cc3aa..7ee2ca5dc 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -784,6 +784,80 @@ bool isWorldAligned(AlignStyle style, WorldAlignMode mode, NodeDrawType drawtype return false; } +void ContentFeatures::updateAlpha(bool translucent_liquids) { + if ((drawtype == NDT_LIQUID || drawtype == NDT_FLOWINGLIQUID) && + !translucent_liquids) + alpha = ALPHAMODE_OPAQUE; +} + +MaterialType ContentFeatures::getMaterialType() const +{ + MaterialType material_type; + switch (alpha) { + case ALPHAMODE_OPAQUE: + material_type = TILE_MATERIAL_OPAQUE; + break; + case ALPHAMODE_CLIP: + material_type = TILE_MATERIAL_BASIC; + break; + case ALPHAMODE_BLEND: + default: + material_type = TILE_MATERIAL_ALPHA; + break; + } + switch (drawtype) { + case NDT_LIQUID: + case NDT_FLOWINGLIQUID: + switch (alpha) { + case ALPHAMODE_OPAQUE: + return (waving == 3) + ? TILE_MATERIAL_WAVING_LIQUID_OPAQUE + : TILE_MATERIAL_LIQUID_OPAQUE; + case ALPHAMODE_CLIP: + return (waving == 3) + ? TILE_MATERIAL_WAVING_LIQUID_BASIC + : TILE_MATERIAL_LIQUID_TRANSPARENT; + case ALPHAMODE_BLEND: + default: + return (waving == 3) + ? TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT + : TILE_MATERIAL_LIQUID_TRANSPARENT; + } + break; + case NDT_ALLFACES_OPTIONAL: + if (waving >= 1) + return TILE_MATERIAL_WAVING_LEAVES; + break; + case NDT_PLANTLIKE: + if (waving >= 1) + return TILE_MATERIAL_WAVING_PLANTS; + break; + case NDT_MESH: + case NDT_NODEBOX: + switch (waving) { + case 1: + return TILE_MATERIAL_WAVING_PLANTS; + case 2: + return TILE_MATERIAL_WAVING_LEAVES; + case 3: + switch (alpha) { + case ALPHAMODE_OPAQUE: + return TILE_MATERIAL_WAVING_LIQUID_OPAQUE; + case ALPHAMODE_CLIP: + return TILE_MATERIAL_WAVING_LIQUID_BASIC; + case ALPHAMODE_BLEND: + return TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT; + default: + assert(false); + } + break; + } + break; + default: break; + } + return material_type; +} + void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc, scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings) { @@ -810,11 +884,8 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc tdef_spec[j] = tiledef_special[j]; } - bool is_liquid = false; - - MaterialType material_type = alpha == ALPHAMODE_OPAQUE ? - TILE_MATERIAL_OPAQUE : (alpha == ALPHAMODE_CLIP ? TILE_MATERIAL_BASIC : - TILE_MATERIAL_ALPHA); + updateAlpha(tsettings.translucent_liquids); + MaterialType material_type = getMaterialType(); switch (drawtype) { default: @@ -825,16 +896,10 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc solidness = 0; break; case NDT_LIQUID: - if (!tsettings.translucent_liquids) - alpha = ALPHAMODE_OPAQUE; solidness = 1; - is_liquid = true; break; case NDT_FLOWINGLIQUID: solidness = 0; - if (!tsettings.translucent_liquids) - alpha = ALPHAMODE_OPAQUE; - is_liquid = true; break; case NDT_GLASSLIKE: solidness = 0; @@ -879,13 +944,9 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc for (TileDef &td : tdef) td.name += std::string("^[noalpha"); } - if (waving >= 1) - material_type = TILE_MATERIAL_WAVING_LEAVES; break; case NDT_PLANTLIKE: solidness = 0; - if (waving >= 1) - material_type = TILE_MATERIAL_WAVING_PLANTS; break; case NDT_FIRELIKE: solidness = 0; @@ -893,15 +954,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc case NDT_MESH: case NDT_NODEBOX: 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 = 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: @@ -914,17 +966,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc break; } - if (is_liquid) { - 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); - } else { - material_type = alpha == ALPHAMODE_OPAQUE ? TILE_MATERIAL_LIQUID_OPAQUE : - TILE_MATERIAL_LIQUID_TRANSPARENT; - } - } - u32 tile_shader = shdsrc->getShader("nodes_shader", material_type, drawtype); MaterialType overlay_material = material_type; @@ -1082,6 +1123,7 @@ void NodeDefManager::clear() f.name = "air"; f.drawtype = NDT_AIRLIKE; f.param_type = CPT_LIGHT; + f.alpha = ALPHAMODE_CLIP; f.light_propagates = true; f.sunlight_propagates = true; f.walkable = false; diff --git a/src/nodedef.h b/src/nodedef.h index de713a1ad..887366103 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -531,6 +531,8 @@ struct ContentFeatures } #ifndef SERVER + void updateAlpha(bool translucent_liquids); + MaterialType getMaterialType() const; void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc, scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings); #endif