This commit is contained in:
Lars Mueller 2024-06-01 21:18:01 +02:00
parent a509aad6b2
commit ed11b33430
8 changed files with 147 additions and 122 deletions

@ -1146,23 +1146,6 @@ void drawItemStack(
} }
video::SMaterial &material = buf->getMaterial(); 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; material.Lighting = false;
driver->setMaterial(material); driver->setMaterial(material);
driver->drawMeshBuffer(buf); driver->drawMeshBuffer(buf);

@ -526,26 +526,7 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
shaderinfo.name = name; shaderinfo.name = name;
shaderinfo.material_type = material_type; shaderinfo.material_type = material_type;
shaderinfo.drawtype = drawtype; shaderinfo.drawtype = drawtype;
switch (material_type) { shaderinfo.base_material = MaterialType_to_irr(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.material = shaderinfo.base_material; shaderinfo.material = shaderinfo.base_material;
bool enable_shaders = g_settings->getBool("enable_shaders"); bool enable_shaders = g_settings->getBool("enable_shaders");

@ -18,31 +18,54 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#include "tile.h" #include "tile.h"
#include "EMaterialTypes.h"
#include "SMaterial.h"
// Sets everything else except the texture in the material void MaterialType_to_irr(MaterialType material_type,
void TileLayer::applyMaterialOptions(video::SMaterial &material) const video::E_MATERIAL_TYPE &irr_mat_type, f32 &irr_mat_param)
{ {
switch (material_type) { switch (material_type) {
case TILE_MATERIAL_OPAQUE: case TILE_MATERIAL_OPAQUE:
case TILE_MATERIAL_LIQUID_OPAQUE: case TILE_MATERIAL_LIQUID_OPAQUE:
case TILE_MATERIAL_WAVING_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; break;
case TILE_MATERIAL_BASIC: case TILE_MATERIAL_BASIC:
case TILE_MATERIAL_PLAIN:
case TILE_MATERIAL_WAVING_LEAVES: case TILE_MATERIAL_WAVING_LEAVES:
case TILE_MATERIAL_WAVING_PLANTS: case TILE_MATERIAL_WAVING_PLANTS:
case TILE_MATERIAL_WAVING_LIQUID_BASIC: case TILE_MATERIAL_WAVING_LIQUID_BASIC:
material.MaterialTypeParam = 0.5; irr_mat_type = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; irr_mat_param = 0.5f;
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:
break; 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<MaterialType>(material_type), material);
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0; material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0;
if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) { if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;

@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once #pragma once
#include "EMaterialTypes.h"
#include "irrlichttypes.h" #include "irrlichttypes.h"
#include <ITexture.h> #include <ITexture.h>
#include <vector> #include <vector>
@ -39,6 +40,11 @@ enum MaterialType{
TILE_MATERIAL_PLAIN_ALPHA 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 // Material flags
// Should backface culling be enabled? // Should backface culling be enabled?
#define MATERIAL_FLAG_BACKFACE_CULLING 0x01 #define MATERIAL_FLAG_BACKFACE_CULLING 0x01

@ -18,9 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#include "wieldmesh.h" #include "wieldmesh.h"
#include "EMaterialTypes.h"
#include "SMaterial.h" #include "SMaterial.h"
#include "settings.h" #include "settings.h"
#include "shader.h"
#include "inventory.h" #include "inventory.h"
#include "client.h" #include "client.h"
#include "itemdef.h" #include "itemdef.h"
@ -249,7 +249,23 @@ void WieldMeshSceneNode::setCube(const ContentFeatures &f,
scene::IMesh *cubemesh = g_extrusion_mesh_cache->createCube(); scene::IMesh *cubemesh = g_extrusion_mesh_cache->createCube();
scene::SMesh *copy = cloneMesh(cubemesh); scene::SMesh *copy = cloneMesh(cubemesh);
cubemesh->drop(); 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); changeToMesh(copy);
copy->drop(); copy->drop();
m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR); 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(), buf->append(&p.vertices[0], p.vertices.size(),
&p.indices[0], p.indices.size()); &p.indices[0], p.indices.size());
buf->drop(); buf->drop();
colors->push_back( colors->emplace_back(p.layer.has_color, p.layer.color);
ItemPartColor(p.layer.has_color, p.layer.color));
} }
return mesh; 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) void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool check_wield_image)
{ {
ITextureSource *tsrc = client->getTextureSource(); ITextureSource *tsrc = client->getTextureSource();
IItemDefManager *idef = client->getItemDefManager(); IItemDefManager *idef = client->getItemDefManager();
IShaderSource *shdrsrc = client->getShaderSource();
const NodeDefManager *ndef = client->getNodeDefManager(); const NodeDefManager *ndef = client->getNodeDefManager();
const ItemDefinition &def = item.getDefinition(idef); const ItemDefinition &def = item.getDefinition(idef);
const ContentFeatures &f = ndef->get(def.name); 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; scene::SMesh *mesh = nullptr;
if (m_enable_shaders) { const auto material_type = def.type == ITEM_NODE
const auto tile_mat = def.type == ITEM_NODE ? getTileMaterial(f.alpha) : TILE_MATERIAL_ALPHA; ? f.getMaterialType() : TILE_MATERIAL_ALPHA;
u32 shader_id = shdrsrc->getShader("object_shader", MaterialType_to_irr(material_type, m_material_type, m_material_type_param);
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;
}
// Color-related // Color-related
m_colors.clear(); m_colors.clear();
@ -644,8 +640,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
} else } else
scaleMesh(mesh, v3f(1.2, 1.2, 1.2)); scaleMesh(mesh, v3f(1.2, 1.2, 1.2));
// add overlays // add overlays
postProcessNodeMesh(mesh, f, false, false, nullptr, postProcessNodeMesh(mesh, f, false, &result->buffer_colors, true);
&result->buffer_colors, true);
if (f.drawtype == NDT_ALLFACES) if (f.drawtype == NDT_ALLFACES)
scaleMesh(mesh, v3f(f.visual_scale)); scaleMesh(mesh, v3f(f.visual_scale));
break; break;
@ -684,8 +679,9 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) { for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
video::SMaterial &material = buf->getMaterial(); video::SMaterial &material = buf->getMaterial();
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; const auto material_type = def.type == ITEM_NODE
material.MaterialTypeParam = 0.0f; // render everything with alpha > 0 ? f.getMaterialType() : TILE_MATERIAL_ALPHA;
MaterialType_to_irr(material_type, material);
material.ZWriteEnable = video::EZW_ON; material.ZWriteEnable = video::EZW_ON;
material.forEachTexture([] (auto &tex) { material.forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
@ -756,8 +752,7 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
} }
void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f,
bool use_shaders, bool set_material, const video::E_MATERIAL_TYPE *mattype, bool use_shaders, std::vector<ItemPartColor> *colors, bool apply_scale)
std::vector<ItemPartColor> *colors, bool apply_scale)
{ {
const u32 mc = mesh->getMeshBufferCount(); const u32 mc = mesh->getMeshBufferCount();
// Allocate colors for existing buffers // Allocate colors for existing buffers
@ -783,11 +778,6 @@ void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f,
} }
video::SMaterial &material = buf->getMaterial(); video::SMaterial &material = buf->getMaterial();
if (set_material)
layer->applyMaterialOptions(material);
if (mattype) {
material.MaterialType = *mattype;
}
if (layer->animation_frame_count > 1) { if (layer->animation_frame_count > 1) {
const FrameSpec &animation_frame = (*layer->frames)[0]; const FrameSpec &animation_frame = (*layer->frames)[0];
material.setTexture(0, animation_frame.texture); material.setTexture(0, animation_frame.texture);

@ -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. * \param colors returns the colors of the mesh buffers in the mesh.
*/ */
void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, bool use_shaders, void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, bool use_shaders,
bool set_material, const video::E_MATERIAL_TYPE *mattype,
std::vector<ItemPartColor> *colors, bool apply_scale = false); std::vector<ItemPartColor> *colors, bool apply_scale = false);

@ -784,6 +784,80 @@ bool isWorldAligned(AlignStyle style, WorldAlignMode mode, NodeDrawType drawtype
return false; 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, void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings) 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]; tdef_spec[j] = tiledef_special[j];
} }
bool is_liquid = false; updateAlpha(tsettings.translucent_liquids);
MaterialType material_type = getMaterialType();
MaterialType material_type = alpha == ALPHAMODE_OPAQUE ?
TILE_MATERIAL_OPAQUE : (alpha == ALPHAMODE_CLIP ? TILE_MATERIAL_BASIC :
TILE_MATERIAL_ALPHA);
switch (drawtype) { switch (drawtype) {
default: default:
@ -825,16 +896,10 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
solidness = 0; solidness = 0;
break; break;
case NDT_LIQUID: case NDT_LIQUID:
if (!tsettings.translucent_liquids)
alpha = ALPHAMODE_OPAQUE;
solidness = 1; solidness = 1;
is_liquid = true;
break; break;
case NDT_FLOWINGLIQUID: case NDT_FLOWINGLIQUID:
solidness = 0; solidness = 0;
if (!tsettings.translucent_liquids)
alpha = ALPHAMODE_OPAQUE;
is_liquid = true;
break; break;
case NDT_GLASSLIKE: case NDT_GLASSLIKE:
solidness = 0; solidness = 0;
@ -879,13 +944,9 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
for (TileDef &td : tdef) for (TileDef &td : tdef)
td.name += std::string("^[noalpha"); td.name += std::string("^[noalpha");
} }
if (waving >= 1)
material_type = TILE_MATERIAL_WAVING_LEAVES;
break; break;
case NDT_PLANTLIKE: case NDT_PLANTLIKE:
solidness = 0; solidness = 0;
if (waving >= 1)
material_type = TILE_MATERIAL_WAVING_PLANTS;
break; break;
case NDT_FIRELIKE: case NDT_FIRELIKE:
solidness = 0; solidness = 0;
@ -893,15 +954,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
case NDT_MESH: case NDT_MESH:
case NDT_NODEBOX: case NDT_NODEBOX:
solidness = 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 = alpha == ALPHAMODE_OPAQUE ?
TILE_MATERIAL_WAVING_LIQUID_OPAQUE : (alpha == ALPHAMODE_CLIP ?
TILE_MATERIAL_WAVING_LIQUID_BASIC : TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
}
break; break;
case NDT_TORCHLIKE: case NDT_TORCHLIKE:
case NDT_SIGNLIKE: case NDT_SIGNLIKE:
@ -914,17 +966,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
break; 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); u32 tile_shader = shdsrc->getShader("nodes_shader", material_type, drawtype);
MaterialType overlay_material = material_type; MaterialType overlay_material = material_type;

@ -531,6 +531,8 @@ struct ContentFeatures
} }
#ifndef SERVER #ifndef SERVER
void updateAlpha(bool translucent_liquids);
MaterialType getMaterialType() const;
void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc, void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings); scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings);
#endif #endif