diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 60eabc1f9..bc8693f3d 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -1146,23 +1146,6 @@ void drawItemStack( } video::SMaterial &material = buf->getMaterial(); - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - material.MaterialTypeParam = 0.0f; // render everything with alpha > 0 - if (def.type == ITEM_NODE) { - switch (client->ndef()->get(def.name).alpha) { - case ALPHAMODE_OPAQUE: - material.MaterialType = video::EMT_SOLID; - break; - case ALPHAMODE_CLIP: - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - material.MaterialTypeParam = 0.5f; - break; - case ALPHAMODE_BLEND: - break; - default: - assert(false); - } - } 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 6a40ce062..78aee2c48 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -18,9 +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" @@ -249,7 +249,23 @@ 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, false, &m_colors, true); + + // Customize materials + for (u32 i = 0; i < cubemesh->getMeshBufferCount(); ++i) { + const TileSpec *tile = &(f.tiles[i]); + scene::IMeshBuffer *buf = cubemesh->getMeshBuffer(i); + for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { + const TileLayer *layer = &tile->layers[layernum]; + if (layer->texture_id == 0) + continue; + video::SMaterial &material = buf->getMaterial(); + layer->applyMaterialOptions(material); + material.MaterialType = m_material_type; + material.MaterialTypeParam = m_material_type_param; + } + } + changeToMesh(copy); copy->drop(); m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR); @@ -357,30 +373,15 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, 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; } -static MaterialType getTileMaterial(AlphaMode alpha) { - switch (alpha) { - case ALPHAMODE_OPAQUE: - return TILE_MATERIAL_OPAQUE; - case ALPHAMODE_CLIP: - return TILE_MATERIAL_BASIC; - case ALPHAMODE_BLEND: - return TILE_MATERIAL_ALPHA; - default: - assert(false); - } -} - void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool check_wield_image) { 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); @@ -388,14 +389,9 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che scene::SMesh *mesh = nullptr; - if (m_enable_shaders) { - const auto tile_mat = def.type == ITEM_NODE ? getTileMaterial(f.alpha) : TILE_MATERIAL_ALPHA; - u32 shader_id = shdrsrc->getShader("object_shader", - tile_mat, def.type == ITEM_NODE ? f.drawtype : NDT_MESH); - m_material_type = shdrsrc->getShaderInfo(shader_id).material; - // For translucent items, render everything with alpha > 0 - m_material_type_param = tile_mat == TILE_MATERIAL_ALPHA ? 0.0f : 0.5f; - } + 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); // Color-related m_colors.clear(); @@ -644,8 +640,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, false, &result->buffer_colors, true); if (f.drawtype == NDT_ALLFACES) scaleMesh(mesh, v3f(f.visual_scale)); break; @@ -684,8 +679,9 @@ 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.0f; // render everything with alpha > 0 + const auto material_type = def.type == ITEM_NODE + ? f.getMaterialType() : TILE_MATERIAL_ALPHA; + MaterialType_to_irr(material_type, material); material.ZWriteEnable = video::EZW_ON; material.forEachTexture([] (auto &tex) { tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; @@ -756,8 +752,7 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, } 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) + bool use_shaders, std::vector *colors, bool apply_scale) { const u32 mc = mesh->getMeshBufferCount(); // Allocate colors for existing buffers @@ -783,11 +778,6 @@ void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, } 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); diff --git a/src/client/wieldmesh.h b/src/client/wieldmesh.h index 954a28465..7988c44cc 100644 --- a/src/client/wieldmesh.h +++ b/src/client/wieldmesh.h @@ -159,5 +159,4 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename * \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 f16dcb9eb..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; 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