From 5b14c03301efdfe5c3a6d4bcae68ea595a621b38 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 4 Jan 2025 17:51:04 +0100 Subject: [PATCH] Use polygon offset to fix z-fighting for overlay tiles --- src/client/mapblock_mesh.cpp | 10 ++++++++ src/client/tile.h | 5 ++++ src/client/wieldmesh.cpp | 46 ++++++++++++++++++++++++++---------- src/client/wieldmesh.h | 11 --------- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 43c6e22e2..627afac3b 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -702,6 +702,16 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; tex.MagFilter = video::ETMAGF_NEAREST; }); + /* + * The second layer is for overlays, but uses the same vertex positions + * as the first, which quickly leads to z-fighting. + * To fix this we can offset the polygons in the direction of the camera. + * This only affects the depth buffer and leads to no visual gaps in geometry. + */ + if (layer == 1) { + material.PolygonOffsetSlopeScale = -1; + material.PolygonOffsetDepthBias = -1; + } { material.MaterialType = m_shdrsrc->getShaderInfo( diff --git a/src/client/tile.h b/src/client/tile.h index cb42efa02..4f5691bc5 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -50,6 +50,11 @@ struct FrameSpec video::ITexture *texture = nullptr; }; +/** + * We have two tile layers: + * layer 0 = base + * layer 1 = overlay + */ #define MAX_TILE_LAYERS 2 //! Defines a layer of a tile. diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 4239c4121..504fcda7d 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -27,6 +27,18 @@ #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, + bool set_material, const video::E_MATERIAL_TYPE *mattype, + std::vector *colors, bool apply_scale = false); + + static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y) { const f32 r = 0.5; @@ -317,25 +329,32 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, colors->clear(); scene::SMesh *mesh = new scene::SMesh(); - for (auto &prebuffers : collector.prebuffers) + for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) { + auto &prebuffers = collector.prebuffers[layer]; for (PreMeshBuffer &p : prebuffers) { if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) { const FrameSpec &frame = (*p.layer.frames)[0]; p.layer.texture = frame.texture; } - for (video::S3DVertex &v : p.vertices) { + for (video::S3DVertex &v : p.vertices) v.Color.setAlpha(255); - } - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); - buf->Material.setTexture(0, p.layer.texture); - p.layer.applyMaterialOptions(buf->Material); - mesh->addMeshBuffer(buf); + + auto buf = make_irr(); 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)); + + // Set up material + buf->Material.setTexture(0, p.layer.texture); + if (layer == 1) { + buf->Material.PolygonOffsetSlopeScale = -1; + buf->Material.PolygonOffsetDepthBias = -1; + } + p.layer.applyMaterialOptions(buf->Material); + + mesh->addMeshBuffer(buf.get()); + colors->emplace_back(p.layer.has_color, p.layer.color); } + } return mesh; } @@ -688,13 +707,15 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, return mesh; } -void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, +static void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, bool set_material, const video::E_MATERIAL_TYPE *mattype, std::vector *colors, bool apply_scale) { + // FIXME: this function is weirdly inconsistent with what MapBlockMesh does. + // also set_material is never true + const u32 mc = mesh->getMeshBufferCount(); // Allocate colors for existing buffers - colors->clear(); colors->resize(mc); for (u32 i = 0; i < mc; ++i) { @@ -705,6 +726,7 @@ void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, if (layer->texture_id == 0) continue; if (layernum != 0) { + // FIXME: why do this? scene::IMeshBuffer *copy = cloneMeshBuffer(buf); copy->getMaterial() = buf->getMaterial(); mesh->addMeshBuffer(copy); diff --git a/src/client/wieldmesh.h b/src/client/wieldmesh.h index 6e92af9f6..a3d8c3af1 100644 --- a/src/client/wieldmesh.h +++ b/src/client/wieldmesh.h @@ -143,14 +143,3 @@ 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 set_material, const video::E_MATERIAL_TYPE *mattype, - std::vector *colors, bool apply_scale = false);