diff --git a/source/light/LightSystem.cpp b/source/light/LightSystem.cpp index 59411034e837d190286ea1b50be4a4b19e897a49..58ffe9dc8593951192a0607ae587f9719ea9480c 100644 --- a/source/light/LightSystem.cpp +++ b/source/light/LightSystem.cpp @@ -1,12 +1,66 @@ #include "LightSystem.h" +class CLevelLoadListener: public IEventListener<XEventLevel> +{ +public: + CLevelLoadListener(CLightSystem *pLightSystem, IXCore *pCore): + m_pLightSystem(pLightSystem) + { + m_pLevelSizeChannel = pCore->getEventChannel<XEventLevelSize>(EVENT_LEVEL_GET_SIZE_GUID); + } + + void onEvent(const XEventLevel *pEvent) override + { + switch(pEvent->type) + { + case XEventLevel::TYPE_LOAD_END: + XEventLevelSize levelSize; + m_pLevelSizeChannel->broadcastEvent(&levelSize); + + m_pLightSystem->setLevelSize(levelSize.vMin, levelSize.vMax); + break; + } + } + +private: + CLightSystem *m_pLightSystem; + IEventChannel<XEventLevelSize> *m_pLevelSizeChannel = NULL; +}; + +//########################################################################## + +CLightSystem::CLightSystem(IXCore *pCore) +{ + m_pLevelListener = new CLevelLoadListener(this, pCore); + + m_pLevelChannel = pCore->getEventChannel<XEventLevel>(EVENT_LEVEL_GUID); + m_pLevelChannel->addListener(m_pLevelListener); +} + CLightSystem::~CLightSystem() { + m_pLevelChannel->removeListener(m_pLevelListener); + mem_delete(m_pLevelListener); mem_delete(m_pSun); mem_release(m_pShapeSphere); mem_release(m_pShapeCone); } +void CLightSystem::setLevelSize(const float3 &vMin, const float3 &vMax) +{ + m_vLevelMin = vMin; + m_vLevelMax = vMax; + m_fLevelDimensions = SMVector3Length(vMin - vMax); + if(m_fLevelDimensions < 100.0f) + { + m_fLevelDimensions = 100.0f; + } + if(m_pSun) + { + m_pSun->setMaxDistance(m_fLevelDimensions); + } +} + IXLightSun *CLightSystem::createSun() { if(m_pSun) @@ -16,6 +70,7 @@ IXLightSun *CLightSystem::createSun() else { m_pSun = new CXLightSun(this); + m_pSun->setMaxDistance(m_fLevelDimensions); m_aLights.push_back(m_pSun); } return(m_pSun); diff --git a/source/light/LightSystem.h b/source/light/LightSystem.h index cf653254e38f6781ee5ca6b225e392df23fbf1d5..e095ce52b3ae23bf3bb76dca571adf172189aa85 100644 --- a/source/light/LightSystem.h +++ b/source/light/LightSystem.h @@ -5,9 +5,11 @@ #include <common/memalloc.h> #include "light.h" +class CLevelLoadListener; class CLightSystem: public IXLightSystem { public: + CLightSystem(IXCore *pCore); ~CLightSystem(); IXLightSun *createSun() override; @@ -27,11 +29,19 @@ public: void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) override; + void setLevelSize(const float3 &vMin, const float3 &vMax); + protected: CXLightSun *m_pSun = NULL; MemAlloc<CXLightPoint, 256, 16, 16> m_poolPoint; MemAlloc<CXLightSpot, 256, 16, 16> m_poolSpot; + float3_t m_vLevelMin, m_vLevelMax; + float m_fLevelDimensions = 0.0f; + + IEventChannel<XEventLevel> *m_pLevelChannel = NULL; + CLevelLoadListener *m_pLevelListener = NULL; + Array<CXLight*> m_aLights; void _deleteLight(CXLight *pLight); diff --git a/source/light/light.cpp b/source/light/light.cpp index 16ce57ec7ddd9d48ed4c390169db07dbf1d58fe5..e5ada15d18f7e5e8440001605d903a9cd04acd86 100644 --- a/source/light/light.cpp +++ b/source/light/light.cpp @@ -308,7 +308,12 @@ void CXLightSun::updatePSConstants(IGXDevice *pDevice) float CXLightSun::getMaxDistance() { - return(1000.0f); + return(m_fMaxDistance); +} + +void CXLightSun::setMaxDistance(float fMax) +{ + m_fMaxDistance = fMax; } void CXLightSun::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) diff --git a/source/light/light.h b/source/light/light.h index 850fcc8874341f94b86276838b134e8c73007991..b8081993fb479011744b2c70300651acff026eed 100644 --- a/source/light/light.h +++ b/source/light/light.h @@ -145,6 +145,7 @@ public: void setDirection(const SMQuaternion &qDirection); float getMaxDistance(); + void setMaxDistance(float fMax); void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) override; @@ -153,6 +154,8 @@ protected: _base_light_data_ps m_dataPS; SMQuaternion m_qDirection; + + float m_fMaxDistance = 1000.0f; }; class CXLightSpot: public CXLight, public virtual IXLightSpot diff --git a/source/light/plugin_main.cpp b/source/light/plugin_main.cpp index fb54c3d09254393322748638d51771a2b9734ba6..ab7934782b28feec8daf3677943e40096058e218 100644 --- a/source/light/plugin_main.cpp +++ b/source/light/plugin_main.cpp @@ -34,7 +34,7 @@ public: { if(guid == IXLIGHTSYSTEM_GUID) { - return(new CLightSystem()); + return(new CLightSystem(m_pCore)); } return(NULL); } diff --git a/source/render/shadow.cpp b/source/render/shadow.cpp index 2bbb79d961c470211ec1f8a0d883b1c3b483f9f8..5a72114229fd2cd2e0b2e8695f71ca8ecf533e90 100644 --- a/source/render/shadow.cpp +++ b/source/render/shadow.cpp @@ -643,6 +643,12 @@ void CShadowPSSM::updateFrustums() float fSplitWeight = 0.8f; float fShadowDistance = min(*r_pssm_max_distance, *r_far); + float fMaxDistanceSun = pSunLight->getMaxDistance(); + if(fShadowDistance > fMaxDistanceSun) + { + fShadowDistance = fMaxDistanceSun; + } + float aSplitDistances[PSSM_MAX_SPLITS]; for(int i = 0; i < *r_pssm_splits; ++i) {