From 8ce65232ff09814f1b86393a84c2c6937155e059 Mon Sep 17 00:00:00 2001 From: "glassmancody.info" Date: Fri, 9 Apr 2021 14:14:35 -0700 Subject: [PATCH] fix race condition with sun uniform --- components/sceneutil/lightmanager.cpp | 33 ++++++++++++++++++++++++++- components/sceneutil/lightmanager.hpp | 5 ++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 8e330ac1ca..4b9549c100 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -644,7 +644,7 @@ namespace SceneUtil configureAmbient(lightMat, sun->getAmbient()); configureDiffuse(lightMat, sun->getDiffuse()); configureSpecular(lightMat, sun->getSpecular()); - mLightManager->getStateSet()->getUniform("LightBuffer")->setElement(0, lightMat); + mLightManager->setSunlightBuffer(lightMat, mLastFrameNumber); } else { @@ -767,6 +767,36 @@ namespace SceneUtil osg::ref_ptr mDummyProgram; }; + class LightManagerStateAttributePerObjectUniform : public osg::StateAttribute + { + public: + LightManagerStateAttributePerObjectUniform() + : mLightManager(nullptr) {} + + LightManagerStateAttributePerObjectUniform(LightManager* lightManager) + : mLightManager(lightManager) + { + } + + LightManagerStateAttributePerObjectUniform(const LightManagerStateAttributePerObjectUniform& copy, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY) + : osg::StateAttribute(copy,copyop), mLightManager(copy.mLightManager) {} + + int compare(const StateAttribute &sa) const override + { + throw std::runtime_error("LightManagerStateAttributePerObjectUniform::compare: unimplemented"); + } + + META_StateAttribute(NifOsg, LightManagerStateAttributePerObjectUniform, osg::StateAttribute::LIGHT) + + void apply(osg::State& state) const override + { + mLightManager->getStateSet()->getUniform("LightBuffer")->setElement(0, mLightManager->getSunlightBuffer(state.getFrameStamp()->getFrameNumber())); + } + + private: + LightManager* mLightManager; + }; + const std::unordered_map LightManager::mLightingMethodSettingMap = { {"legacy", LightingMethod::FFP} ,{"shaders compatibility", LightingMethod::PerObjectUniform} @@ -845,6 +875,7 @@ namespace SceneUtil initSingleUBO(targetLights); getOrCreateStateSet()->addUniform(new osg::Uniform("PointLightCount", 0)); + getOrCreateStateSet()->setAttributeAndModes(new LightManagerStateAttributePerObjectUniform(this), osg::StateAttribute::ON); addCullCallback(new LightManagerCullCallback(this)); } diff --git a/components/sceneutil/lightmanager.hpp b/components/sceneutil/lightmanager.hpp index 1ed87ad7c2..62620c61f2 100644 --- a/components/sceneutil/lightmanager.hpp +++ b/components/sceneutil/lightmanager.hpp @@ -179,6 +179,9 @@ namespace SceneUtil auto& getLightBuffer(size_t frameNum) { return mLightBuffers[frameNum%2]; } + osg::Matrixf getSunlightBuffer(size_t frameNum) const { return mSunlightBuffers[frameNum%2]; } + void setSunlightBuffer(const osg::Matrixf& buffer, size_t frameNum) { mSunlightBuffers[frameNum%2] = buffer; } + std::map getLightDefines() const; void processChangedSettings(const Settings::CategorySettingVector& changed); @@ -217,6 +220,8 @@ namespace SceneUtil osg::ref_ptr mLightBuffers[2]; + osg::Matrixf mSunlightBuffers[2]; + // < Light ID , Buffer Index > using LightIndexMap = std::unordered_map; LightIndexMap mLightIndexMaps[2];