mirror of
https://github.com/minetest/minetest.git
synced 2024-11-29 19:13:44 +01:00
Add a setting to group transparency sorted triangles by buffer (#15115)
This commit is contained in:
parent
c175046d30
commit
df4e70b2c7
@ -1843,6 +1843,11 @@ video_driver (Video driver) enum ,opengl,opengl3,ogles2
|
||||
# Set to 0 to disable it entirely.
|
||||
transparency_sorting_distance (Transparency Sorting Distance) int 16 0 128
|
||||
|
||||
# Draw transparency sorted triangles grouped by their mesh buffers.
|
||||
# This breaks transparency sorting between mesh buffers, but avoids situations
|
||||
# where transparency sorting would be very slow otherwise.
|
||||
transparency_sorting_group_by_buffers (Transparency Sorting Group by Buffers) bool true
|
||||
|
||||
# Radius of cloud area stated in number of 64 node cloud squares.
|
||||
# Values larger than 26 will start to produce sharp cutoffs at cloud area corners.
|
||||
cloud_radius (Cloud radius) int 12 1 62
|
||||
|
@ -73,6 +73,7 @@ static const std::string ClientMap_settings[] = {
|
||||
"trilinear_filter",
|
||||
"bilinear_filter",
|
||||
"anisotropic_filter",
|
||||
"transparency_sorting_group_by_buffers",
|
||||
"transparency_sorting_distance",
|
||||
"occlusion_culler",
|
||||
"enable_raytraced_culling",
|
||||
@ -115,6 +116,9 @@ void ClientMap::onSettingChanged(std::string_view name, bool all)
|
||||
m_cache_bilinear_filter = g_settings->getBool("bilinear_filter");
|
||||
if (all || name == "anisotropic_filter")
|
||||
m_cache_anistropic_filter = g_settings->getBool("anisotropic_filter");
|
||||
if (all || name == "transparency_sorting_group_by_buffers")
|
||||
m_cache_transparency_sorting_group_by_buffers =
|
||||
g_settings->getBool("transparency_sorting_group_by_buffers");
|
||||
if (all || name == "transparency_sorting_distance")
|
||||
m_cache_transparency_sorting_distance = g_settings->getU16("transparency_sorting_distance");
|
||||
if (all || name == "occlusion_culler")
|
||||
@ -1337,7 +1341,8 @@ void ClientMap::updateTransparentMeshBuffers()
|
||||
}
|
||||
|
||||
if (do_sort_block) {
|
||||
blockmesh->updateTransparentBuffers(m_camera_position, block->getPos());
|
||||
blockmesh->updateTransparentBuffers(m_camera_position, block->getPos(),
|
||||
m_cache_transparency_sorting_group_by_buffers);
|
||||
++sorted_blocks;
|
||||
} else {
|
||||
blockmesh->consolidateTransparentBuffers();
|
||||
|
@ -182,6 +182,7 @@ private:
|
||||
bool m_cache_trilinear_filter;
|
||||
bool m_cache_bilinear_filter;
|
||||
bool m_cache_anistropic_filter;
|
||||
bool m_cache_transparency_sorting_group_by_buffers;
|
||||
u16 m_cache_transparency_sorting_distance;
|
||||
|
||||
bool m_loops_occlusion_culler;
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
#include "mapblock_mesh.h"
|
||||
#include "CMeshBuffer.h"
|
||||
#include "client.h"
|
||||
#include "mapblock.h"
|
||||
#include "map.h"
|
||||
@ -818,7 +819,8 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
||||
return true;
|
||||
}
|
||||
|
||||
void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos)
|
||||
void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos,
|
||||
bool group_by_buffers)
|
||||
{
|
||||
// nothing to do if the entire block is opaque
|
||||
if (m_transparent_triangles.empty())
|
||||
@ -834,24 +836,56 @@ void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos)
|
||||
m_transparent_buffers_consolidated = false;
|
||||
m_transparent_buffers.clear();
|
||||
|
||||
std::vector<std::pair<scene::SMeshBuffer *, std::vector<u16>>> ordered_strains;
|
||||
std::unordered_map<scene::SMeshBuffer *, size_t> strain_idxs;
|
||||
|
||||
if (group_by_buffers) {
|
||||
// find (reversed) order for strains, by iterating front-to-back
|
||||
// (if a buffer A has a triangle nearer than all triangles of another
|
||||
// buffer B, A should be drawn in front of (=after) B)
|
||||
scene::SMeshBuffer *current_buffer = nullptr;
|
||||
for (auto it = triangle_refs.rbegin(); it != triangle_refs.rend(); ++it) {
|
||||
const auto &t = m_transparent_triangles[*it];
|
||||
if (current_buffer == t.buffer)
|
||||
continue;
|
||||
current_buffer = t.buffer;
|
||||
auto [_it2, is_new] =
|
||||
strain_idxs.emplace(current_buffer, ordered_strains.size());
|
||||
if (is_new)
|
||||
ordered_strains.emplace_back(current_buffer, std::vector<u16>{});
|
||||
}
|
||||
}
|
||||
|
||||
// find order for triangles, by iterating back-to-front
|
||||
scene::SMeshBuffer *current_buffer = nullptr;
|
||||
std::vector<u16> current_strain;
|
||||
std::vector<u16> *current_strain = nullptr;
|
||||
for (auto i : triangle_refs) {
|
||||
const auto &t = m_transparent_triangles[i];
|
||||
if (current_buffer != t.buffer) {
|
||||
if (current_buffer) {
|
||||
m_transparent_buffers.emplace_back(current_buffer, std::move(current_strain));
|
||||
current_strain.clear();
|
||||
}
|
||||
current_buffer = t.buffer;
|
||||
if (group_by_buffers) {
|
||||
auto it = strain_idxs.find(current_buffer);
|
||||
assert(it != strain_idxs.end());
|
||||
current_strain = &ordered_strains[it->second].second;
|
||||
} else {
|
||||
ordered_strains.emplace_back(current_buffer, std::vector<u16>{});
|
||||
current_strain = &ordered_strains.back().second;
|
||||
}
|
||||
}
|
||||
current_strain.push_back(t.p1);
|
||||
current_strain.push_back(t.p2);
|
||||
current_strain.push_back(t.p3);
|
||||
current_strain->push_back(t.p1);
|
||||
current_strain->push_back(t.p2);
|
||||
current_strain->push_back(t.p3);
|
||||
}
|
||||
|
||||
if (!current_strain.empty())
|
||||
m_transparent_buffers.emplace_back(current_buffer, std::move(current_strain));
|
||||
m_transparent_buffers.reserve(ordered_strains.size());
|
||||
if (group_by_buffers) {
|
||||
// the order was reversed
|
||||
for (auto it = ordered_strains.rbegin(); it != ordered_strains.rend(); ++it)
|
||||
m_transparent_buffers.emplace_back(it->first, std::move(it->second));
|
||||
} else {
|
||||
for (auto it = ordered_strains.begin(); it != ordered_strains.end(); ++it)
|
||||
m_transparent_buffers.emplace_back(it->first, std::move(it->second));
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlockMesh::consolidateTransparentBuffers()
|
||||
|
@ -209,8 +209,14 @@ public:
|
||||
/// Center of the bounding-sphere, in BS-space, relative to block pos.
|
||||
v3f getBoundingSphereCenter() const { return m_bounding_sphere_center; }
|
||||
|
||||
/// update transparent buffers to render towards the camera
|
||||
void updateTransparentBuffers(v3f camera_pos, v3s16 block_pos);
|
||||
/** Update transparent buffers to render towards the camera.
|
||||
* @param group_by_buffers If true, triangles in the same buffer are batched
|
||||
* into the same PartialMeshBuffer, resulting in fewer draw calls, but
|
||||
* wrong order. Triangles within a single buffer are still ordered, and
|
||||
* buffers are ordered relative to each other (with respect to their nearest
|
||||
* triangle).
|
||||
*/
|
||||
void updateTransparentBuffers(v3f camera_pos, v3s16 block_pos, bool group_by_buffers);
|
||||
void consolidateTransparentBuffers();
|
||||
|
||||
/// get the list of transparent buffers
|
||||
|
@ -302,6 +302,7 @@ void set_default_settings()
|
||||
settings->setDefault("arm_inertia", "true");
|
||||
settings->setDefault("show_nametag_backgrounds", "true");
|
||||
settings->setDefault("show_block_bounds_radius_near", "4");
|
||||
settings->setDefault("transparency_sorting_group_by_buffers", "true");
|
||||
settings->setDefault("transparency_sorting_distance", "16");
|
||||
|
||||
settings->setDefault("enable_minimap", "true");
|
||||
|
Loading…
Reference in New Issue
Block a user