Don't cull upper face of waving liquids below solid nodes (#17302)

This commit is contained in:
ZenonSeth
2026-07-26 22:12:47 +02:00
committed by GitHub
parent 4d516e7b3f
commit 2e1a401ad0
4 changed files with 36 additions and 2 deletions
+32 -2
View File
@@ -450,14 +450,44 @@ void MapblockMeshGenerator::drawSolidNode()
continue;
if (n2 == CONTENT_IGNORE)
continue;
// For a waving liquid source, keep the top face even when a solid node
// is directly above: wave animation can pull the surface down and expose
// a gap where the face was culled. Also keep backface culling off so the
// face is visible from below e.g. looking up from underwater.
// Submerged solids surrounded by liquid or other solid nodes on all sides are excluded.
bool liquid_needs_top_face = face == 0
&& cur_node.f->drawtype == NDT_LIQUID
&& cur_node.f->waving == 3
&& data->m_enable_waving_water;
if (liquid_needs_top_face) {
liquid_needs_top_face = false;
static const v3s16 h_dirs[4] = {
v3s16(1,0,0), v3s16(-1,0,0), v3s16(0,0,1), v3s16(0,0,-1)
};
for (const v3s16 &d : h_dirs) {
const ContentFeatures &f_side = nodedef->get(data->m_vmanip.getNodeNoEx(p2 + d));
bool side_is_translucent = !(f_side.visuals->solidness || f_side.visuals->visual_solidness);
bool side_is_same_flowing_liquid =
f_side.drawtype == NDT_FLOWINGLIQUID && cur_node.f->sameLiquidRender(f_side);
// Draw the top face as soon there's a translucent node diagonally above to
// avoid visual gaps in the liquid surface
if (side_is_translucent && !side_is_same_flowing_liquid) {
liquid_needs_top_face = true;
break;
}
}
}
if (n2 != CONTENT_AIR) {
const ContentFeatures &f2 = nodedef->get(n2);
if (f2.visuals->solidness == 2)
if (f2.visuals->solidness == 2 && !liquid_needs_top_face)
continue;
if (cur_node.f->drawtype == NDT_LIQUID) {
if (cur_node.f->sameLiquidRender(f2))
continue;
backface_culling = f2.visuals->solidness || f2.visuals->visual_solidness;
backface_culling =
!liquid_needs_top_face && (f2.visuals->solidness || f2.visuals->visual_solidness);
}
}
faces |= 1 << face;
+1
View File
@@ -48,6 +48,7 @@ struct MeshMakeData
bool m_generate_minimap = false;
bool m_smooth_lighting = false;
bool m_enable_water_reflections = false;
bool m_enable_waving_water = false;
const NodeDefManager *m_nodedef;
+2
View File
@@ -91,6 +91,7 @@ MeshUpdateQueue::MeshUpdateQueue(Client *client):
{
m_cache_smooth_lighting = g_settings->getBool("smooth_lighting");
m_cache_enable_water_reflections = g_settings->getBool("enable_water_reflections");
m_cache_enable_waving_water = g_settings->getBool("enable_waving_water");
}
MeshUpdateQueue::~MeshUpdateQueue()
@@ -239,6 +240,7 @@ void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q)
data->m_generate_minimap = !!m_client->getMinimap();
data->m_smooth_lighting = m_cache_smooth_lighting;
data->m_enable_water_reflections = m_cache_enable_water_reflections;
data->m_enable_waving_water = m_cache_enable_waving_water;
}
/*
+1
View File
@@ -106,6 +106,7 @@ private:
// TODO: Add callback to update these when g_settings changes, and update all meshes
bool m_cache_smooth_lighting;
bool m_cache_enable_water_reflections;
bool m_cache_enable_waving_water;
void fillDataFromMapBlocks(QueuedMeshUpdate *q);
};