From 7c261118e06c630ea9ad00f20d7005b8edc108dd Mon Sep 17 00:00:00 2001 From: x2048 Date: Sat, 9 Jul 2022 22:26:39 +0200 Subject: [PATCH] Release shadow mapping resources when not needed (#12497) --- src/client/clientmap.cpp | 3 +- src/client/content_cao.cpp | 11 ---- src/client/shadows/dynamicshadowsrender.cpp | 56 +++++++++++++++------ src/client/shadows/dynamicshadowsrender.h | 2 + src/client/wieldmesh.cpp | 4 -- 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 38ba1daad2df..c5ba98ff6e10 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -472,7 +472,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) // pass the shadow map texture to the buffer texture ShadowRenderer *shadow = m_rendering_engine->get_shadow_renderer(); if (shadow && shadow->is_active()) { - auto &layer = material.TextureLayer[3]; + auto &layer = material.TextureLayer[ShadowRenderer::TEXTURE_LAYER_SHADOW]; layer.Texture = shadow->get_texture(); layer.TextureWrapU = video::E_TEXTURE_CLAMP::ETC_CLAMP_TO_EDGE; layer.TextureWrapV = video::E_TEXTURE_CLAMP::ETC_CLAMP_TO_EDGE; @@ -485,6 +485,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } driver->setMaterial(material); ++material_swaps; + material.TextureLayer[ShadowRenderer::TEXTURE_LAYER_SHADOW].Texture = nullptr; } v3f block_wpos = intToFloat(descriptor.m_pos * MAP_BLOCKSIZE, BS); diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 32c1bb4a8e33..3126ee5e87e6 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1318,12 +1318,6 @@ void GenericCAO::updateTextures(std::string mod) m_previous_texture_modifier = m_current_texture_modifier; m_current_texture_modifier = mod; - video::ITexture *shadow_texture = nullptr; - if (auto shadow = RenderingEngine::get_shadow_renderer()) - shadow_texture = shadow->get_texture(); - - const u32 TEXTURE_LAYER_SHADOW = 3; - if (m_spritenode) { if (m_prop.visual == "sprite") { std::string texturestring = "no_texture.png"; @@ -1334,7 +1328,6 @@ void GenericCAO::updateTextures(std::string mod) m_spritenode->getMaterial(0).MaterialTypeParam = 0.5f; m_spritenode->setMaterialTexture(0, tsrc->getTextureForMesh(texturestring)); - m_spritenode->setMaterialTexture(TEXTURE_LAYER_SHADOW, shadow_texture); // This allows setting per-material colors. However, until a real lighting // system is added, the code below will have no effect. Once MineTest @@ -1370,7 +1363,6 @@ void GenericCAO::updateTextures(std::string mod) material.MaterialType = m_material_type; material.MaterialTypeParam = 0.5f; material.TextureLayer[0].Texture = texture; - material.TextureLayer[TEXTURE_LAYER_SHADOW].Texture = shadow_texture; material.setFlag(video::EMF_LIGHTING, true); material.setFlag(video::EMF_BILINEAR_FILTER, false); material.setFlag(video::EMF_BACK_FACE_CULLING, m_prop.backface_culling); @@ -1421,7 +1413,6 @@ void GenericCAO::updateTextures(std::string mod) material.setFlag(video::EMF_BILINEAR_FILTER, false); material.setTexture(0, tsrc->getTextureForMesh(texturestring)); - material.setTexture(TEXTURE_LAYER_SHADOW, shadow_texture); material.getTextureMatrix(0).makeIdentity(); // This allows setting per-material colors. However, until a real lighting @@ -1448,7 +1439,6 @@ void GenericCAO::updateTextures(std::string mod) auto& material = m_meshnode->getMaterial(0); material.setTexture(0, tsrc->getTextureForMesh(tname)); - material.setTexture(TEXTURE_LAYER_SHADOW, shadow_texture); // This allows setting per-material colors. However, until a real lighting // system is added, the code below will have no effect. Once MineTest @@ -1473,7 +1463,6 @@ void GenericCAO::updateTextures(std::string mod) auto& material = m_meshnode->getMaterial(1); material.setTexture(0, tsrc->getTextureForMesh(tname)); - material.setTexture(TEXTURE_LAYER_SHADOW, shadow_texture); // This allows setting per-material colors. However, until a real lighting // system is added, the code below will have no effect. Once MineTest diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index b8ceeb6239e4..944deb801ff8 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -70,31 +70,45 @@ ShadowRenderer::~ShadowRenderer() delete m_shadow_mix_cb; m_shadow_node_array.clear(); m_light_list.clear(); +} - if (shadowMapTextureDynamicObjects) +void ShadowRenderer::disable() +{ + m_shadows_enabled = false; + if (shadowMapTextureFinal) { + m_driver->setRenderTarget(shadowMapTextureFinal, true, true, + video::SColor(255, 255, 255, 255)); + m_driver->setRenderTarget(0, false, false); + } + + if (shadowMapTextureDynamicObjects) { m_driver->removeTexture(shadowMapTextureDynamicObjects); + shadowMapTextureDynamicObjects = nullptr; + } - if (shadowMapTextureFinal) + if (shadowMapTextureFinal) { m_driver->removeTexture(shadowMapTextureFinal); + shadowMapTextureFinal = nullptr; + } - if (shadowMapTextureColors) + if (shadowMapTextureColors) { m_driver->removeTexture(shadowMapTextureColors); + shadowMapTextureColors = nullptr; + } - if (shadowMapClientMap) + if (shadowMapClientMap) { m_driver->removeTexture(shadowMapClientMap); + shadowMapClientMap = nullptr; + } - if (shadowMapClientMapFuture) + if (shadowMapClientMapFuture) { m_driver->removeTexture(shadowMapClientMapFuture); -} - -void ShadowRenderer::disable() -{ - m_shadows_enabled = false; - if (shadowMapTextureFinal) { - m_driver->setRenderTarget(shadowMapTextureFinal, true, true, - video::SColor(255, 255, 255, 255)); - m_driver->setRenderTarget(0, true, true); + shadowMapClientMapFuture = nullptr; } + + for (auto node : m_shadow_node_array) + if (node.shadowMode & E_SHADOW_MODE::ESM_RECEIVE) + node.node->setMaterialTexture(TEXTURE_LAYER_SHADOW, nullptr); } void ShadowRenderer::initialize() @@ -163,11 +177,18 @@ void ShadowRenderer::setShadowIntensity(float shadow_intensity) void ShadowRenderer::addNodeToShadowList( scene::ISceneNode *node, E_SHADOW_MODE shadowMode) { - m_shadow_node_array.emplace_back(NodeToApply(node, shadowMode)); + if (!node) + return; + m_shadow_node_array.emplace_back(node, shadowMode); + if (shadowMode == ESM_RECEIVE || shadowMode == ESM_BOTH) + node->setMaterialTexture(TEXTURE_LAYER_SHADOW, shadowMapTextureFinal); } void ShadowRenderer::removeNodeFromShadowList(scene::ISceneNode *node) { + if (!node) + return; + node->setMaterialTexture(TEXTURE_LAYER_SHADOW, nullptr); for (auto it = m_shadow_node_array.begin(); it != m_shadow_node_array.end();) { if (it->node == node) { it = m_shadow_node_array.erase(it); @@ -235,6 +256,10 @@ void ShadowRenderer::updateSMTextures() std::string("shadowmap_final_") + itos(m_shadow_map_texture_size), frt, true); assert(shadowMapTextureFinal != nullptr); + + for (auto &node : m_shadow_node_array) + if (node.shadowMode == ESM_RECEIVE || node.shadowMode == ESM_BOTH) + node.node->setMaterialTexture(TEXTURE_LAYER_SHADOW, shadowMapTextureFinal); } if (!m_shadow_node_array.empty() && !m_light_list.empty()) { @@ -322,6 +347,7 @@ void ShadowRenderer::update(video::ITexture *outputTarget) return; } + if (!m_shadow_node_array.empty() && !m_light_list.empty()) { for (DirectionalLight &light : m_light_list) { diff --git a/src/client/shadows/dynamicshadowsrender.h b/src/client/shadows/dynamicshadowsrender.h index 2e3b58f6f9e9..bd27f6f20046 100644 --- a/src/client/shadows/dynamicshadowsrender.h +++ b/src/client/shadows/dynamicshadowsrender.h @@ -51,6 +51,8 @@ struct NodeToApply class ShadowRenderer { public: + static const int TEXTURE_LAYER_SHADOW = 3; + ShadowRenderer(IrrlichtDevice *device, Client *client); ~ShadowRenderer(); diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 25b343573868..0a89e2aa2dcb 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -556,10 +556,6 @@ void WieldMeshSceneNode::changeToMesh(scene::IMesh *mesh) if (m_shadow) { // Add mesh to shadow caster m_shadow->addNodeToShadowList(m_meshnode); - - // Set shadow texture - for (u32 i = 0; i < m_meshnode->getMaterialCount(); i++) - m_meshnode->setMaterialTexture(3, m_shadow->get_texture()); } }