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();
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);

@ -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");

@ -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<MaterialType>(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;

@ -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 <ITexture.h>
#include <vector>
@ -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

@ -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<ItemPartColor> *colors, bool apply_scale)
bool use_shaders, std::vector<ItemPartColor> *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);

@ -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<ItemPartColor> *colors, bool apply_scale = false);

@ -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;

@ -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