mirror of
https://github.com/luanti-org/luanti.git
synced 2025-12-26 16:25:25 +01:00
Merge colorized buffers after meshgen (#16763)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user