diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index 83a870f7fe..b9f2cbd831 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -13,7 +13,7 @@ namespace SceneUtil { using namespace osgShadow; - void ShadowManager::setupShadowSettings() + void ShadowManager::setupShadowSettings(Shader::ShaderManager& shaderManager) { mEnableShadows = Settings::Manager::getBool("enable shadows", "Shadows"); @@ -32,8 +32,7 @@ namespace SceneUtil = std::clamp(Settings::Manager::getInt("number of shadow maps", "Shadows"), 1, 8); mShadowSettings->setNumShadowMapsPerLight(numberOfShadowMapsPerLight); - mShadowSettings->setBaseShadowTextureUnit( - osg::GLExtensions::Get(0, false)->glMaxTextureUnits - numberOfShadowMapsPerLight); + mShadowSettings->setBaseShadowTextureUnit(shaderManager.reserveGlobalTextureUnits(Shader::ShaderManager::Slot::ShadowMaps, numberOfShadowMapsPerLight)); const float maximumShadowMapDistance = Settings::Manager::getFloat("maximum shadow map distance", "Shadows"); if (maximumShadowMapDistance > 0) @@ -122,7 +121,7 @@ namespace SceneUtil mShadowedScene->setNodeMask(sceneRoot->getNodeMask()); mShadowSettings = mShadowedScene->getShadowSettings(); - setupShadowSettings(); + setupShadowSettings(shaderManager); mShadowTechnique->setupCastingShader(shaderManager); mShadowTechnique->setWorldMask(worldMask); diff --git a/components/sceneutil/shadow.hpp b/components/sceneutil/shadow.hpp index c969ca331f..76fd2b7fdd 100644 --- a/components/sceneutil/shadow.hpp +++ b/components/sceneutil/shadow.hpp @@ -29,7 +29,7 @@ namespace SceneUtil Shader::ShaderManager& shaderManager); ~ShadowManager(); - void setupShadowSettings(); + void setupShadowSettings(Shader::ShaderManager& shaderManager); Shader::ShaderManager::DefineMap getShadowDefines(); diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 9f31412713..73290da2e3 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -636,31 +636,24 @@ namespace Shader program->addShader(linkedShader); } - int ShaderManager::reserveGlobalTextureUnits(Slot slot) + int ShaderManager::reserveGlobalTextureUnits(Slot slot, int count) { - int unit = mReservedTextureUnitsBySlot[static_cast(slot)]; - if (unit >= 0) - return unit; + // TODO: Reuse units when count increase forces reallocation + // TODO: Warn if trampling on the ~8 units needed by model textures + auto unit = mReservedTextureUnitsBySlot[static_cast(slot)]; + if (unit.index >= 0 && unit.count >= count) + return unit.index; - { - // Texture units from `8 - numberOfShadowMaps` to `8` are used for shadows, so we skip them here. - // TODO: Maybe instead of fixed texture units use `reserveGlobalTextureUnits` for shadows as well. - static const int numberOfShadowMaps = Settings::Manager::getBool("enable shadows", "Shadows") - ? std::clamp(Settings::Manager::getInt("number of shadow maps", "Shadows"), 1, 8) - : 0; - if (getAvailableTextureUnits() >= 8 && getAvailableTextureUnits() - 1 < 8) - mReservedTextureUnits = mMaxTextureUnits - (8 - numberOfShadowMaps); - } - - if (getAvailableTextureUnits() < 2) + if (getAvailableTextureUnits() < count + 1) throw std::runtime_error("Can't reserve texture unit; no available units"); - mReservedTextureUnits++; + mReservedTextureUnits += count; - unit = mMaxTextureUnits - mReservedTextureUnits; + unit.index = mMaxTextureUnits - mReservedTextureUnits; + unit.count = count; mReservedTextureUnitsBySlot[static_cast(slot)] = unit; - return unit; + return unit.index; } void ShaderManager::update(osgViewer::Viewer& viewer) diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index e057867ee3..f27c52a16e 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -76,9 +76,11 @@ namespace Shader { OpaqueDepthTexture, SkyTexture, + ShadowMaps, + SLOT_COUNT }; - int reserveGlobalTextureUnits(Slot slot); + int reserveGlobalTextureUnits(Slot slot, int count = 1); void update(osgViewer::Viewer& viewer); void setHotReloadEnabled(bool value); @@ -116,7 +118,8 @@ namespace Shader int mMaxTextureUnits = 0; int mReservedTextureUnits = 0; std::unique_ptr mHotReloadManager; - std::array mReservedTextureUnitsBySlot = { -1, -1 }; + struct ReservedTextureUnits { int index = -1; int count = 0; }; + std::array(Slot::SLOT_COUNT) > mReservedTextureUnitsBySlot = {}; }; bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos);