Transparency sorting for DrawList and Materials (#41)
This commit is contained in:
parent
277160a954
commit
e0b0513465
@ -805,6 +805,11 @@ autoscale_mode (Autoscaling mode) enum disable disable,enable,force
|
||||
# A restart is required after changing this.
|
||||
show_entity_selectionbox (Show entity selection boxes) bool false
|
||||
|
||||
# Sort transparent materials from back to front for proper rendering
|
||||
# Note: works on a per-chunk basis
|
||||
# Note: different materials are sorted independently
|
||||
transparency_sorting (Transparency sorting) bool true
|
||||
|
||||
[*Menus]
|
||||
|
||||
# Use a cloud animation for the main menu background.
|
||||
|
@ -939,6 +939,12 @@
|
||||
# type: bool
|
||||
# show_entity_selectionbox = false
|
||||
|
||||
# Sort transparent materials from back to front for proper rendering
|
||||
# Note: works on a per-chunk basis
|
||||
# Note: different materials are sorted independently
|
||||
# type: bool
|
||||
# transparency_sorting = true
|
||||
|
||||
## Menus
|
||||
|
||||
# Use a cloud animation for the main menu background.
|
||||
|
@ -88,6 +88,7 @@ ClientMap::ClientMap(
|
||||
m_cache_trilinear_filter = g_settings->getBool("trilinear_filter");
|
||||
m_cache_bilinear_filter = g_settings->getBool("bilinear_filter");
|
||||
m_cache_anistropic_filter = g_settings->getBool("anisotropic_filter");
|
||||
m_cache_transparency_sorting = g_settings->getFlag("transparency_sorting");
|
||||
|
||||
}
|
||||
|
||||
@ -147,8 +148,8 @@ void ClientMap::updateDrawList()
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "CM::updateDrawList()", SPT_AVG);
|
||||
|
||||
for (auto &i : m_drawlist) {
|
||||
MapBlock *block = i.second;
|
||||
for (auto const &i : m_drawlist) {
|
||||
MapBlock *block = i.block;
|
||||
block->refDrop();
|
||||
}
|
||||
m_drawlist.clear();
|
||||
@ -247,7 +248,7 @@ void ClientMap::updateDrawList()
|
||||
|
||||
// Add to set
|
||||
block->refGrab();
|
||||
m_drawlist[block->getPos()] = block;
|
||||
m_drawlist.push_back({block, d});
|
||||
|
||||
sector_blocks_drawn++;
|
||||
} // foreach sectorblocks
|
||||
@ -256,6 +257,12 @@ void ClientMap::updateDrawList()
|
||||
m_last_drawn_sectors.insert(sp);
|
||||
}
|
||||
|
||||
if (m_drawlist.capacity() > m_drawlist.size() / 4)
|
||||
m_drawlist.shrink_to_fit();
|
||||
|
||||
if (m_cache_transparency_sorting)
|
||||
std::sort(m_drawlist.begin(), m_drawlist.end(), [] (DrawListItem const &a, DrawListItem const &b) { return a.distance > b.distance; });
|
||||
|
||||
g_profiler->avg("MapBlock meshes in range [#]", blocks_in_range_with_mesh);
|
||||
g_profiler->avg("MapBlocks occlusion culled [#]", blocks_occlusion_culled);
|
||||
g_profiler->avg("MapBlocks drawn [#]", m_drawlist.size());
|
||||
@ -306,16 +313,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
|
||||
MeshBufListList drawbufs;
|
||||
|
||||
for (auto &i : m_drawlist) {
|
||||
v3s16 block_pos = i.first;
|
||||
MapBlock *block = i.second;
|
||||
|
||||
// If the mesh of the block happened to get deleted, ignore it
|
||||
if (!block->mesh)
|
||||
continue;
|
||||
|
||||
float d = 0.0;
|
||||
if (!isBlockInSight(block->getPos(), camera_position,
|
||||
for (auto &item : m_drawlist) {
|
||||
MapBlock *block = item.block;
|
||||
v3s16 block_pos = block->getPos();
|
||||
float d;
|
||||
if (!isBlockInSight(block_pos, camera_position,
|
||||
camera_direction, camera_fov, 100000 * BS, &d))
|
||||
continue;
|
||||
|
||||
@ -387,6 +389,14 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
|
||||
// Render all layers in order
|
||||
for (auto &lists : drawbufs.lists) {
|
||||
if (m_cache_transparency_sorting) {
|
||||
static const auto comparator = [] (MeshBufList const &a, MeshBufList const &b) {
|
||||
// comparing pointers with < is UB unless they belong to the same array, but std::less is always allowed
|
||||
static const std::less<video::ITexture *> texture_less;
|
||||
return texture_less(a.m.TextureLayer[0].Texture, b.m.TextureLayer[0].Texture);
|
||||
};
|
||||
std::sort(lists.begin(), lists.end(), comparator);
|
||||
}
|
||||
for (MeshBufList &list : lists) {
|
||||
// Check and abort if the machine is swapping a lot
|
||||
if (draw.getTimerTime() > 2000) {
|
||||
|
@ -55,6 +55,11 @@ struct MeshBufListList
|
||||
void add(scene::IMeshBuffer *buf, v3s16 position, u8 layer);
|
||||
};
|
||||
|
||||
struct DrawListItem {
|
||||
MapBlock *block;
|
||||
float distance;
|
||||
};
|
||||
|
||||
class Client;
|
||||
class ITextureSource;
|
||||
|
||||
@ -146,11 +151,12 @@ private:
|
||||
f32 m_camera_fov = M_PI;
|
||||
v3s16 m_camera_offset;
|
||||
|
||||
std::map<v3s16, MapBlock*> m_drawlist;
|
||||
std::vector<DrawListItem> m_drawlist;
|
||||
|
||||
std::set<v2s16> m_last_drawn_sectors;
|
||||
|
||||
bool m_cache_trilinear_filter;
|
||||
bool m_cache_bilinear_filter;
|
||||
bool m_cache_anistropic_filter;
|
||||
bool m_cache_transparency_sorting;
|
||||
};
|
||||
|
@ -245,6 +245,7 @@ void set_default_settings()
|
||||
settings->setDefault("round_screen", "0");
|
||||
settings->setDefault("enable_local_map_saving", "false");
|
||||
settings->setDefault("show_entity_selectionbox", "false");
|
||||
settings->setDefault("transparency_sorting", "true");
|
||||
settings->setDefault("texture_clean_transparent", "false");
|
||||
settings->setDefault("texture_min_size", "0");
|
||||
settings->setDefault("ambient_occlusion_gamma", "2.2");
|
||||
|
@ -123,18 +123,18 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||
v3f blockpos_relative = blockpos - camera_pos;
|
||||
|
||||
// Total distance
|
||||
f32 d = MYMAX(0, blockpos_relative.getLength() - block_max_radius);
|
||||
f32 d = blockpos_relative.getLength();
|
||||
|
||||
if (distance_ptr)
|
||||
*distance_ptr = d;
|
||||
|
||||
// If block is far away, it's not in sight
|
||||
if (d > range)
|
||||
if (d > range + block_max_radius)
|
||||
return false;
|
||||
|
||||
// If block is (nearly) touching the camera, don't
|
||||
// bother validating further (that is, render it anyway)
|
||||
if (d == 0)
|
||||
if (d <= block_max_radius)
|
||||
return true;
|
||||
|
||||
// Adjust camera position, for purposes of computing the angle,
|
||||
|
Loading…
x
Reference in New Issue
Block a user