1
0
mirror of https://github.com/luanti-org/luanti.git synced 2025-12-26 08:15:22 +01:00

Merge colorized buffers after meshgen (#16763)

This commit is contained in:
sfan5
2025-12-24 11:58:31 +01:00
committed by GitHub
parent c7300c1319
commit 46436248de
4 changed files with 89 additions and 4 deletions

View File

@@ -16,7 +16,9 @@
#include "client/meshgen/collector.h"
#include "client/renderingengine.h"
#include <array>
#include <algorithm>
#include <cmath>
#include <cassert>
#include "client/texturesource.h"
#include <SMesh.h>
#include <IMeshBuffer.h>
@@ -585,6 +587,47 @@ void PartialMeshBuffer::draw(video::IVideoDriver *driver) const
MapBlockMesh
*/
static void applyColorAndMerge(std::vector<PreMeshBuffer> &prebuffers)
{
// TODO: we should change the meshgen so it already applies the tile color
// so that we don't need to this extra step.
// However currently the CAO code relies on the ability to erase the vertex
// colors (light data) before applying the tile colors.
for (auto &p : prebuffers) {
// bake color into vertices
p.applyTileColor();
// erase color information for later comparisons
p.layer.has_color = false;
p.layer.color = 0;
}
std::unordered_map<TileLayer, size_t> seen;
for (size_t i = 0; i < prebuffers.size(); i++) {
PreMeshBuffer &p = prebuffers[i];
auto it = seen.find(p.layer);
if (it == seen.end()) { // first time
seen[p.layer] = i;
continue;
}
// merge
auto &dst = prebuffers[it->second];
assert(p.layer == dst.layer);
if (dst.append(p)) {
p = PreMeshBuffer();
} else {
// other buffer full, this one becomes the new target
it->second = i;
}
}
// remove all empty buffers
prebuffers.erase(std::remove_if(prebuffers.begin(), prebuffers.end(),
[] (const PreMeshBuffer &p) {
return p.empty();
}), prebuffers.end());
}
MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
m_tsrc(client->getTextureSource()),
m_shdrsrc(client->getShaderSource()),
@@ -638,11 +681,12 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
scene::SMesh *mesh = static_cast<scene::SMesh *>(m_mesh[layer].get());
for(u32 i = 0; i < collector.prebuffers[layer].size(); i++)
{
PreMeshBuffer &p = collector.prebuffers[layer][i];
applyColorAndMerge(collector.prebuffers[layer]);
p.applyTileColor();
for (size_t i = 0; i < collector.prebuffers[layer].size(); i++) {
PreMeshBuffer &p = collector.prebuffers[layer][i];
// Note that the buffer index matters, so 'continue' is forbidden here.
assert(!p.empty());
// Generate animation data
if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {

View File

@@ -4,6 +4,21 @@
#include "collector.h"
#include <stdexcept>
#include <cassert>
bool PreMeshBuffer::append(const PreMeshBuffer &other)
{
const size_t nv = vertices.size();
const size_t ni = indices.size();
if (nv + other.vertices.size() > U16_MAX)
return false;
vertices.insert(vertices.end(), other.vertices.begin(), other.vertices.end());
indices.insert(indices.end(), other.indices.begin(), other.indices.end());
for (size_t i = ni; i < indices.size(); i++)
indices[i] += nv;
return true;
}
void MeshCollector::append(const TileSpec &tile, const video::S3DVertex *vertices,
u32 numVertices, const u16 *indices, u32 numIndices)
@@ -24,6 +39,7 @@ void MeshCollector::append(const TileLayer &layer, const video::S3DVertex *verti
const u16 aux = layer.texture_layer_idx;
u32 vertex_count = p.vertices.size();
assert(vertex_count + numVertices <= U16_MAX);
for (u32 i = 0; i < numVertices; i++) {
p.vertices.emplace_back(vertices[i].Pos + offset, vertices[i].Normal,
vertices[i].Color, vertices[i].TCoords, aux);

View File

@@ -19,6 +19,10 @@ struct PreMeshBuffer
PreMeshBuffer() = default;
explicit PreMeshBuffer(const TileLayer &layer) : layer(layer) {}
bool empty() const {
return indices.empty();
}
/// @brief Colorizes vertices as indicated by tile layer
void applyTileColor()
{
@@ -33,6 +37,10 @@ struct PreMeshBuffer
c->getBlue() * tc.getBlue() / 255U);
}
}
/// @brief Append another buffer to this one
/// @return false if index would overflow
bool append(const PreMeshBuffer &other);
};
struct MeshCollector

View File

@@ -167,6 +167,23 @@ struct TileLayer
bool has_color = false;
};
template<>
struct std::hash<TileLayer>
{
// All layers equal according to TileLayer::operator== will have the same
// hash value according to this function.
std::size_t operator()(const TileLayer &l) const noexcept
{
std::size_t ret = 0;
for (auto h : { l.texture_id, l.shader_id, (u32)l.material_flags }) {
ret += h;
ret ^= (ret << 6) + (ret >> 2); // distribute bits
}
return ret;
}
};
// Stores information for drawing an animated tile
struct AnimationInfo {