BVB Source Codes

CRYENGINE Show LightEntity.cpp Source code

Return Download CRYENGINE: download LightEntity.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "3dEngine.h"
  5. #include "ObjMan.h"
  6. #include "VisAreas.h"
  7. #include "terrain.h"
  8. #include "LightEntity.h"
  9. #include "PolygonClipContext.h"
  10. #include <CryAnimation/ICryAnimation.h>
  11. #include <CryRenderer/IShader.h>
  12. #include "ClipVolume.h"
  13. #include "ClipVolumeManager.h"
  14. #include "ShadowCache.h"
  15.  
  16. #pragma warning(disable: 4244)
  17.  
  18. PodArray<SPlaneObject> CLightEntity::s_lstTmpCastersHull;
  19.  
  20. #define MIN_SHADOW_RES_OMNI_LIGHT 64
  21. #define MIN_SHADOW_RES_PROJ_LIGHT 128
  22.  
  23. void CLightEntity::StaticReset()
  24. {
  25.         stl::free_container(s_lstTmpCastersHull);
  26. }
  27.  
  28. void CLightEntity::InitEntityShadowMapInfoStructure()
  29. {
  30.         // Init ShadowMapInfo structure
  31.         if (!m_pShadowMapInfo)
  32.                 m_pShadowMapInfo = new ShadowMapInfo(); // leak
  33. }
  34.  
  35. CLightEntity::CLightEntity()
  36. {
  37.         m_layerId = ~0;
  38.  
  39.         m_bShadowCaster = false;
  40.         m_pShadowMapInfo = NULL;
  41.         m_pNotCaster = NULL;
  42.  
  43.         memset(&m_Matrix, 0, sizeof(m_Matrix));
  44.  
  45.         m_pStatObj = NULL;
  46.         GetInstCount(GetRenderNodeType())++;
  47. }
  48.  
  49. CLightEntity::~CLightEntity()
  50. {
  51.         SAFE_RELEASE(m_light.m_Shader.m_pShader);
  52.         //m_light.m_Shader = NULL; // hack to avoid double deallocation
  53.  
  54.         Get3DEngine()->UregisterLightFromAccessabilityCache(this);
  55.         Get3DEngine()->FreeRenderNodeState(this);
  56.         ((C3DEngine*)Get3DEngine())->FreeLightSourceComponents(&m_light, false);
  57.  
  58.         ((C3DEngine*)Get3DEngine())->RemoveEntityLightSources(this);
  59.  
  60.         // delete shadow frustums
  61.         if (m_pShadowMapInfo)
  62.         {
  63.                 for (int nLod = 0; nLod < MAX_GSM_LODS_NUM; nLod++)
  64.                 {
  65.                         //TODO: after porting the sorting to jobs, add a sync point here to prevent deleting a ShadowFrustum which could still be used by a job
  66.                         m_pShadowMapInfo->pGSM[nLod].reset();
  67.                 }
  68.         }
  69.         SAFE_DELETE(m_pShadowMapInfo);
  70.  
  71.         GetInstCount(GetRenderNodeType())--;
  72.  
  73.         SAFE_RELEASE(m_pStatObj);
  74. }
  75.  
  76. void CLightEntity::SetLayerId(uint16 nLayerId)
  77. {
  78.         bool bChanged = m_layerId != nLayerId;
  79.         m_layerId = nLayerId;
  80.  
  81.         if (bChanged)
  82.         {
  83.                 Get3DEngine()->C3DEngine::UpdateObjectsLayerAABB(this);
  84.         }
  85. }
  86.  
  87. const char* CLightEntity::GetName(void) const
  88. {
  89.         return GetOwnerEntity() ? GetOwnerEntity()->GetName() : (m_light.m_sName ? m_light.m_sName : "LightEntity");
  90. }
  91.  
  92. void CLightEntity::GetLocalBounds(AABB& bbox)
  93. {
  94.         bbox = m_WSBBox;
  95.         bbox.min -= m_light.m_Origin;
  96.         bbox.max -= m_light.m_Origin;
  97. }
  98.  
  99. bool CLightEntity::IsLightAreasVisible()
  100. {
  101.         IVisArea* pArea = GetEntityVisArea();
  102.  
  103.         // test area vis
  104.         if (!pArea || pArea->GetVisFrameId() == GetRenderer()->GetFrameID())
  105.                 return true; // visible
  106.  
  107.         if (m_light.m_Flags & DLF_THIS_AREA_ONLY)
  108.                 return false;
  109.  
  110.         // test neighbors
  111.         IVisArea* Areas[64];
  112.         int nCount = pArea->GetVisAreaConnections(Areas, 64);
  113.         for (int i = 0; i < nCount; i++)
  114.                 if (Areas[i]->GetVisFrameId() == GetRenderer()->GetFrameID())
  115.                         return true;
  116.         // visible
  117.  
  118.         return false; // not visible
  119. }
  120.  
  121. //////////////////////////////////////////////////////////////////////////
  122. int CLightEntity::GetSlotCount() const
  123. {
  124.         if (m_pStatObj)
  125.                 return 1;
  126.  
  127.         return 0;
  128. }
  129.  
  130. //////////////////////////////////////////////////////////////////////////
  131. void CLightEntity::SetMatrix(const Matrix34& mat)
  132. {
  133.         m_Matrix = mat;
  134.         Vec3 wp = mat.GetTranslation();
  135.         if (!(m_light.m_Flags & DLF_DEFERRED_CUBEMAPS))
  136.         {
  137.                 float fRadius = m_light.m_fRadius;
  138.                 if (m_light.m_Flags & DLF_AREA_LIGHT) // Use max for area lights.
  139.                         fRadius += max(m_light.m_fAreaWidth, m_light.m_fAreaHeight);
  140.                 SetBBox(AABB(wp - Vec3(fRadius), wp + Vec3(fRadius)));
  141.         }
  142.         else
  143.         {
  144.                 OBB obb(OBB::CreateOBBfromAABB(Matrix33(m_Matrix), AABB(-m_light.m_ProbeExtents, m_light.m_ProbeExtents)));
  145.                 SetBBox(AABB::CreateAABBfromOBB(wp, obb));
  146.         }
  147.         m_light.SetPosition(wp);
  148.         m_light.SetMatrix(mat);
  149.         SetLightProperties(m_light);
  150.         Get3DEngine()->RegisterEntity(this);
  151.  
  152.         if (!memcmp(&m_Matrix, &mat, sizeof(Matrix34)))
  153.                 return;
  154.  
  155.         //update shadow frustums
  156.         if (m_pShadowMapInfo != NULL)
  157.         {
  158.                 for (int i = 0; i < MAX_GSM_LODS_NUM && m_pShadowMapInfo->pGSM[i] != NULL; i++)
  159.                 {
  160.                         m_pShadowMapInfo->pGSM[i]->RequestUpdate();
  161.                 }
  162.         }
  163. }
  164.  
  165. void C3DEngine::UpdateSunLightSource(const SRenderingPassInfo& passInfo)
  166. {
  167.         if (!m_pSun)
  168.                 m_pSun = (CLightEntity*)CreateLightSource();
  169.  
  170.         CDLight DynLight;
  171.  
  172.         //      float fGSMBoxSize = (float)Get3DEngine()->m_fGsmRange;
  173.         //      Vec3 vCameraDir = GetCamera().GetMatrix().GetColumn(1).GetNormalized();
  174.         //      Vec3 vSunDir = Get3DEngine()->GetSunDir().GetNormalized();              // todo: remove GetNormalized() once GetSunDir() returns the normalized value
  175.         //Vec3 vCameraDirWithoutDepth = vCameraDir - vCameraDir.Dot(vSunDir)*vSunDir;
  176.         //      Vec3 vFocusPos = GetCamera().GetPosition() + vCameraDirWithoutDepth*fGSMBoxSize;
  177.  
  178.         DynLight.SetPosition(passInfo.GetCamera().GetPosition() + GetSunDir());  //+ vSunShadowDir;
  179.         DynLight.m_fRadius = 100000000;
  180.         DynLight.SetLightColor(GetSunColor());
  181.         DynLight.SetSpecularMult(GetGlobalParameter(E3DPARAM_SUN_SPECULAR_MULTIPLIER));
  182.         DynLight.m_Flags |= DLF_DIRECTIONAL | DLF_SUN | DLF_THIS_AREA_ONLY | DLF_LM | DLF_SPECULAROCCLUSION |
  183.                             ((m_bSunShadows && passInfo.RenderShadows()) ? DLF_CASTSHADOW_MAPS : 0);
  184.         DynLight.m_sName = "Sun";
  185.  
  186.         m_pSun->SetLightProperties(DynLight);
  187.  
  188.         m_pSun->SetBBox(AABB(
  189.                           DynLight.m_Origin - Vec3(DynLight.m_fRadius, DynLight.m_fRadius, DynLight.m_fRadius),
  190.                           DynLight.m_Origin + Vec3(DynLight.m_fRadius, DynLight.m_fRadius, DynLight.m_fRadius)));
  191.  
  192.         m_pSun->SetRndFlags(ERF_OUTDOORONLY, true);
  193.  
  194.         IF (GetCVars()->e_Sun && m_pTerrain, 1)
  195.                 RegisterEntity(m_pSun);
  196.         else
  197.                 UnRegisterEntityAsJob(m_pSun);
  198. }
  199.  
  200. Vec3 CLightEntity::GSM_GetNextScreenEdge(float fPrevRadius, float fPrevDistanceFromView, const SRenderingPassInfo& passInfo)
  201. {
  202.         //////////////////////////////////////////////////////////////////////////
  203.         //Camera Frustum edge
  204.         Vec3 vEdgeN = passInfo.GetCamera().GetEdgeN();
  205.         Vec3 vEdgeF = passInfo.GetCamera().GetEdgeF();
  206.  
  207.         //Lineseg lsgFrustumEdge(vEdgeN, vEdgeF);
  208.  
  209.         Vec3 vPrevSphereCenter(0.0f, fPrevDistanceFromView, 0.0f);
  210.  
  211.         //float fPointT;
  212.         //float fDistToFrustEdge = ( (vPrevSphereCenter.Cross(vEdgeF)).GetLength() ) / ( vEdgeF.GetLength() );
  213.  
  214.         float fDistToFrustEdge = (((vPrevSphereCenter - vEdgeN).Cross(vEdgeF - vEdgeN)).GetLength()) / ((vEdgeF - vEdgeN).GetLength());
  215.  
  216.         /*Vec3 diff = vPrevSphereCenter - vEdgeN;
  217.            Vec3 dir = vEdgeF - vEdgeN;
  218.            fPointT = (diff.Dot(dir))/dir.GetLength();*/
  219.  
  220.         //Vec3 vProjectedCenter = lsgFrustumEdge.GetPoint(fPointT);
  221.  
  222.         //float fDistToFrustEdge = (vProjectedCenter - vPrevSphereCenter).GetLength();
  223.  
  224.         float fDistToPlaneOnEdgeSquared = fPrevRadius * fPrevRadius - fDistToFrustEdge * fDistToFrustEdge;
  225.         float fDistToPlaneOnEdge = fDistToPlaneOnEdgeSquared > 0.0f ? sqrt_tpl(fDistToPlaneOnEdgeSquared) : 0.0f;
  226.  
  227.         Vec3 vEdgeDir = (vEdgeF - vEdgeN);
  228.  
  229.         vEdgeDir.SetLength(2.0f * fDistToPlaneOnEdge);
  230.  
  231.         Vec3 vEdgeNextScreen = vEdgeN /*vProjectedCenter*/ + vEdgeDir;
  232.  
  233.         return vEdgeNextScreen;
  234. };
  235.  
  236. float CLightEntity::GSM_GetLODProjectionCenter(const Vec3& vEdgeScreen, float fRadius)
  237. {
  238.         float fScreenEdgeSq = vEdgeScreen.z * vEdgeScreen.z + vEdgeScreen.x * vEdgeScreen.x;
  239.         float fRadiusSq = max(fRadius * fRadius, 2.0f * fScreenEdgeSq);
  240.         float fDistanceFromNear = sqrt_tpl(fRadiusSq - fScreenEdgeSq);
  241.         float fDistanceFromView = fDistanceFromNear + vEdgeScreen.y;
  242.         return fDistanceFromView;
  243. }
  244.  
  245. void CLightEntity::UpdateGSMLightSourceShadowFrustum(const SRenderingPassInfo& passInfo)
  246. {
  247.         FUNCTION_PROFILER_3DENGINE;
  248.  
  249.         const int nMaxLodCount = min(GetCVars()->e_GsmLodsNum, MAX_GSM_LODS_NUM - 1);
  250.         int nDynamicLodCount = nMaxLodCount;
  251.         int nCachedLodCount = 0;
  252.  
  253.         // check for shadow cache
  254.         if (m_light.m_Flags & DLF_SUN)
  255.         {
  256.                 int nFirstCachedLod = Get3DEngine()->m_nGsmCache - 1;
  257.                 if (nFirstCachedLod >= 0)
  258.                 {
  259.                         nDynamicLodCount = clamp_tpl(nFirstCachedLod, 0, nMaxLodCount);
  260.                         nCachedLodCount = nMaxLodCount - nDynamicLodCount;
  261.                 }
  262.         }
  263.  
  264.         // update dynamic and static frustums
  265.         float fDistFromView = 0;
  266.         float fRadiusLastLod = 0;
  267.  
  268.         int nNextLod = 0;
  269.         nNextLod = UpdateGSMLightSourceDynamicShadowFrustum(nDynamicLodCount, nCachedLodCount, fDistFromView, fRadiusLastLod, nCachedLodCount == 0, passInfo);
  270.         nNextLod += UpdateGSMLightSourceCachedShadowFrustum(nDynamicLodCount, nCachedLodCount, fDistFromView, fRadiusLastLod, passInfo);
  271.         nNextLod += UpdateGSMLightSourceNearestShadowFrustum(nNextLod, passInfo);
  272.  
  273.         // free not used frustums
  274.         for (int nLod = nNextLod; nLod < MAX_GSM_LODS_NUM; nLod++)
  275.         {
  276.                 if (ShadowMapFrustum* pFr = m_pShadowMapInfo->pGSM[nLod])
  277.                 {
  278.                         pFr->ResetCasterLists();
  279.                         pFr->m_eFrustumType = ShadowMapFrustum::e_GsmDynamic;
  280.                         pFr->pShadowCacheData.reset();
  281.                 }
  282.         }
  283. }
  284.  
  285. int CLightEntity::UpdateGSMLightSourceDynamicShadowFrustum(int nDynamicLodCount, int nDistanceLodCount, float& fDistanceFromViewNextDynamicLod, float& fGSMBoxSizeNextDynamicLod, bool bFadeLastCascade, const SRenderingPassInfo& passInfo)
  286. {
  287.         assert(m_pTerrain);
  288.         InitEntityShadowMapInfoStructure();
  289.  
  290.         float fGSMBoxSize = fGSMBoxSizeNextDynamicLod = (float)Get3DEngine()->m_fGsmRange;
  291.         Vec3 vCameraDir = passInfo.GetCamera().GetMatrix().GetColumn(1).GetNormalized();
  292.         float fDistToLight = passInfo.GetCamera().GetPosition().GetDistance(GetPos(true));
  293.  
  294.         PodArray<SPlaneObject>& lstCastersHull = s_lstTmpCastersHull;
  295.         lstCastersHull.Clear();
  296.  
  297.         // prepare shadow frustums
  298.         int nLod;
  299.  
  300.         //compute distance for first LOD
  301.         Vec3 vEdgeScreen = passInfo.GetCamera().GetEdgeN();
  302.         //clamp first frustum to DRAW_NEAREST_MIN near plane because weapon can be placed beyond camera near plane in world space
  303.         vEdgeScreen.y = min(vEdgeScreen.y, DRAW_NEAREST_MIN);
  304.         float fDistanceFromView = fDistanceFromViewNextDynamicLod = GSM_GetLODProjectionCenter(vEdgeScreen, Get3DEngine()->m_fGsmRange);
  305.  
  306.         for (nLod = 0; nLod < nDynamicLodCount + nDistanceLodCount; nLod++)
  307.         {
  308.                 const float fFOV = (m_light).m_fLightFrustumAngle * 2;
  309.                 const bool bDoGSM = !!(m_light.m_Flags & DLF_SUN);
  310.  
  311.                 if (bDoGSM)
  312.                 {
  313.                         Vec3 vSunDir = Get3DEngine()->GetSunDir().GetNormalized();    // todo: remove GetNormalized() once GetSunDir() returns the normalized value
  314.                         Vec3 vCameraDirWithoutDepth = vCameraDir - vCameraDir.Dot(vSunDir) * vSunDir;
  315.  
  316.                         Vec3 vFocusPos = passInfo.GetCamera().GetPosition() + vCameraDirWithoutDepth * fGSMBoxSize;
  317.                         SetBBox(AABB(vFocusPos - Vec3(fGSMBoxSize, fGSMBoxSize, fGSMBoxSize), vFocusPos + Vec3(fGSMBoxSize, fGSMBoxSize, fGSMBoxSize)));
  318.                 }
  319.                 else
  320.                 {
  321.                         float fRadius = m_light.m_fRadius;
  322.                         if (m_light.m_Flags & DLF_AREA_LIGHT) // Use max for area lights.
  323.                                 fRadius += max(m_light.m_fAreaWidth, m_light.m_fAreaHeight);
  324.                         SetBBox(AABB(m_light.m_Origin - Vec3(fRadius), m_light.m_Origin + Vec3(fRadius)));
  325.                 }
  326.  
  327.                 if (!m_pShadowMapInfo->pGSM[nLod])
  328.                         m_pShadowMapInfo->pGSM[nLod] = new ShadowMapFrustum;
  329.  
  330.                 m_pShadowMapInfo->pGSM[nLod]->m_eFrustumType = nLod < nDynamicLodCount ? ShadowMapFrustum::e_GsmDynamic : ShadowMapFrustum::e_GsmDynamicDistance;
  331.                 m_pShadowMapInfo->pGSM[nLod]->bUseAdditiveBlending = false;
  332.                 m_pShadowMapInfo->pGSM[nLod]->fShadowFadingDist = (bFadeLastCascade && nLod == nDynamicLodCount - 1) ? 1.0f : 0.0f;
  333.  
  334.                 if (!ProcessFrustum(nLod, bDoGSM ? fGSMBoxSize : 0, fDistanceFromView, lstCastersHull, passInfo))
  335.                 {
  336.                         nLod++;
  337.                         break;
  338.                 }
  339.  
  340.                 //compute plane  for next GSM slice
  341.                 vEdgeScreen = GSM_GetNextScreenEdge(fGSMBoxSize, fDistanceFromView, passInfo);
  342.                 fGSMBoxSize *= Get3DEngine()->m_fGsmRangeStep;
  343.  
  344.                 //compute distance from camera for next LOD
  345.                 fDistanceFromView = GSM_GetLODProjectionCenter(vEdgeScreen, fGSMBoxSize);
  346.  
  347.                 if (nLod < nDynamicLodCount)
  348.                 {
  349.                         fDistanceFromViewNextDynamicLod = fDistanceFromView;
  350.                         fGSMBoxSizeNextDynamicLod = fGSMBoxSize;
  351.                 }
  352.         }
  353.  
  354.         return nLod;
  355. }
  356.  
  357. int CLightEntity::UpdateGSMLightSourceCachedShadowFrustum(int nFirstLod, int nLodCount, float& fDistFromViewDynamicLod, float fRadiusDynamicLod, const SRenderingPassInfo& passInfo)
  358. {
  359.         ShadowFrustumMGPUCache* pFrustumCache = GetRenderer()->GetShadowFrustumMGPUCache();
  360.         assert(pFrustumCache);
  361.  
  362.         static ICVar* pHeightMapAOVar = GetConsole()->GetCVar("r_HeightMapAO");
  363.         const int firstCachedFrustumIndex = nFirstLod + nLodCount;
  364.         const bool bRestoreFromCache = GetRenderer()->GetActiveGPUCount() > 1 && pFrustumCache->nUpdateMaskMT != 0 && m_pShadowMapInfo->pGSM[firstCachedFrustumIndex];
  365.         const bool bHeightMapAO = Get3DEngine()->m_bHeightMapAoEnabled && pHeightMapAOVar && pHeightMapAOVar->GetIVal() > 0 && (m_light.m_Flags & DLF_SUN);
  366.  
  367.         int nLod = 0;
  368.  
  369.         if (bRestoreFromCache)
  370.         {
  371.                 for (nLod = 0; nLod < nLodCount; ++nLod)
  372.                 {
  373.                         assert(pFrustumCache->m_staticShadowMapFrustums[nLod] && m_pShadowMapInfo->pGSM[firstCachedFrustumIndex + nLod]);
  374.  
  375.                         ShadowMapFrustum* pFr = m_pShadowMapInfo->pGSM[firstCachedFrustumIndex + nLod];
  376.                         *pFr = *pFrustumCache->m_staticShadowMapFrustums[nLod];
  377.                         pFr->bIsMGPUCopy = true;
  378.                 }
  379.  
  380.                 if (bHeightMapAO)
  381.                 {
  382.                         assert(pFrustumCache->m_pHeightMapAOFrustum && m_pShadowMapInfo->pGSM[firstCachedFrustumIndex + nLod]);
  383.  
  384.                         ShadowMapFrustum* pFr = m_pShadowMapInfo->pGSM[firstCachedFrustumIndex + nLod];
  385.                         *pFr = *pFrustumCache->m_pHeightMapAOFrustum;
  386.                         pFr->bIsMGPUCopy = true;
  387.  
  388.                         ++nLod;
  389.                 }
  390.         }
  391.         else
  392.         {
  393.                 ShadowMapFrustum::ShadowCacheData::eUpdateStrategy nUpdateStrategy =
  394.                   static_cast<ShadowMapFrustum::ShadowCacheData::eUpdateStrategy>(Get3DEngine()->m_nCachedShadowsUpdateStrategy);
  395.  
  396.                 if (GetCVars()->e_ShadowsCacheUpdate)
  397.                         nUpdateStrategy = ShadowMapFrustum::ShadowCacheData::eFullUpdate;
  398.  
  399.                 if (s_lstTmpCastersHull.empty())
  400.                         MakeShadowCastersHull(s_lstTmpCastersHull, passInfo);
  401.  
  402.                 ShadowCache shadowCache(this, nUpdateStrategy);
  403.  
  404.                 for (nLod = 0; nLod < nLodCount; ++nLod)
  405.                 {
  406.                         ShadowMapFrustumPtr& pFr = m_pShadowMapInfo->pGSM[firstCachedFrustumIndex + nLod];
  407.                         shadowCache.InitShadowFrustum(pFr, nFirstLod + nLod, nFirstLod, fDistFromViewDynamicLod, fRadiusDynamicLod, passInfo);
  408.                         CalculateShadowBias(pFr, nFirstLod + nLod, fRadiusDynamicLod);
  409.                         pFr->bIsMGPUCopy = false;
  410.  
  411.                         // update MGPU frustum cache
  412.                         if (GetRenderer()->GetActiveGPUCount() > 1 && pFrustumCache->m_staticShadowMapFrustums[nLod])
  413.                                 *pFrustumCache->m_staticShadowMapFrustums[nLod] = *pFr;
  414.  
  415.                         // update distance from view
  416.                         Vec3 vEdgeScreen = GSM_GetNextScreenEdge(fRadiusDynamicLod, fDistFromViewDynamicLod, passInfo);
  417.                         fRadiusDynamicLod *= Get3DEngine()->m_fGsmRangeStep;
  418.                         fDistFromViewDynamicLod = GSM_GetLODProjectionCenter(vEdgeScreen, fRadiusDynamicLod);
  419.                 }
  420.  
  421.                 if (bHeightMapAO)
  422.                 {
  423.                         ShadowMapFrustumPtr& pFr = m_pShadowMapInfo->pGSM[firstCachedFrustumIndex + nLod];
  424.  
  425.                         shadowCache.InitHeightMapAOFrustum(pFr, nFirstLod + nLod, passInfo);
  426.                         pFr->bIsMGPUCopy = false;
  427.                         if (GetRenderer()->GetActiveGPUCount() > 1 && pFrustumCache->m_pHeightMapAOFrustum)
  428.                                 *pFrustumCache->m_pHeightMapAOFrustum = *pFr;
  429.  
  430.                         ++nLod;
  431.                 }
  432.  
  433.                 if (GetCVars()->e_ShadowsCacheUpdate == 1)
  434.                         GetCVars()->e_ShadowsCacheUpdate = 0;
  435.  
  436.                 Get3DEngine()->m_nCachedShadowsUpdateStrategy = ShadowMapFrustum::ShadowCacheData::eIncrementalUpdate;
  437.  
  438.                 int nActiveGPUCount = GetRenderer()->GetActiveGPUCount();
  439.                 pFrustumCache->nUpdateMaskMT = (1 << nActiveGPUCount) - 1;
  440.         }
  441.  
  442.         return nLod;
  443. }
  444.  
  445. int CLightEntity::UpdateGSMLightSourceNearestShadowFrustum(int nFrustumIndex, const SRenderingPassInfo& passInfo)
  446. {
  447.         CRY_ASSERT(nFrustumIndex >= 0 && nFrustumIndex < MAX_GSM_LODS_NUM);
  448.         static ICVar* pDrawNearShadowsCVar = GetConsole()->GetCVar("r_DrawNearShadows");
  449.  
  450.         if (pDrawNearShadowsCVar && pDrawNearShadowsCVar->GetIVal() > 0 && nFrustumIndex < CRY_ARRAY_COUNT(m_pShadowMapInfo->pGSM))
  451.         {
  452.                 if (m_light.m_Flags & DLF_SUN)
  453.                 {
  454.                         ShadowMapFrustumPtr& pFr = m_pShadowMapInfo->pGSM[nFrustumIndex];
  455.                         if (!pFr) pFr = new ShadowMapFrustum;
  456.  
  457.                         auto nearestShadowViews = pFr->m_pShadowsView;
  458.                         *pFr = *m_pShadowMapInfo->pGSM[0];        // copy first cascade
  459.                         pFr->m_pShadowsView = nearestShadowViews; // restore original shadow views
  460.  
  461.                         pFr->m_eFrustumType = ShadowMapFrustum::e_Nearest;
  462.                         pFr->bUseShadowsPool = false;
  463.                         pFr->bUseAdditiveBlending = true;
  464.                         pFr->fShadowFadingDist = 1.0f;
  465.                         pFr->fDepthConstBias = 0.0001f;
  466.                         pFr->castersList.clear();
  467.                         pFr->jobExecutedCastersList.clear();
  468.  
  469.                         return 1;
  470.                 }
  471.         }
  472.  
  473.         return 0;
  474. }
  475.  
  476. bool CLightEntity::ProcessFrustum(int nLod, float fGSMBoxSize, float fDistanceFromView, PodArray<SPlaneObject>& lstCastersHull, const SRenderingPassInfo& passInfo)
  477. {
  478.         ShadowMapFrustum* pFr = m_pShadowMapInfo->pGSM[nLod];
  479.  
  480.         // make shadow map frustum for receiving (include all objects into frustum)
  481.         assert(pFr);
  482.  
  483.         bool bDoGSM = fGSMBoxSize != 0;
  484.         bool bDoNextLod = false;
  485.  
  486.         if (bDoGSM)// && (m_light.m_Flags & DLF_SUN || m_light.m_Flags & DLF_PROJECT))
  487.         {
  488.                 InitShadowFrustum_SUN_Conserv(pFr, SMC_EXTEND_FRUSTUM | SMC_SHADOW_FRUSTUM_TEST, fGSMBoxSize, fDistanceFromView, nLod, passInfo);
  489.  
  490.                 const uint32 renderNodeFlags = pFr->m_eFrustumType == ShadowMapFrustum::e_GsmDynamicDistance ? ERF_DYNAMIC_DISTANCESHADOWS : 0xFFFFFFFF;
  491.                 FillFrustumCastersList_SUN(pFr, SMC_EXTEND_FRUSTUM | SMC_SHADOW_FRUSTUM_TEST, renderNodeFlags, lstCastersHull, nLod, passInfo);
  492.         }
  493.         else if (m_light.m_Flags & (DLF_PROJECT | DLF_AREA_LIGHT))
  494.         {
  495.                 InitShadowFrustum_PROJECTOR(pFr, SMC_EXTEND_FRUSTUM | SMC_SHADOW_FRUSTUM_TEST, passInfo);
  496.                 FillFrustumCastersList_PROJECTOR(pFr, SMC_EXTEND_FRUSTUM | SMC_SHADOW_FRUSTUM_TEST, passInfo);
  497.         }
  498.         else
  499.         {
  500.                 pFr->bOmniDirectionalShadow = true;
  501.                 InitShadowFrustum_OMNI(pFr, SMC_EXTEND_FRUSTUM | SMC_SHADOW_FRUSTUM_TEST, passInfo);
  502.                 FillFrustumCastersList_OMNI(pFr, SMC_EXTEND_FRUSTUM | SMC_SHADOW_FRUSTUM_TEST, passInfo);
  503.         }
  504.  
  505.         CalculateShadowBias(pFr, nLod, fGSMBoxSize);
  506.  
  507.         if (GetCVars()->e_ShadowsFrustums && pFr && pFr->castersList.Count())
  508.                 pFr->DrawFrustum(GetRenderer(), (GetCVars()->e_ShadowsFrustums == 1) ? 1000 : 1);
  509.  
  510.         return bDoGSM;
  511. }
  512.  
  513. // note: drop it
  514. /*void GetPointBBoxDistances(const Vec3 & vPoint, const Vec3 & mins, const Vec3 & maxs,
  515.    float & fMinDist, float & fMaxDist)
  516.    {
  517.    Vec3 arrVerts3d[8] =
  518.    {
  519.    Vec3(mins.x,mins.y,mins.z),
  520.    Vec3(mins.x,maxs.y,mins.z),
  521.    Vec3(maxs.x,mins.y,mins.z),
  522.    Vec3(maxs.x,maxs.y,mins.z),
  523.    Vec3(mins.x,mins.y,maxs.z),
  524.    Vec3(mins.x,maxs.y,maxs.z),
  525.    Vec3(maxs.x,mins.y,maxs.z),
  526.    Vec3(maxs.x,maxs.y,maxs.z)
  527.    };
  528.  
  529.    typedef Triangle_tpl<float> MyTriangle;
  530.  
  531.    //     1______3
  532.    //     /      /|
  533.    //   /      / |
  534.    //   0------2  |
  535.    //   |   5  |  /7
  536.    //   |      | /
  537.    //   |      |/
  538.    //   4------6
  539.  
  540.    float fDistancesSq[12] =
  541.    {
  542.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[0],arrVerts3d[1],arrVerts3d[2]))),
  543.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[1],arrVerts3d[3],arrVerts3d[2]))),
  544.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[5],arrVerts3d[6],arrVerts3d[7]))),
  545.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[5],arrVerts3d[4],arrVerts3d[6]))),
  546.  
  547.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[0],arrVerts3d[2],arrVerts3d[6]))),
  548.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[0],arrVerts3d[6],arrVerts3d[4]))),
  549.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[2],arrVerts3d[3],arrVerts3d[7]))),
  550.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[2],arrVerts3d[7],arrVerts3d[6]))),
  551.  
  552.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[5],arrVerts3d[1],arrVerts3d[0]))),
  553.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[5],arrVerts3d[0],arrVerts3d[4]))),
  554.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[3],arrVerts3d[1],arrVerts3d[5]))),
  555.    (Distance::Point_TriangleSq( vPoint, MyTriangle(arrVerts3d[3],arrVerts3d[5],arrVerts3d[7]))),
  556.    };
  557.  
  558.    // take sqrt_tpl at end
  559.    fMinDist = fDistancesSq[0];
  560.    fMaxDist = fDistancesSq[0];
  561.    for(int i=0; i<12; i++)
  562.    {
  563.    if(fDistancesSq[i]<fMinDist)
  564.    fMinDist = fDistancesSq[i];
  565.    }
  566.  
  567.    for(int i=0; i<8; i++)
  568.    {
  569.    float fVertDistSq = arrVerts3d[i].GetSquaredDistance(vPoint);
  570.    if(fVertDistSq>fMaxDist)
  571.    fMaxDist = fVertDistSq;
  572.    }
  573.  
  574.    fMinDist = sqrt_tpl(fMinDist);
  575.    fMaxDist = sqrt_tpl(fMaxDist);
  576.    }*/
  577.  
  578. float frac_my(float fVal, float fSnap)
  579. {
  580.         float fValSnapped = fVal - fSnap * int(fVal / fSnap);
  581.         return fValSnapped;
  582. }
  583.  
  584. void CLightEntity::InitShadowFrustum_SUN_Conserv(ShadowMapFrustum* pFr, int dwAllowedTypes, float fGSMBoxSize, float fDistance, int nLod, const SRenderingPassInfo& passInfo)
  585. {
  586.         FUNCTION_PROFILER_3DENGINE;
  587.  
  588.         assert(nLod >= 0 && nLod < MAX_GSM_LODS_NUM);
  589.  
  590.         //Toggle between centered or frustrum optimized position for cascade
  591.         fDistance = GetCVars()->e_ShadowsCascadesCentered ? 0 : fDistance;
  592.  
  593.         //TOFIX: replace fGSMBoxSize  by fRadius
  594.         float fRadius = fGSMBoxSize;
  595.  
  596. #ifdef FEATURE_SVO_GI
  597.         if (GetCVars()->e_svoTI_Apply && GetCVars()->e_svoTI_InjectionMultiplier && nLod == GetCVars()->e_svoTI_GsmCascadeLod)
  598.                 fRadius += min(GetCVars()->e_svoTI_RsmConeMaxLength, GetCVars()->e_svoTI_ConeMaxLength);
  599. #endif
  600.  
  601.         //Calc center of projection based on the current screen and LOD radius
  602.         //Vec3 vEdgeScreen = GetCamera().GetEdgeN(); //GetEdgeP();
  603.         Vec3 vViewDir = passInfo.GetCamera().GetViewdir();
  604.         //float fDistance = sqrt_tpl( fGSMBoxSize*fGSMBoxSize - vEdgeScreen.z*vEdgeScreen.z - vEdgeScreen.x*vEdgeScreen.x ) + vEdgeScreen.y;
  605.  
  606.         pFr->RequestUpdate();
  607.  
  608.         pFr->nShadowMapLod = nLod;
  609.         pFr->vLightSrcRelPos = m_light.m_Origin - passInfo.GetCamera().GetPosition();
  610.         pFr->fRadius = m_light.m_fRadius;
  611.         assert(m_light.m_pOwner);
  612.         pFr->pLightOwner = m_light.m_pOwner;
  613.         pFr->m_Flags = m_light.m_Flags;
  614.         pFr->bIncrementalUpdate = false;
  615.  
  616.         const AABB& box = GetBBox();
  617.         const float fBoxRadius = max(0.00001f, box.GetRadius());
  618.  
  619.         //      float fDistToLightSrc = pFr->vLightSrcRelPos.GetLength();
  620.         pFr->fFOV = (float)RAD2DEG(atan_tpl(fRadius / DISTANCE_TO_THE_SUN)) * 2.0f;
  621.         if (pFr->fFOV > LIGHT_PROJECTOR_MAX_FOV)
  622.                 pFr->fFOV = LIGHT_PROJECTOR_MAX_FOV;
  623.         pFr->fProjRatio = 1.0f;
  624.  
  625.         //Sampling parameters
  626.         //Calculate proper projection of frustum to the terrain receiving area but not based on fBoxRadius
  627.         float fGsmInitRange = Get3DEngine()->m_fGsmRange;
  628.         float fGsmStep = Get3DEngine()->m_fGsmRangeStep;
  629.  
  630.         float arrWidthS[] = { 1.94f, 1.0f, 0.8f, 0.5f, 0.3f, 0.3f, 0.3f, 0.3f };
  631.  
  632.         pFr->fWidthS = arrWidthS[nLod];//fBoxRadiusMax/arrRangeS[nLod]; //fBoxRadius //*GetCVars()->e_ShadowsMaxTexRes *
  633.         pFr->fWidthT = pFr->fWidthS;
  634.         pFr->fBlurS = 0.0f;//arrBlurS[nLod];
  635.         pFr->fBlurT = pFr->fBlurS;
  636.  
  637.         Vec3 vLightDir = pFr->vLightSrcRelPos.normalized();
  638.  
  639.         float fDist = pFr->vLightSrcRelPos.GetLength();
  640.  
  641.         //float fMaxFrustEdge = GSM_GetNextScreenEdge(fGSMBoxSize, fDistance).GetLength();
  642.         Vec3 vEdgeN = passInfo.GetCamera().GetEdgeN();
  643.         Vec3 vCamSpView(0.0f, fDistance, 0.0f);
  644.         float fEdgeScale = (fDistance + fGSMBoxSize) / vEdgeN.y * vEdgeN.GetLength();
  645.         float fMaxFrustEdge = ((vEdgeN.GetNormalized() * fEdgeScale) - vCamSpView).GetLength();
  646.         fMaxFrustEdge *= 1.37f;
  647.  
  648.         //if(fGSMBoxSize>500)
  649.         //{
  650.         //  pFr->fNearDist = (fDist - fGSMBoxSize*2.f);
  651.         //  pFr->fFarDist  = (fDist + fGSMBoxSize*2.f);
  652.         //}
  653.         //else
  654.         {
  655.                 //if (Get3DEngine()->m_fSunClipPlaneRange) <= 256.5f)
  656.                 //{
  657.                 //      pFr->fNearDist = (fDist - Get3DEngine()->m_fSunClipPlaneRange));
  658.                 //      pFr->fFarDist  = (fDist + Get3DEngine()->m_fSunClipPlaneRange));
  659.                 //}
  660.  
  661.                 pFr->fRendNear = fDist - fMaxFrustEdge;
  662.                 //pFr->fRendFar = fDist + fMaxFrustEdge;
  663.  
  664.                 const float fDepthRange = 2.0f * max(Get3DEngine()->m_fSunClipPlaneRange, fMaxFrustEdge);
  665.                 const float fNearAdjust = Lerp(fDepthRange - fMaxFrustEdge, fMaxFrustEdge, Get3DEngine()->m_fSunClipPlaneRangeShift);
  666.  
  667.                 pFr->fNearDist = fDist - fNearAdjust;
  668.                 pFr->fFarDist = fDist + fDepthRange - fNearAdjust;
  669.         }
  670.  
  671.         if (pFr->fFarDist > m_light.m_fRadius)
  672.                 pFr->fFarDist = m_light.m_fRadius;
  673.  
  674.         if (pFr->fNearDist < pFr->fFarDist * 0.005f)
  675.                 pFr->fNearDist = pFr->fFarDist * 0.005f;
  676.  
  677.         assert(pFr->fNearDist < pFr->fFarDist);
  678.  
  679.         pFr->nTexSize = GetCVars()->e_ShadowsMaxTexRes;
  680.  
  681.         //if(pFr->isUpdateRequested(-1))
  682.         pFr->vProjTranslation = passInfo.GetCamera().GetPosition() + fDistance * vViewDir;
  683.         ;
  684.  
  685.         // local jitter amount depends on frustum size
  686.         pFr->fFrustrumSize = 1.0f / (fGSMBoxSize * (float)Get3DEngine()->m_fGsmRange);
  687.         pFr->nUpdateFrameId = passInfo.GetFrameID();
  688.         pFr->bIncrementalUpdate = false;
  689.  
  690.         //Get gsm bounds
  691.         GetGsmFrustumBounds(passInfo.GetCamera(), pFr);
  692.  
  693.         //      pFr->fDepthTestBias = (pFr->fFarDist - pFr->fNearDist) * 0.0001f * (fGSMBoxSize/2.f);
  694.         if (GetCVars()->e_ShadowsBlendCascades)
  695.         {
  696.                 pFr->bBlendFrustum = true;
  697.                 pFr->fBlendVal = GetCVars()->e_ShadowsBlendCascadesVal;
  698.  
  699.                 CCamera& BlendCam = pFr->FrustumPlanes[1] = pFr->FrustumPlanes[0];
  700.                 BlendCam.SetFrustum(256, 256, pFr->fBlendVal * pFr->fFOV * (gf_PI / 180.0f), pFr->fNearDist, pFr->fFarDist);
  701.         }
  702.         else
  703.         {
  704.                 pFr->bBlendFrustum = false;
  705.                 pFr->fBlendVal = 1.0f;
  706.         }
  707. }
  708.  
  709. void CLightEntity::CalculateShadowBias(ShadowMapFrustum* pFr, int nLod, float fGSMBoxSize) const
  710. {
  711.         const float* arrDepthConstBias = Get3DEngine()->GetShadowsCascadesConstBias();
  712.         const float* arrDepthSlopeBias = Get3DEngine()->GetShadowsCascadesSlopeBias();
  713.  
  714.         assert(nLod >= 0 && nLod < 8);
  715.  
  716.         if (m_light.m_Flags & DLF_SUN)
  717.         {
  718.                 float fVladRatio = min(fGSMBoxSize / 2.f, 1.f);
  719.                 float fConstBiasRatio = arrDepthConstBias[nLod] * Get3DEngine()->m_fShadowsConstBias * fVladRatio;
  720.                 float fSlopeBiasRatio = arrDepthSlopeBias[nLod] * Get3DEngine()->m_fShadowsSlopeBias * fVladRatio;
  721.  
  722.                 pFr->fDepthConstBias = fConstBiasRatio * (pFr->fFarDist - pFr->fNearDist) / (872727.27f * 2.0f) /** 0.000000001f;*/;
  723.                 pFr->fDepthTestBias = fVladRatio * (pFr->fFarDist - pFr->fNearDist) * (fGSMBoxSize * 0.5f * 0.5f + 0.5f) * 0.0000005f;
  724.                 pFr->fDepthSlopeBias = fSlopeBiasRatio * (fGSMBoxSize / max(0.00001f, Get3DEngine()->m_fGsmRange)) * 0.1f;
  725.  
  726.                 if (pFr->IsCached())
  727.                 {
  728.                         pFr->fDepthConstBias = min(pFr->fDepthConstBias, 0.005f); // clamp bias as for cached frustums distance between near and far can be massive
  729.                 }
  730.         }
  731.         else
  732.         {
  733.                 pFr->fDepthConstBias = m_light.m_fShadowBias * 0.000003f * pFr->fFarDist;  //should be reverted to 0.0000001 after fixinf +X-frustum
  734.                 pFr->fDepthTestBias = 0.00028f * pFr->fFarDist;//(fTexRatio * 0.5) + */( (pFr->fFarDist - pFr->fNearDist) * 0.5f/1535.f );
  735.                 pFr->fDepthSlopeBias = m_light.m_fShadowSlopeBias * Get3DEngine()->m_fShadowsSlopeBias;
  736.         }
  737.  
  738.         if (pFr->fDepthTestBias > 0.005f)
  739.                 pFr->fDepthTestBias = 0.005f;
  740.  
  741.         if (pFr->fNearDist < 1000.f) // if not sun
  742.                 if (pFr->fDepthTestBias < 0.0005f)
  743.                         pFr->fDepthTestBias = 0.0005f;
  744. }
  745.  
  746. bool SegmentFrustumIntersection(const Vec3& P0, const Vec3& P1, const CCamera& frustum, Vec3* pvIntesectP0 = NULL, Vec3* pvIntesectP1 = NULL)
  747. {
  748.         if (P0.IsEquivalent(P1))
  749.         {
  750.                 return frustum.IsPointVisible(P0);
  751.         }
  752.  
  753.         //Actual Segment-Frustum intersection test
  754.         float tE = 0.0f;
  755.         float tL = 1.0f;
  756.         Vec3 dS = P1 - P0;
  757.  
  758.         for (int i = 0; i < 6; i++)
  759.         {
  760.                 const Plane* currPlane = frustum.GetFrustumPlane(i);
  761.  
  762.                 Vec3 ni = currPlane->n;
  763.                 Vec3 Vi = ni * (-currPlane->d);
  764.  
  765.                 float N = -(ni | Vec3(P0 - Vi));
  766.                 float D = ni | dS;
  767.  
  768.                 if (D == 0) //segment is parallel to face
  769.                 {
  770.                         if (N < 0)
  771.                                 return false; //outside face
  772.                         else
  773.                                 continue; //inside face
  774.                 }
  775.  
  776.                 float t = N / D;
  777.                 if (D < 0) //segment is entering face
  778.                 {
  779.                         tE = max(tE, t);
  780.                         if (tE > tL)
  781.                                 return false;
  782.                 }
  783.                 else //segment is leaving face
  784.                 {
  785.                         tL = min(tL, t);
  786.                         if (tL < tE)
  787.                                 return false;
  788.                 }
  789.         }
  790.         //calc intersection point if needed
  791.         if (pvIntesectP0)
  792.                 *pvIntesectP0 = P0 + tE * dS;   // = P(tE) = point where S enters polygon
  793.         if (pvIntesectP1)
  794.                 *pvIntesectP1 = P0 + tL * dS;   // = P(tL) = point where S leaves polygon
  795.  
  796.         //it's intersecting frustum
  797.         return true;
  798. }
  799.  
  800. bool CLightEntity::FrustumIntersection(const CCamera& viewFrustum, const CCamera& shadowFrustum)
  801. {
  802.         int i;
  803.  
  804.         Vec3 pvViewFrust[8];
  805.         Vec3 pvShadowFrust[8];
  806.  
  807.         viewFrustum.GetFrustumVertices(pvViewFrust);
  808.         shadowFrustum.GetFrustumVertices(pvShadowFrust);
  809.  
  810.         //test points inclusion
  811.         //8 points
  812.         for (i = 0; i < 8; i++)
  813.         {
  814.                 if (viewFrustum.IsPointVisible(pvShadowFrust[i]))
  815.                 {
  816.                         return true;
  817.                 }
  818.  
  819.                 if (shadowFrustum.IsPointVisible(pvViewFrust[i]))
  820.                 {
  821.                         return true;
  822.                 }
  823.         }
  824.  
  825.         //fixme: clean code with frustum edges
  826.         //12 edges
  827.         for (i = 0; i < 4; i++)
  828.         {
  829.                 //far face
  830.                 if (SegmentFrustumIntersection(pvShadowFrust[i], pvShadowFrust[(i + 1) % 4], viewFrustum))
  831.                         return true;
  832.                 //near face
  833.                 if (SegmentFrustumIntersection(pvShadowFrust[i + 4], pvShadowFrust[(i + 1) % 4 + 4], viewFrustum))
  834.                         return true;
  835.                 //other edges
  836.                 if (SegmentFrustumIntersection(pvShadowFrust[i], pvShadowFrust[i + 4], viewFrustum))
  837.                         return true;
  838.  
  839.                 //vice-versa test
  840.                 //far face
  841.                 if (SegmentFrustumIntersection(pvViewFrust[i], pvViewFrust[(i + 1) % 4], shadowFrustum))
  842.                         return true;
  843.                 //near face
  844.                 if (SegmentFrustumIntersection(pvViewFrust[i + 4], pvViewFrust[(i + 1) % 4 + 4], shadowFrustum))
  845.                         return true;
  846.                 //other edges
  847.                 if (SegmentFrustumIntersection(pvViewFrust[i], pvViewFrust[i + 4], shadowFrustum))
  848.                         return true;
  849.         }
  850.  
  851.         return false;
  852. }
  853.  
  854. //TODO: should be in the renderer or in 3dengine only (with FrustumIntersection)
  855. /*void GetShadowMatrixOrtho(Matrix44& mLightProj, Matrix44& mLightView, const Matrix44& mViewMatrix, ShadowMapFrustum* lof, bool bViewDependent)
  856.    {
  857.  
  858.    mathMatrixPerspectiveFov(&mLightProj, lof->fFOV*(gf_PI/180.0f), lof->fProjRatio, lof->fNearDist, lof->fFarDist);
  859.  
  860.    const Vec3 zAxis(0.f, 0.f, 1.f);
  861.    const Vec3 yAxis(0.f, 1.f, 0.f);
  862.    Vec3 Up;
  863.    Vec3 Eye = Vec3(
  864.    lof->vLightSrcRelPos.x+lof->vProjTranslation.x,
  865.    lof->vLightSrcRelPos.y+lof->vProjTranslation.y,
  866.    lof->vLightSrcRelPos.z+lof->vProjTranslation.z);
  867.    Vec3 At = Vec3(lof->vProjTranslation.x, lof->vProjTranslation.y, lof->vProjTranslation.z);
  868.  
  869.    Vec3 vLightDir = At - Eye;
  870.    vLightDir.Normalize();
  871.  
  872.    //D3DXVECTOR3 eyeLightDir;
  873.    //D3DXVec3TransformNormal(&eyeLightDir, &vLightDir, pmViewMatrix);
  874.  
  875.    if (bViewDependent)
  876.    {
  877.    //we should have LightDir vector transformed to the view space
  878.  
  879.    Eye = GetTransposed44(mViewMatrix).TransformPoint(Eye);
  880.    At = GetTransposed44(mViewMatrix).TransformPoint(At);
  881.  
  882.    vLightDir = GetTransposed44(mViewMatrix).TransformVector(vLightDir);
  883.    //vLightDir.Normalize();
  884.    }
  885.  
  886.    if ( fabsf(vLightDir.Dot(zAxis))>0.95f )
  887.    Up = yAxis;
  888.    else
  889.    Up = zAxis;
  890.  
  891.    //Eye        = Vec3(8745.8809, 1281.8682, 5086.0918);
  892.    //At = Vec3(212.88541, 90.157082, 8.6914768);
  893.    //Up = Vec3(0.00000000, 0.00000000, 1.0000000);
  894.  
  895.    //get look-at matrix
  896.    mathMatrixLookAt(&mLightView, Eye, At, Up);
  897.  
  898.    //we should transform coords to the view space, so shadows are oriented according to camera always
  899.    if (bViewDependent)
  900.    {
  901.    mLightView = mViewMatrix * mLightView;
  902.    }
  903.  
  904.    }*/
  905.  
  906. bool CLightEntity::GetGsmFrustumBounds(const CCamera& viewFrustum, ShadowMapFrustum* pShadowFrustum)
  907. {
  908.         int i;
  909.  
  910.         Vec3 pvViewFrust[8];
  911.         Vec3 pvShadowFrust[8];
  912.  
  913.         CCamera& camShadowFrustum = pShadowFrustum->FrustumPlanes[0];
  914.  
  915.         Matrix34A mShadowView, mShadowProj;
  916.         Matrix34A mShadowComposite;
  917.  
  918.         //get composite shadow matrix to compute bounds
  919.         //FIX: check viewFrustum.GetMatrix().GetInverted()???
  920.         Matrix44A mCameraView = Matrix44A(viewFrustum.GetMatrix().GetInverted());
  921.         /*GetShadowMatrixOrtho( mShadowProj,
  922.            mShadowView,
  923.            mCameraView, pShadowFrustum, false);*/
  924.  
  925.         //Pre-multiply matrices
  926.         //renderer coord system
  927.         //FIX: replace this hack with full projective depth bound computations (light space z currently)
  928.         mShadowComposite = viewFrustum.GetMatrix().GetInverted(); /** mShadowProj*/;
  929.         //GetTransposed44(Matrix44(Matrix33::CreateRotationX(-gf_PI/2) * viewFrustum.GetMatrix().GetInverted()));
  930.  
  931.         //set CCamera
  932.         //engine coord system
  933.         //FIX: should be processed like this
  934.         //camShadowFrustum.SetMatrix( Matrix34( GetTransposed44(mShadowView) ) );
  935.         //camShadowFrustum.SetFrustum(pShadowFrustum->nTexSize,pShadowFrustum->nTexSize,pShadowFrustum->fFOV*(gf_PI/180.0f), pShadowFrustum->fNearDist, pShadowFrustum->fFarDist);
  936.  
  937.         viewFrustum.GetFrustumVertices(pvViewFrust);
  938.         camShadowFrustum.GetFrustumVertices(pvShadowFrust);
  939.  
  940.         Vec3 vCamPosition = viewFrustum.GetPosition();
  941.  
  942.         Vec3 vIntersectP0(0, 0, 0), vIntersectP1(0, 0, 0);
  943.  
  944.         AABB viewAABB;
  945.         viewAABB.Reset();
  946.  
  947.         bool bIntersected = false;
  948.         Vec3 vP0_NDC, vP1_NDC;
  949.         f32 fZ_NDC_Max = 0.0f; // nead plane
  950.         f32 fDisatanceToMaxBound = 0;
  951.         Vec3 vMaxBoundPoint(ZERO);
  952.  
  953.         //fixme: clean code with frustum edges
  954.         //12 edges
  955.         for (i = 0; i < 4; i++)
  956.         {
  957.                 //far face
  958.                 if (SegmentFrustumIntersection(pvShadowFrust[i], pvShadowFrust[(i + 1) % 4], viewFrustum, &vIntersectP0, &vIntersectP1))
  959.                 {
  960.                         //viewAABB.Add(vIntersectP0);
  961.                         //viewAABB.Add(vIntersectP1);
  962.  
  963.                         if (GetCVars()->e_GsmDepthBoundsDebug)
  964.                         {
  965.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLine(vIntersectP0, RGBA8(0xff, 0xff, 0x1f, 0xff), vIntersectP1, RGBA8(0xff, 0xff, 0x1f, 0xff), 2.0f);
  966.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP0, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  967.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP1, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  968.                         }
  969.  
  970.                         //todo: move to func
  971.                         //projection
  972.                         //vP0_NDC = Vec4(vIntersectP0,1.0f) * mShadowComposite;
  973.                         //vP0_NDC /= vP0_NDC.w;
  974.  
  975.                         /*vP0_NDC = mShadowComposite.TransformPoint(vIntersectP0);
  976.  
  977.                            fZ_NDC_Min = min(fZ_NDC_Min, vP0_NDC.z);
  978.                            fZ_NDC_Max = max(fZ_NDC_Max, vP0_NDC.z);*/
  979.  
  980.                         //vP1_NDC = Vec4(vIntersectP1,1.0f) * mShadowComposite;
  981.                         //vP1_NDC /= vP1_NDC.w;
  982.  
  983.                         /*vP1_NDC = mShadowComposite.TransformPoint(vIntersectP1);
  984.  
  985.                            fZ_NDC_Min = min(fZ_NDC_Min, vP1_NDC.z);
  986.                            fZ_NDC_Max = max(fZ_NDC_Max, vP1_NDC.z);*/
  987.  
  988.                         float fCurDistance = (vCamPosition - vIntersectP0).GetLength();
  989.                         if (fCurDistance > fDisatanceToMaxBound)
  990.                         {
  991.                                 vMaxBoundPoint = vIntersectP0;
  992.                                 fDisatanceToMaxBound = fCurDistance;
  993.                         }
  994.  
  995.                         fCurDistance = (vCamPosition - vIntersectP1).GetLength();
  996.                         if (fCurDistance > fDisatanceToMaxBound)
  997.                         {
  998.                                 vMaxBoundPoint = vIntersectP1;
  999.                                 fDisatanceToMaxBound = fCurDistance;
  1000.                         }
  1001.  
  1002.                         bIntersected = true;
  1003.                 }
  1004.  
  1005.                 //near face
  1006.                 if (SegmentFrustumIntersection(pvShadowFrust[i + 4], pvShadowFrust[(i + 1) % 4 + 4], viewFrustum, &vIntersectP0, &vIntersectP1))
  1007.                 {
  1008.                         //viewAABB.Add(vIntersectP0);
  1009.                         //viewAABB.Add(vIntersectP1);
  1010.  
  1011.                         if (GetCVars()->e_GsmDepthBoundsDebug)
  1012.                         {
  1013.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLine(vIntersectP0, RGBA8(0xff, 0xff, 0x1f, 0xff), vIntersectP1, RGBA8(0xff, 0xff, 0x1f, 0xff), 2.0f);
  1014.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP0, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1015.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP1, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1016.                         }
  1017.  
  1018.                         //todo: move to func
  1019.                         //projection
  1020.                         //vP0_NDC = Vec4(vIntersectP0,1.0f) * mShadowComposite;
  1021.                         //vP0_NDC /= vP0_NDC.w;
  1022.  
  1023.                         /*vP0_NDC = mShadowComposite.TransformPoint(vIntersectP0);
  1024.  
  1025.                            fZ_NDC_Min = min(fZ_NDC_Min, vP0_NDC.z);
  1026.                            fZ_NDC_Max = max(fZ_NDC_Max, vP0_NDC.z);*/
  1027.  
  1028.                         //vP1_NDC = Vec4(vIntersectP1,1.0f) * mShadowComposite;
  1029.                         //vP1_NDC /= vP1_NDC.w;
  1030.  
  1031.                         /*vP1_NDC = mShadowComposite.TransformPoint(vIntersectP1);
  1032.  
  1033.                            fZ_NDC_Min = min(fZ_NDC_Min, vP1_NDC.z);
  1034.                            fZ_NDC_Max = max(fZ_NDC_Max, vP1_NDC.z);*/
  1035.  
  1036.                         float fCurDistance = (vCamPosition - vIntersectP0).GetLength();
  1037.                         if (fCurDistance > fDisatanceToMaxBound)
  1038.                         {
  1039.                                 vMaxBoundPoint = vIntersectP0;
  1040.                                 fDisatanceToMaxBound = fCurDistance;
  1041.                         }
  1042.  
  1043.                         fCurDistance = (vCamPosition - vIntersectP1).GetLength();
  1044.                         if (fCurDistance > fDisatanceToMaxBound)
  1045.                         {
  1046.                                 vMaxBoundPoint = vIntersectP1;
  1047.                                 fDisatanceToMaxBound = fCurDistance;
  1048.                         }
  1049.  
  1050.                         bIntersected = true;
  1051.                 }
  1052.  
  1053.                 //other edges
  1054.                 if (SegmentFrustumIntersection(pvShadowFrust[i], pvShadowFrust[i + 4], viewFrustum, &vIntersectP0, &vIntersectP1))
  1055.                 {
  1056.                         //viewAABB.Add(vIntersectP0);
  1057.                         //viewAABB.Add(vIntersectP1);
  1058.  
  1059.                         if (GetCVars()->e_GsmDepthBoundsDebug)
  1060.                         {
  1061.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLine(vIntersectP0, RGBA8(0xff, 0xff, 0x1f, 0xff), vIntersectP1, RGBA8(0xff, 0xff, 0x1f, 0xff), 2.0f);
  1062.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP0, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1063.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP1, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1064.                         }
  1065.  
  1066.                         //todo: move to func
  1067.                         //projection
  1068.                         //vP0_NDC = Vec4(vIntersectP0,1.0f) * mShadowComposite;
  1069.                         //vP0_NDC /= vP0_NDC.w;
  1070.  
  1071.                         /*vP0_NDC = mShadowComposite.TransformPoint(vIntersectP0);
  1072.  
  1073.                            fZ_NDC_Min = min(fZ_NDC_Min, vP0_NDC.z);
  1074.                            fZ_NDC_Max = max(fZ_NDC_Max, vP0_NDC.z);*/
  1075.  
  1076.                         //vP1_NDC = Vec4(vIntersectP1,1.0f) * mShadowComposite;
  1077.                         //vP1_NDC /= vP1_NDC.w;
  1078.  
  1079.                         /*vP1_NDC = mShadowComposite.TransformPoint(vIntersectP1);
  1080.  
  1081.                            fZ_NDC_Min = min(fZ_NDC_Min, vP1_NDC.z);
  1082.                            fZ_NDC_Max = max(fZ_NDC_Max, vP1_NDC.z);*/
  1083.  
  1084.                         float fCurDistance = (vCamPosition - vIntersectP0).GetLength();
  1085.                         if (fCurDistance > fDisatanceToMaxBound)
  1086.                         {
  1087.                                 vMaxBoundPoint = vIntersectP0;
  1088.                                 fDisatanceToMaxBound = fCurDistance;
  1089.                         }
  1090.  
  1091.                         fCurDistance = (vCamPosition - vIntersectP1).GetLength();
  1092.                         if (fCurDistance > fDisatanceToMaxBound)
  1093.                         {
  1094.                                 vMaxBoundPoint = vIntersectP1;
  1095.                                 fDisatanceToMaxBound = fCurDistance;
  1096.                         }
  1097.  
  1098.                         bIntersected = true;
  1099.                 }
  1100.  
  1101.                 //vice-versa test
  1102.                 //far face
  1103.                 if (SegmentFrustumIntersection(pvViewFrust[i], pvViewFrust[(i + 1) % 4], camShadowFrustum, &vIntersectP0, &vIntersectP1))
  1104.                 {
  1105.                         //viewAABB.Add(vIntersectP0);
  1106.                         //viewAABB.Add(vIntersectP1);
  1107.  
  1108.                         if (GetCVars()->e_GsmDepthBoundsDebug)
  1109.                         {
  1110.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLine(vIntersectP0, RGBA8(0xff, 0xff, 0x1f, 0xff), vIntersectP1, RGBA8(0xff, 0xff, 0x1f, 0xff), 2.0f);
  1111.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP0, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1112.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP1, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1113.                         }
  1114.  
  1115.                         //todo: move to func
  1116.                         //projection
  1117.                         //vP0_NDC = Vec4(vIntersectP0,1.0f) * mShadowComposite;
  1118.                         //vP0_NDC /= vP0_NDC.w;
  1119.  
  1120.                         /*vP0_NDC = mShadowComposite.TransformPoint(vIntersectP0);
  1121.  
  1122.                            fZ_NDC_Min = min(fZ_NDC_Min, vP0_NDC.z);
  1123.                            fZ_NDC_Max = max(fZ_NDC_Max, vP0_NDC.z);*/
  1124.  
  1125.                         //vP1_NDC = Vec4(vIntersectP1,1.0f) * mShadowComposite;
  1126.                         //vP1_NDC /= vP1_NDC.w;
  1127.  
  1128.                         /*vP1_NDC = mShadowComposite.TransformPoint(vIntersectP1);
  1129.  
  1130.                            fZ_NDC_Min = min(fZ_NDC_Min, vP1_NDC.z);
  1131.                            fZ_NDC_Max = max(fZ_NDC_Max, vP1_NDC.z);*/
  1132.  
  1133.                         float fCurDistance = (vCamPosition - vIntersectP0).GetLength();
  1134.                         if (fCurDistance > fDisatanceToMaxBound)
  1135.                         {
  1136.                                 vMaxBoundPoint = vIntersectP0;
  1137.                                 fDisatanceToMaxBound = fCurDistance;
  1138.                         }
  1139.  
  1140.                         fCurDistance = (vCamPosition - vIntersectP1).GetLength();
  1141.                         if (fCurDistance > fDisatanceToMaxBound)
  1142.                         {
  1143.                                 vMaxBoundPoint = vIntersectP1;
  1144.                                 fDisatanceToMaxBound = fCurDistance;
  1145.                         }
  1146.  
  1147.                         bIntersected = true;
  1148.                 }
  1149.  
  1150.                 if (SegmentFrustumIntersection(pvViewFrust[i + 4], pvViewFrust[(i + 1) % 4 + 4], camShadowFrustum, &vIntersectP0, &vIntersectP1))
  1151.                 {
  1152.                         //viewAABB.Add(vIntersectP0);
  1153.                         //viewAABB.Add(vIntersectP1);
  1154.  
  1155.                         if (GetCVars()->e_GsmDepthBoundsDebug)
  1156.                         {
  1157.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLine(vIntersectP0, RGBA8(0xff, 0xff, 0x1f, 0xff), vIntersectP1, RGBA8(0xff, 0xff, 0x1f, 0xff), 2.0f);
  1158.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP0, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1159.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP1, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1160.                         }
  1161.  
  1162.                         //todo: move to func
  1163.                         //projection
  1164.                         //vP0_NDC = Vec4(vIntersectP0,1.0f) * mShadowComposite;
  1165.                         //vP0_NDC /= vP0_NDC.w;
  1166.  
  1167.                         /*vP0_NDC = mShadowComposite.TransformPoint(vIntersectP0);
  1168.  
  1169.                            fZ_NDC_Min = min(fZ_NDC_Min, vP0_NDC.z);
  1170.                            fZ_NDC_Max = max(fZ_NDC_Max, vP0_NDC.z);*/
  1171.  
  1172.                         //vP1_NDC = Vec4(vIntersectP1,1.0f) * mShadowComposite;
  1173.                         //vP1_NDC /= vP1_NDC.w;
  1174.  
  1175.                         /*vP1_NDC = mShadowComposite.TransformPoint(vIntersectP1);
  1176.  
  1177.                            fZ_NDC_Min = min(fZ_NDC_Min, vP1_NDC.z);
  1178.                            fZ_NDC_Max = max(fZ_NDC_Max, vP1_NDC.z);*/
  1179.  
  1180.                         float fCurDistance = (vCamPosition - vIntersectP0).GetLength();
  1181.                         if (fCurDistance > fDisatanceToMaxBound)
  1182.                         {
  1183.                                 vMaxBoundPoint = vIntersectP0;
  1184.                                 fDisatanceToMaxBound = fCurDistance;
  1185.                         }
  1186.  
  1187.                         fCurDistance = (vCamPosition - vIntersectP1).GetLength();
  1188.                         if (fCurDistance > fDisatanceToMaxBound)
  1189.                         {
  1190.                                 vMaxBoundPoint = vIntersectP1;
  1191.                                 fDisatanceToMaxBound = fCurDistance;
  1192.                         }
  1193.  
  1194.                         bIntersected = true;
  1195.                 }
  1196.  
  1197.                 //other edges
  1198.                 if (SegmentFrustumIntersection(pvViewFrust[i], pvViewFrust[i + 4], camShadowFrustum, &vIntersectP0, &vIntersectP1))
  1199.                 {
  1200.                         //viewAABB.Add(vIntersectP0);
  1201.                         //viewAABB.Add(vIntersectP1);
  1202.  
  1203.                         if (GetCVars()->e_GsmDepthBoundsDebug)
  1204.                         {
  1205.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLine(vIntersectP0, RGBA8(0xff, 0xff, 0x1f, 0xff), vIntersectP1, RGBA8(0xff, 0xff, 0x1f, 0xff), 2.0f);
  1206.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP0, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1207.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vIntersectP1, RGBA8(0xff, 0xff, 0xff, 0xff), 10);
  1208.                         }
  1209.  
  1210.                         //todo: move to func
  1211.                         //projection
  1212.                         //vP0_NDC = Vec4(vIntersectP0,1.0f) * mShadowComposite;
  1213.                         //vP0_NDC /= vP0_NDC.w;
  1214.  
  1215.                         /*vP0_NDC = mShadowComposite.TransformPoint(vIntersectP0);
  1216.  
  1217.                            fZ_NDC_Min = min(fZ_NDC_Min, vP0_NDC.z);
  1218.                            fZ_NDC_Max = max(fZ_NDC_Max, vP0_NDC.z);*/
  1219.  
  1220.                         //vP1_NDC = Vec4(vIntersectP1,1.0f) * mShadowComposite;
  1221.                         //vP1_NDC /= vP1_NDC.w;
  1222.  
  1223.                         /*vP1_NDC = mShadowComposite.TransformPoint(vIntersectP1);
  1224.  
  1225.                            fZ_NDC_Min = min(fZ_NDC_Min, vP1_NDC.z);
  1226.                            fZ_NDC_Max = max(fZ_NDC_Max, vP1_NDC.z);*/
  1227.  
  1228.                         float fCurDistance = (vCamPosition - vIntersectP0).GetLength();
  1229.                         if (fCurDistance > fDisatanceToMaxBound)
  1230.                         {
  1231.                                 vMaxBoundPoint = vIntersectP0;
  1232.                                 fDisatanceToMaxBound = fCurDistance;
  1233.                         }
  1234.  
  1235.                         fCurDistance = (vCamPosition - vIntersectP1).GetLength();
  1236.                         if (fCurDistance > fDisatanceToMaxBound)
  1237.                         {
  1238.                                 vMaxBoundPoint = vIntersectP1;
  1239.                                 fDisatanceToMaxBound = fCurDistance;
  1240.                         }
  1241.  
  1242.                         bIntersected = true;
  1243.                 }
  1244.  
  1245.         }
  1246.  
  1247.         if (GetCVars()->e_GsmDepthBoundsDebug)
  1248.         {
  1249.                 GetRenderer()->GetIRenderAuxGeom()->DrawPoint(vMaxBoundPoint, RGBA8(0xff, 0x00, 0x00, 0xff), 10);
  1250.         }
  1251.  
  1252.         //Get3DEngine()->DrawBBox(viewAABB);
  1253.  
  1254.         return bIntersected;
  1255. }
  1256.  
  1257. void GetCubemapFrustum(ShadowMapFrustum* pFr, int nS, CCamera& shadowFrust)
  1258. {
  1259.         //FIX: don't generate frustum in renderer
  1260.         float sCubeVector[6][7] =
  1261.         {
  1262.                 { 1,  0,  0,  0, 0, 1,  -90 }, //posx
  1263.                 { -1, 0,  0,  0, 0, 1,  90  }, //negx
  1264.                 { 0,  1,  0,  0, 0, -1, 0   }, //posy
  1265.                 { 0,  -1, 0,  0, 0, 1,  0   }, //negy
  1266.                 { 0,  0,  1,  0, 1, 0,  0   }, //posz
  1267.                 { 0,  0,  -1, 0, 1, 0,  0   }, //negz
  1268.         };
  1269.  
  1270.         int nShadowTexSize = pFr->nTexSize;
  1271.         Vec3 vPos = pFr->vLightSrcRelPos + pFr->vProjTranslation;
  1272.  
  1273.         Vec3 vForward = Vec3(sCubeVector[nS][0], sCubeVector[nS][1], sCubeVector[nS][2]);
  1274.         Vec3 vUp = Vec3(sCubeVector[nS][3], sCubeVector[nS][4], sCubeVector[nS][5]);
  1275.         Matrix33 matRot = Matrix33::CreateOrientation(vForward, vUp, DEG2RAD(sCubeVector[nS][6]));
  1276.  
  1277.         float fMinDist = pFr->fNearDist;
  1278.         float fMaxDist = pFr->fFarDist;
  1279.         shadowFrust.SetMatrix(Matrix34(matRot, vPos));
  1280.         shadowFrust.SetFrustum(nShadowTexSize, nShadowTexSize, 90.0f * gf_PI / 180.0f, fMinDist, fMaxDist);
  1281. }
  1282.  
  1283. void CLightEntity::CheckValidFrustums_OMNI(ShadowMapFrustum* pFr, const SRenderingPassInfo& passInfo)
  1284. {
  1285.         pFr->nOmniFrustumMask = 0;
  1286.  
  1287.         const CCamera& cameraFrust = passInfo.GetCamera();
  1288.  
  1289.         for (int nS = 0; nS < 6; nS++)
  1290.         {
  1291.  
  1292.                 CCamera shadowFrust;
  1293.                 GetCubemapFrustum(pFr, nS, shadowFrust);
  1294.  
  1295.                 if (FrustumIntersection(cameraFrust, shadowFrust))
  1296.                         pFr->nOmniFrustumMask |= (1 << nS);
  1297.  
  1298.         }
  1299. }
  1300.  
  1301. bool CLightEntity::CheckFrustumsIntersect(CLightEntity* lightEnt)
  1302. {
  1303.         Vec3 pvShadowFrust[8];
  1304.         bool bRes = false;
  1305.  
  1306.         ShadowMapFrustum* pFr1;
  1307.         ShadowMapFrustum* pFr2;
  1308.  
  1309.         pFr1 = this->GetShadowFrustum(0);
  1310.         pFr2 = lightEnt->GetShadowFrustum(0);
  1311.  
  1312.         if (!pFr1 || !pFr2)
  1313.                 return false;
  1314.  
  1315.         int nFaces1, nFaces2;
  1316.         nFaces1 = (pFr1->bOmniDirectionalShadow ? 6 : 1);
  1317.         nFaces2 = (pFr2->bOmniDirectionalShadow ? 6 : 1);
  1318.  
  1319.         for (int nS1 = 0; nS1 < nFaces1; nS1++)
  1320.         {
  1321.                 for (int nS2 = 0; nS2 < nFaces2; nS2++)
  1322.                 {
  1323.                         CCamera shadowFrust1 = pFr1->FrustumPlanes[nS1];
  1324.                         CCamera shadowFrust2 = pFr2->FrustumPlanes[nS2];
  1325.                         ;
  1326.  
  1327.                         if (FrustumIntersection(shadowFrust1, shadowFrust2))
  1328.                         {
  1329.                                 bRes = true;
  1330.  
  1331.                                 //debug frustums
  1332.                                 vtx_idx pnInd[8] = {
  1333.                                         0, 4, 1, 5, 2, 6, 3, 7
  1334.                                 };
  1335.                                 //first frustum
  1336.                                 shadowFrust1.GetFrustumVertices(pvShadowFrust);
  1337.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPolyline(pvShadowFrust, 4, true, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1338.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPolyline(pvShadowFrust + 4, 4, true, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1339.  
  1340.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1341.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd + 2, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1342.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd + 4, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1343.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd + 6, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1344.  
  1345.                                 //second frustum
  1346.                                 shadowFrust2.GetFrustumVertices(pvShadowFrust);
  1347.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPolyline(pvShadowFrust, 4, true, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1348.                                 GetRenderer()->GetIRenderAuxGeom()->DrawPolyline(pvShadowFrust + 4, 4, true, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1349.  
  1350.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1351.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd + 2, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1352.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd + 4, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1353.                                 GetRenderer()->GetIRenderAuxGeom()->DrawLines(pvShadowFrust, 8, pnInd + 6, 2, RGBA8(0xff, 0xff, 0x1f, 0xff));
  1354.  
  1355.                         }
  1356.                 }
  1357.         }
  1358.         return bRes;
  1359. }
  1360.  
  1361. void CLightEntity::InitShadowFrustum_PROJECTOR(ShadowMapFrustum* pFr, int dwAllowedTypes, const SRenderingPassInfo& passInfo)
  1362. {
  1363.         FUNCTION_PROFILER_3DENGINE;
  1364.  
  1365.         const int nFrameId = passInfo.GetMainFrameID();
  1366.  
  1367.         float fShadowUpdate = (float)(m_light.m_nShadowUpdateRatio * GetCVars()->e_ShadowsUpdateViewDistRatio);
  1368.         const float fShadowUpdateScale = (1 << DL_SHADOW_UPDATE_SHIFT) * (1 << DL_SHADOW_UPDATE_SHIFT);  // e_ShadowsUpdateViewDistRatio is also fixed point, 256 == 1.0f
  1369.  
  1370.         // construct camera from projector
  1371.         Matrix34 entMat = ((ILightSource*)m_light.m_pOwner)->GetMatrix();
  1372.  
  1373.         Vec3 vProjDir = entMat.GetColumn(0).GetNormalizedSafe();
  1374.  
  1375.         pFr->nShadowMapLod = -1;    // not used
  1376.  
  1377.         // place center into middle of projector far plane
  1378.         pFr->vLightSrcRelPos = -vProjDir * m_light.m_fRadius;
  1379.         pFr->vProjTranslation = m_light.m_Origin - pFr->vLightSrcRelPos;
  1380.         if (pFr->fRadius != m_light.m_fRadius)
  1381.                 pFr->RequestUpdate();
  1382.         pFr->bIncrementalUpdate = false;
  1383.         pFr->fRadius = m_light.m_fRadius;
  1384.         assert(m_light.m_pOwner && m_light.m_pOwner == this);
  1385.         pFr->pLightOwner = this;
  1386.         pFr->m_Flags = m_light.m_Flags;
  1387.         pFr->bBlendFrustum = false;
  1388.  
  1389.         //      float fDistToLightSrc = pFr->vLightSrcRelPos.GetLength();
  1390.         pFr->fFOV = CLAMP(m_light.m_fLightFrustumAngle * 2.f, 0.0001f, LIGHT_PROJECTOR_MAX_FOV);
  1391.  
  1392.         pFr->fNearDist = 0.01f;
  1393.         pFr->fFarDist = m_light.m_fRadius;
  1394.  
  1395.         // set texture size
  1396.         uint32 nTexSize = GetCVars()->e_ShadowsMaxTexRes;
  1397.  
  1398.         if (pFr->bOmniDirectionalShadow)
  1399.                 nTexSize = GetCVars()->e_ShadowsMaxTexRes / 2;
  1400.  
  1401.         const CCamera& cCam = passInfo.GetCamera();
  1402.  
  1403.         float fLightToCameraDist = cCam.GetPosition().GetDistance(m_light.m_Origin);
  1404.  
  1405.         float fLightToCameraDistAdjusted = max(5.f, fLightToCameraDist - m_light.m_fRadius);
  1406.         while (nTexSize > (800.f / fLightToCameraDistAdjusted) * pFr->fRadius * m_light.m_Color.Luminance() * (pFr->fFOV / 90.f) && nTexSize > 256)
  1407.                 nTexSize /= 2;
  1408.  
  1409.         float shadowUpdateDist = max(0.0f, fLightToCameraDist - m_light.m_fShadowUpdateMinRadius);
  1410.  
  1411.         float shadowUpdateRate = 255.0f;
  1412.  
  1413.         if (GetCVars()->e_ShadowsUpdateViewDistRatio)
  1414.                 shadowUpdateRate = min(255.f, fShadowUpdateScale * shadowUpdateDist * passInfo.GetZoomFactor() / (fShadowUpdate));
  1415.  
  1416.         pFr->nShadowPoolUpdateRate = (uint8) shadowUpdateRate;
  1417.  
  1418.         if (m_light.m_Flags & DLF_DEFERRED_LIGHT)
  1419.         {
  1420.  
  1421.                 float fScaledRadius = m_light.m_fRadius * m_light.m_fShadowResolutionScale;
  1422.                 //TD smooth distribution curve
  1423.                 float fAreaZ0, fAreaZ1;
  1424.                 if (fLightToCameraDist <= m_light.m_fRadius)
  1425.                 {
  1426.                         fAreaZ0 = cCam.GetNearPlane();
  1427.                         fAreaZ1 = 2.0f * fScaledRadius;
  1428.                 }
  1429.                 else
  1430.                 {
  1431.                         fAreaZ0 = max(cCam.GetNearPlane(), fLightToCameraDist - fScaledRadius);
  1432.                         fAreaZ1 = fLightToCameraDist + fScaledRadius;
  1433.                 }
  1434.  
  1435.                 float fCamFactor = log(cCam.GetFarPlane() / cCam.GetNearPlane());
  1436.  
  1437.                 float fFadingBase = GetCVars()->e_ShadowsAdaptScale;
  1438.                 float fSMZ0 = log(fAreaZ0 / cCam.GetNearPlane()) / log(fFadingBase);
  1439.                 float fSMZ1 = log(fAreaZ1 / cCam.GetNearPlane()) / log(fFadingBase);
  1440.                 fSMZ0 /= fCamFactor;
  1441.                 fSMZ1 /= fCamFactor;
  1442.  
  1443.                 float fCoverageScaleFactor = GetCVars()->e_ShadowsResScale;
  1444.                 if (!(m_light.m_Flags & (DLF_PROJECT | DLF_AREA_LIGHT)))
  1445.                         fCoverageScaleFactor /= 3.5f;
  1446.  
  1447.                 nTexSize = int((fSMZ1 - fSMZ0) * ((float)GetCVars()->e_ShadowsMaxTexRes * fCoverageScaleFactor /*/(7*cCam.GetFarPlane())*/));
  1448.  
  1449.                 uint32 nPoolSize = GetCVars()->e_ShadowsPoolSize;
  1450.                 uint32 nMaxTexRes = GetCVars()->e_ShadowsMaxTexRes;
  1451.  
  1452.                 uint32 nMinRes, nMaxRes, nPhysicalMaxRes;
  1453.  
  1454.                 if (m_light.m_Flags & (DLF_PROJECT | DLF_AREA_LIGHT))
  1455.                 {
  1456.                         nMinRes = MIN_SHADOW_RES_PROJ_LIGHT;
  1457.                         nMaxRes = nMaxTexRes;
  1458.                         nPhysicalMaxRes = nPoolSize;
  1459.                 }
  1460.                 else
  1461.                 {
  1462.                         nMinRes = MIN_SHADOW_RES_OMNI_LIGHT;
  1463.                         nMaxRes = nMaxTexRes >> 1;
  1464.                         nPhysicalMaxRes = nPoolSize >> 2;
  1465.                 }
  1466.  
  1467.                 if (m_light.m_nShadowMinResolution)
  1468.                 {
  1469.                         nMinRes = nPoolSize >> (4 - m_light.m_nShadowMinResolution); // 4 possible percentages of pool size exposed in editor 100%, 50%, 25%, 12.5% (IEditorImpl.cpp)
  1470.  
  1471.                         if (nMinRes > nMaxRes)     // if a very large min res is requested, go beyond normal limits, up to physical pool size. CINEMATICS ONLY PLEASE!
  1472.                                 nMaxRes = min(nPhysicalMaxRes, nMinRes);
  1473.                 }
  1474.  
  1475.                 nTexSize = max(nMinRes, nTexSize);
  1476.                 nTexSize = min(min(nMaxRes, nTexSize), nPhysicalMaxRes);  // make sure we never go above pool size
  1477.  
  1478.                 //nTexSize -= (nTexSize % 32);
  1479.                 //nTexSize = max(nTexSize, 32);
  1480.                 //nTexSize = min(nTexSize, GetCVars()->e_ShadowsMaxTexRes*2);
  1481.  
  1482.                 // force power of two
  1483.                 nTexSize = 1 << IntegerLog2((uint32)nTexSize);
  1484.         }
  1485.  
  1486.         if (pFr->nTexSize != nTexSize)
  1487.         {
  1488.                 pFr->nTexSize = nTexSize;
  1489.                 pFr->RequestUpdate();
  1490.         }
  1491.  
  1492.         //      m_pShadowMapInfo->bUpdateRequested = false;
  1493.         //      pFr->bUpdateRequested = true;
  1494.         // local jitter amount depends on frustum size
  1495.         //FIX:: non-linear adjustment for fFrustrumSize
  1496.         pFr->fFrustrumSize = 20.0f * nTexSize / 64.0f; // / (fGSMBoxSize*Get3DEngine()->m_fGsmRange);
  1497.         //pFr->nDLightId = m_light.m_Id;
  1498.  
  1499.         //float fGSMBoxSize =  pFr->fRadius * tan_tpl(DEG2RAD(pFr->fFOV)*0.5f);
  1500.  
  1501.         //pFr->fDepthTestBias = (pFr->fFarDist - pFr->fNearDist) * 0.0001f * (fGSMBoxSize/2.f);
  1502.         //pFr->fDepthTestBias *= (pFr->fFarDist - pFr->fNearDist) / 256.f;
  1503.  
  1504.         pFr->nUpdateFrameId = nFrameId;
  1505. }
  1506.  
  1507. void CLightEntity::InitShadowFrustum_OMNI(ShadowMapFrustum* pFr, int dwAllowedTypes, const SRenderingPassInfo& passInfo)
  1508. {
  1509.         InitShadowFrustum_PROJECTOR(pFr, dwAllowedTypes, passInfo);
  1510.         CheckValidFrustums_OMNI(pFr, passInfo);
  1511. }
  1512.  
  1513. bool IsABBBVisibleInFrontOfPlane_FAST(const AABB& objBox, const SPlaneObject& clipPlane);
  1514.  
  1515. bool IsAABBInsideHull(const SPlaneObject* pHullPlanes, int nPlanesNum, const AABB& aabbBox)
  1516. {
  1517.         for (int i = 0; i < nPlanesNum; i++)
  1518.         {
  1519.                 if (!IsABBBVisibleInFrontOfPlane_FAST(aabbBox, pHullPlanes[i]))
  1520.                         return false;
  1521.         }
  1522.  
  1523.         return true;
  1524. }
  1525.  
  1526. bool IsSphereInsideHull(const SPlaneObject* pHullPlanes, int nPlanesNum, const Sphere& objSphere)
  1527. {
  1528.         for (int i = 0; i < nPlanesNum; i++)
  1529.         {
  1530.                 if (-pHullPlanes[i].plane.DistFromPlane(objSphere.center) > objSphere.radius)
  1531.                         return false;
  1532.         }
  1533.         return true;
  1534. }
  1535.  
  1536. int CLightEntity::MakeShadowCastersHull(PodArray<SPlaneObject>& lstCastersHull, const SRenderingPassInfo& passInfo)
  1537. {
  1538.         // Construct hull from camera vertices and light source position
  1539.         FUNCTION_PROFILER_3DENGINE;
  1540.  
  1541.         Vec3 vCamPos = passInfo.GetCamera().GetPosition();
  1542.  
  1543.         Vec3 arrFrustVerts[10];
  1544.         passInfo.GetCamera().GetFrustumVertices(arrFrustVerts);
  1545.  
  1546.         // 0 to 5 are the camera frustum vertices
  1547.         for (int v = 0; v < 4; v++)
  1548.                 arrFrustVerts[v] = vCamPos + (arrFrustVerts[v] - vCamPos).normalized() * GetObjManager()->m_fGSMMaxDistance * 1.3f; //0.2f;
  1549.         arrFrustVerts[4] = passInfo.GetCamera().GetPosition();
  1550.  
  1551. #ifdef FEATURE_SVO_GI
  1552.         if (GetCVars()->e_svoTI_Apply && GetCVars()->e_svoTI_InjectionMultiplier)
  1553.         {
  1554.                 arrFrustVerts[4] -= passInfo.GetCamera().GetViewdir() * min(GetCVars()->e_svoTI_RsmConeMaxLength, GetCVars()->e_svoTI_ConeMaxLength);
  1555.         }
  1556. #endif
  1557.  
  1558.         // 5 to 9 are the translated frustum vertices
  1559.         Vec3 vSunDir = (m_light.m_Origin - vCamPos).normalized() * Get3DEngine()->m_fSunClipPlaneRange;
  1560.         for (int v = 0; v < 5; v++)
  1561.                 arrFrustVerts[v + 5] = arrFrustVerts[v] + vSunDir;
  1562.  
  1563.         // The method outputs 9 or 10 planes
  1564.         lstCastersHull.reserve(10);
  1565.  
  1566.         // Indices to create the planes of the camera frustum, can be offset by 5 to create planes for the translated frustum
  1567.         uint vertexIndex[5][3] = {
  1568.                 { 4, 1, 0 }, { 4, 0, 3 }, { 4, 3, 2 }, { 4, 2, 1 }, { 0, 1, 2 }
  1569.         };
  1570.  
  1571.         Plane planeArray[5];
  1572.         planeArray[0] = Plane::CreatePlane(arrFrustVerts[vertexIndex[0][0]], arrFrustVerts[vertexIndex[0][1]], arrFrustVerts[vertexIndex[0][2]]);
  1573.         planeArray[1] = Plane::CreatePlane(arrFrustVerts[vertexIndex[1][0]], arrFrustVerts[vertexIndex[1][1]], arrFrustVerts[vertexIndex[1][2]]);
  1574.         planeArray[2] = Plane::CreatePlane(arrFrustVerts[vertexIndex[2][0]], arrFrustVerts[vertexIndex[2][1]], arrFrustVerts[vertexIndex[2][2]]);
  1575.         planeArray[3] = Plane::CreatePlane(arrFrustVerts[vertexIndex[3][0]], arrFrustVerts[vertexIndex[3][1]], arrFrustVerts[vertexIndex[3][2]]);
  1576.         planeArray[4] = Plane::CreatePlane(arrFrustVerts[vertexIndex[4][0]], arrFrustVerts[vertexIndex[4][1]], arrFrustVerts[vertexIndex[4][2]]);
  1577.  
  1578.         // Test each plane against the sun vector to know if all the translated vertices are on the correct side of the plane.
  1579.         bool bUsePlane[5];
  1580.         for (uint i = 0; i < 5; ++i)
  1581.         {
  1582.                 bUsePlane[i] = planeArray[i].n.Dot(vSunDir) > 0;
  1583.         }
  1584.  
  1585.         // Select the far plane
  1586.         if (bUsePlane[4])
  1587.         {
  1588.                 SPlaneObject po;
  1589.                 po.plane = planeArray[4];
  1590.                 po.Update();
  1591.                 lstCastersHull.Add(po);
  1592.         }
  1593.         else
  1594.         {
  1595.                 SPlaneObject po;
  1596.                 po.plane = Plane::CreatePlane(arrFrustVerts[vertexIndex[4][0] + 5], arrFrustVerts[vertexIndex[4][1] + 5], arrFrustVerts[vertexIndex[4][2] + 5]);
  1597.                 po.Update();
  1598.                 lstCastersHull.Add(po);
  1599.         }
  1600.  
  1601.         // Select side planes
  1602.         for (uint i = 0; i < 4; ++i)
  1603.         {
  1604.                 uint iPlaneOffset = bUsePlane[i] ? 0 : 5;
  1605.                 uint iOtherOffset = bUsePlane[i] ? 5 : 0;
  1606.                 uint iNextPlane = i < 3 ? i + 1 : 0;
  1607.  
  1608.                 // Either add this plane or the equivalent plane in the translated frustum
  1609.                 if (bUsePlane[i])
  1610.                 {
  1611.                         SPlaneObject po;
  1612.                         po.plane = planeArray[i];
  1613.                         po.Update();
  1614.                         lstCastersHull.Add(po);
  1615.                 }
  1616.                 else
  1617.                 {
  1618.                         SPlaneObject po;
  1619.                         po.plane = Plane::CreatePlane(arrFrustVerts[vertexIndex[i][0] + 5], arrFrustVerts[vertexIndex[i][1] + 5], arrFrustVerts[vertexIndex[i][2] + 5]);
  1620.                         po.Update();
  1621.                         lstCastersHull.Add(po);
  1622.                 }
  1623.  
  1624.                 // If this plane belong to a different frustum than the far plane, add a junction plane
  1625.                 if (bUsePlane[4] != bUsePlane[i])
  1626.                 {
  1627.                         SPlaneObject po;
  1628.                         po.plane = Plane::CreatePlane(arrFrustVerts[vertexIndex[i][1] + iPlaneOffset], arrFrustVerts[vertexIndex[i][1] + iOtherOffset], arrFrustVerts[vertexIndex[i][2] + iPlaneOffset]);
  1629.                         po.Update();
  1630.                         lstCastersHull.Add(po);
  1631.                 }
  1632.  
  1633.                 // If this plane belong to a different frustum than the next plane, add a junction plane
  1634.                 if (bUsePlane[iNextPlane] != bUsePlane[i])
  1635.                 {
  1636.                         SPlaneObject po;
  1637.                         po.plane = Plane::CreatePlane(arrFrustVerts[vertexIndex[i][0] + iPlaneOffset], arrFrustVerts[vertexIndex[i][2] + iPlaneOffset], arrFrustVerts[vertexIndex[i][2] + iOtherOffset]);
  1638.                         po.Update();
  1639.                         lstCastersHull.Add(po);
  1640.                 }
  1641.         }
  1642.  
  1643.         return lstCastersHull.Count();
  1644. }
  1645.  
  1646. void CLightEntity::FillFrustumCastersList_SUN(ShadowMapFrustum* pFr, int dwAllowedTypes, int nRenderNodeFlags, PodArray<SPlaneObject>& lstCastersHull, int nLod, const SRenderingPassInfo& passInfo)
  1647. {
  1648.         FUNCTION_PROFILER_3DENGINE;
  1649.  
  1650.         pFr->bOmniDirectionalShadow = false;
  1651.  
  1652.         if (pFr->bBlendFrustum)
  1653.         {
  1654.                 float fBlendVal = GetCVars()->e_ShadowsBlendCascadesVal;
  1655.  
  1656.                 float fRange = Get3DEngine()->m_fGsmRange;
  1657.                 float fRangeStep = Get3DEngine()->m_fGsmRangeStep;
  1658.                 float fRadius = fRange * powf(fRangeStep, nLod);
  1659.  
  1660.                 float fBlendRadius = fRadius - (fBlendVal * (nLod + 1));
  1661.  
  1662.                 pFr->fBlendVal = fBlendRadius / fRadius;
  1663.                 pFr->bBlendFrustum = true;
  1664.         }
  1665.  
  1666.         Vec3 vMapCenter = Vec3(CTerrain::GetTerrainSize() * 0.5f, CTerrain::GetTerrainSize() * 0.5f, CTerrain::GetTerrainSize() * 0.25f);
  1667.  
  1668.         // prevent crash in qhull
  1669.         if (!dwAllowedTypes || !((passInfo.GetCamera().GetPosition() - vMapCenter).GetLength() < CTerrain::GetTerrainSize() * 4))
  1670.                 return;
  1671.  
  1672.         // setup camera
  1673.  
  1674.         CCamera& FrustCam = pFr->FrustumPlanes[0] = CCamera();
  1675.         Vec3 vLightDir = -pFr->vLightSrcRelPos.normalized();
  1676.  
  1677.         Matrix34A mat = Matrix33::CreateRotationVDir(vLightDir);
  1678.         mat.SetTranslation(pFr->vLightSrcRelPos + pFr->vProjTranslation);
  1679.  
  1680.         FrustCam.SetMatrixNoUpdate(mat);
  1681.         FrustCam.SetFrustum(256, 256, pFr->fFOV * (gf_PI / 180.0f), pFr->fNearDist, pFr->fFarDist);
  1682.  
  1683.         if (!lstCastersHull.Count()) // make hull first time it is needed
  1684.                 MakeShadowCastersHull(lstCastersHull, passInfo);
  1685.  
  1686.         //  fill casters list
  1687.         if (pFr->isUpdateRequested(0))
  1688.         {
  1689.                 pFr->ResetCasterLists();
  1690.                 if (pFr->m_eFrustumType != ShadowMapFrustum::e_GsmDynamicDistance || GetCVars()->e_DynamicDistanceShadows > 0)
  1691.                 {
  1692.                         PodArray<SPlaneObject>* pShadowHull = (pFr->nShadowMapLod && !passInfo.IsRenderingCubemap()) ? &lstCastersHull : NULL;
  1693.                         m_pObjManager->MakeShadowCastersList((CVisArea*)GetEntityVisArea(), GetBBox(),
  1694.                                                              dwAllowedTypes, nRenderNodeFlags, pFr->vLightSrcRelPos + pFr->vLightSrcRelPos, &m_light, pFr, pShadowHull, passInfo);
  1695.                 }
  1696.         }
  1697. }
  1698.  
  1699. void CLightEntity::FillFrustumCastersList_PROJECTOR(ShadowMapFrustum* pFr, int dwAllowedTypes, const SRenderingPassInfo& passInfo)
  1700. {
  1701.         FUNCTION_PROFILER_3DENGINE;
  1702.  
  1703.         //  fill casters list
  1704.         pFr->ResetCasterLists();
  1705.         pFr->bOmniDirectionalShadow = false;
  1706.  
  1707.         if (dwAllowedTypes)
  1708.         {
  1709.                 // setup camera
  1710.                 CCamera& FrustCam = pFr->FrustumPlanes[0] = CCamera();
  1711.                 Vec3 vLightDir = -pFr->vLightSrcRelPos.normalized();
  1712.                 Matrix34 mat = Matrix33::CreateRotationVDir(vLightDir);
  1713.                 mat.SetTranslation(GetBBox().GetCenter());
  1714.  
  1715.                 FrustCam.SetMatrix(mat);
  1716.                 FrustCam.SetFrustum(pFr->nTexSize, pFr->nTexSize, pFr->fFOV * (gf_PI / 180.0f), pFr->fNearDist, pFr->fFarDist);
  1717.  
  1718.                 m_pObjManager->MakeShadowCastersList((CVisArea*)GetEntityVisArea(), GetBBox(),
  1719.                                                             dwAllowedTypes, 0xFFFFFFFF, pFr->vLightSrcRelPos + GetBBox().GetCenter(), &m_light, pFr, NULL, passInfo);
  1720.  
  1721.                 DetectCastersListChanges(pFr, passInfo);
  1722.  
  1723.                 pFr->aabbCasters.Reset(); // fix: should i .Reset() pFr->aabbCasters ?
  1724.         }
  1725. }
  1726.  
  1727. void CLightEntity::FillFrustumCastersList_OMNI(ShadowMapFrustum* pFr, int dwAllowedTypes, const SRenderingPassInfo& passInfo)
  1728. {
  1729.         FUNCTION_PROFILER_3DENGINE;
  1730.  
  1731.         //  fill casters list
  1732.         pFr->ResetCasterLists();
  1733.  
  1734.         if (dwAllowedTypes)
  1735.         {
  1736.                 // setup camera
  1737.                 CCamera& FrustCam = pFr->FrustumPlanes[0] = CCamera();
  1738.                 Vec3 vLightDir = -pFr->vLightSrcRelPos.normalized();
  1739.                 Matrix34 mat = Matrix33::CreateRotationVDir(vLightDir);
  1740.                 mat.SetTranslation(GetBBox().GetCenter());
  1741.  
  1742.                 FrustCam.SetMatrix(mat);
  1743.                 FrustCam.SetFrustum(256, 256, pFr->fFOV * (gf_PI / 180.0f) * 0.9f, pFr->fNearDist, pFr->fFarDist);
  1744.  
  1745.                 m_pObjManager->MakeShadowCastersList((CVisArea*)GetEntityVisArea(), GetBBox(),
  1746.                                                      dwAllowedTypes, 0xFFFFFFFF, pFr->vLightSrcRelPos + GetBBox().GetCenter(), &m_light, pFr, NULL, passInfo);
  1747.  
  1748.                 DetectCastersListChanges(pFr, passInfo);
  1749.  
  1750.                 pFr->aabbCasters.Reset(); // fix: should i .Reset() pFr->aabbCasters ?
  1751.  
  1752.                 // Update all omni frustums
  1753.                 pFr->UpdateOmniFrustums();
  1754.         }
  1755. }
  1756.  
  1757. void CLightEntity::DetectCastersListChanges(ShadowMapFrustum* pFr, const SRenderingPassInfo& passInfo)
  1758. {
  1759.         uint32 uCastersListCheckSum = 0;
  1760.         for (int i = 0; i < pFr->castersList.Count(); i++)
  1761.         {
  1762.                 IShadowCaster* pNode = pFr->castersList.GetAt(i);
  1763.                 const AABB entBox = pNode->GetBBoxVirtual();
  1764.                 uCastersListCheckSum += uint32((entBox.min.x + entBox.min.y + entBox.min.z) * 10000.f);
  1765.                 uCastersListCheckSum += uint32((entBox.max.x + entBox.max.y + entBox.max.z) * 10000.f);
  1766.  
  1767.                 ICharacterInstance* pChar = pNode->GetEntityCharacter(0);
  1768.  
  1769.                 if (pChar)
  1770.                 {
  1771.                         ISkeletonAnim* pISkeletonAnim = pChar->GetISkeletonAnim();
  1772.                         if (pISkeletonAnim)
  1773.                         {
  1774.                                 uint32 numAnimsLayer0 = pISkeletonAnim->GetNumAnimsInFIFO(0);
  1775.                                 if (numAnimsLayer0 != 0)
  1776.                                 {
  1777.                                         pFr->RequestUpdate();
  1778.                                 }
  1779.                         }
  1780.                 }
  1781.         }
  1782.  
  1783.         if (pFr->fRadius < DISTANCE_TO_THE_SUN)
  1784.         {
  1785.                 uCastersListCheckSum += uint32((m_WSBBox.min.x + m_WSBBox.min.y + m_WSBBox.min.z) * 10000.f);
  1786.                 uCastersListCheckSum += uint32((m_WSBBox.max.x + m_WSBBox.max.y + m_WSBBox.max.z) * 10000.f);
  1787.         }
  1788.  
  1789.         if (pFr->uCastersListCheckSum != uCastersListCheckSum)
  1790.         {
  1791.                 pFr->RequestUpdate();
  1792.                 pFr->uCastersListCheckSum = uCastersListCheckSum;
  1793.  
  1794.                 if (GetCVars()->e_ShadowsDebug == 3)
  1795.                 {
  1796.                         const char* szName = ((CLightEntity*)(pFr->pLightOwner))->m_light.m_sName;
  1797.                         PrintMessage("Requesting %s shadow update for %s, frame id = %d",
  1798.                                      pFr->bOmniDirectionalShadow ? "Cube" : "2D", szName, passInfo.GetFrameID());
  1799.                 }
  1800.         }
  1801. }
  1802.  
  1803. ShadowMapFrustum* CLightEntity::GetShadowFrustum(int nId)
  1804. {
  1805.         if (m_pShadowMapInfo && nId < MAX_GSM_LODS_NUM)
  1806.                 return m_pShadowMapInfo->pGSM[nId];
  1807.  
  1808.         return NULL;
  1809. };
  1810.  
  1811. void CLightEntity::OnCasterDeleted(IShadowCaster* pCaster)
  1812. {
  1813.         if (!m_pShadowMapInfo)
  1814.                 return;
  1815.  
  1816.         for (int nGsmId = 0; nGsmId < MAX_GSM_LODS_NUM; nGsmId++)
  1817.         {
  1818.                 if (ShadowMapFrustum* pFr = m_pShadowMapInfo->pGSM[nGsmId])
  1819.                 {
  1820.                         pFr->castersList.Delete(pCaster);
  1821.  
  1822.                         if (pFr->pShadowCacheData)
  1823.                         {
  1824.                                 pFr->pShadowCacheData->mProcessedCasters.erase(pCaster);
  1825.                         }
  1826.                 }
  1827.         }
  1828. }
  1829.  
  1830. void CLightEntity::GetMemoryUsage(ICrySizer* pSizer) const
  1831. {
  1832.         SIZER_COMPONENT_NAME(pSizer, "LightEntity");
  1833.         pSizer->AddObject(this, sizeof(*this));
  1834.         pSizer->AddObject(m_pShadowMapInfo);
  1835. }
  1836.  
  1837. void CLightEntity::UpdateCastShadowFlag(float fDistance, const SRenderingPassInfo& passInfo)
  1838. {
  1839.         if (!(m_light.m_Flags & DLF_SUN))
  1840.         {
  1841.                 if (fDistance > m_fWSMaxViewDist * GetFloatCVar(e_ShadowsCastViewDistRatioLights) || !passInfo.RenderShadows())
  1842.                         m_light.m_Flags &= ~DLF_CASTSHADOW_MAPS;
  1843.                 else if (m_bShadowCaster)
  1844.                         m_light.m_Flags |= DLF_CASTSHADOW_MAPS;
  1845.         }
  1846.  
  1847. #if defined(FEATURE_SVO_GI)
  1848.         if (GetGIMode() == eGM_DynamicVoxelization)
  1849.                 m_light.m_Flags |= DLF_USE_FOR_SVOGI;
  1850.         else
  1851.                 m_light.m_Flags &= ~DLF_USE_FOR_SVOGI;
  1852. #endif
  1853. }
  1854.  
  1855. void CLightEntity::Render(const SRendParams& rParams, const SRenderingPassInfo& passInfo)
  1856. {
  1857. #if defined(FEATURE_SVO_GI)
  1858.         if (GetCVars()->e_svoTI_SkipNonGILights && GetCVars()->e_svoTI_Apply && !GetGIMode())
  1859.                 return;
  1860.         if (GetCVars()->e_svoTI_Apply && (IRenderNode::GetGIMode() == eGM_HideIfGiIsActive))
  1861.                 return;
  1862. #endif
  1863.  
  1864.         if (m_layerId != uint16(~0) && m_dwRndFlags & ERF_HIDDEN)
  1865.                 return;
  1866.  
  1867.         if (!(m_light.m_Flags & DLF_DEFERRED_LIGHT) || passInfo.IsRecursivePass())
  1868.                 return;
  1869.  
  1870.         if (m_light.m_fRadius < 0.01f)
  1871.                 return;
  1872.  
  1873.         UpdateCastShadowFlag(rParams.fDistance, passInfo);
  1874.  
  1875.         FUNCTION_PROFILER_3DENGINE;
  1876.  
  1877.         int nRenderNodeMinSpec = (m_dwRndFlags & ERF_SPEC_BITS_MASK) >> ERF_SPEC_BITS_SHIFT;
  1878.         if (!CheckMinSpec(nRenderNodeMinSpec))
  1879.                 return;
  1880.  
  1881.         Sphere sp(m_light.m_BaseOrigin, m_light.m_fBaseRadius);
  1882.  
  1883.         bool bIsVisible = false;
  1884.         if (m_light.m_Flags & DLF_DEFERRED_CUBEMAPS)
  1885.         {
  1886.                 OBB obb(OBB::CreateOBBfromAABB(Matrix33(m_light.m_ObjMatrix), AABB(-m_light.m_ProbeExtents, m_light.m_ProbeExtents)));
  1887.                 bIsVisible = passInfo.GetCamera().IsOBBVisible_F(m_light.m_Origin, obb);
  1888.         }
  1889.         else if (m_light.m_Flags & DLF_AREA_LIGHT)
  1890.         {
  1891.                 // OBB test for area lights.
  1892.                 Vec3 vBoxMax(m_light.m_fBaseRadius, m_light.m_fBaseRadius + m_light.m_fAreaWidth, m_light.m_fBaseRadius + m_light.m_fAreaHeight);
  1893.                 Vec3 vBoxMin(-0.1f, -(m_light.m_fBaseRadius + m_light.m_fAreaWidth), -(m_light.m_fBaseRadius + m_light.m_fAreaHeight));
  1894.  
  1895.                 OBB obb(OBB::CreateOBBfromAABB(Matrix33(m_light.m_ObjMatrix), AABB(vBoxMin, vBoxMax)));
  1896.                 bIsVisible = passInfo.GetCamera().IsOBBVisible_F(m_light.m_BaseOrigin, obb);
  1897.         }
  1898.         else
  1899.                 bIsVisible = passInfo.GetCamera().IsSphereVisible_F(sp);
  1900.  
  1901.         if (!bIsVisible && !(m_light.m_Flags & DLF_ATTACH_TO_SUN))
  1902.                 return;
  1903.  
  1904.         //assert(m_light.IsOk());
  1905.  
  1906.         if ((m_light.m_Flags & DLF_DISABLED) || (!GetCVars()->e_DynamicLights))
  1907.                 return;
  1908.  
  1909.         if ((m_light.m_Flags & DLF_PROJECT) && (m_light.m_fLightFrustumAngle < 90.f) && (m_light.m_pLightImage || m_light.m_pLightDynTexSource))
  1910. #if defined(FEATURE_SVO_GI)
  1911.                 if (!GetCVars()->e_svoTI_Apply || GetGIMode() != eGM_DynamicVoxelization)
  1912. #endif
  1913.         {
  1914.                 CCamera lightCam = passInfo.GetCamera();
  1915.                 lightCam.SetPositionNoUpdate(m_light.m_Origin);
  1916.                 Matrix34 entMat = ((ILightSource*)(m_light.m_pOwner))->GetMatrix();
  1917.                 entMat.OrthonormalizeFast();
  1918.                 Matrix33 matRot = Matrix33::CreateRotationVDir(entMat.GetColumn(0));
  1919.                 lightCam.SetMatrixNoUpdate(Matrix34(matRot, m_light.m_Origin));
  1920.                 lightCam.SetFrustum(1, 1, (m_light.m_fLightFrustumAngle * 2) / 180.0f * gf_PI, 0.1f, m_light.m_fRadius);
  1921.                 if (!FrustumIntersection(passInfo.GetCamera(), lightCam))
  1922.                         return;
  1923.         }
  1924.  
  1925.         const int nEngineFrameID = passInfo.GetFrameID();
  1926.  
  1927.         int nMaxReqursion = (m_light.m_Flags & DLF_THIS_AREA_ONLY) ? 2 : 3;
  1928.         if (!m_pObjManager || !m_pVisAreaManager || !m_pVisAreaManager->IsEntityVisAreaVisible(this, nMaxReqursion, &m_light, passInfo))
  1929.         {
  1930.                 if (m_light.m_Flags & DLF_SUN && m_pVisAreaManager && m_pVisAreaManager->m_bSunIsNeeded)
  1931.                 {
  1932.                         // sun may be used in indoor even if outdoor is not visible
  1933.                 }
  1934.                 else if (!GetEntityVisArea() && GetEntityTerrainNode() && !(m_light.m_Flags & DLF_THIS_AREA_ONLY) && m_pVisAreaManager && m_pVisAreaManager->m_bSunIsNeeded)
  1935.                 {
  1936.                         // not "this area only" outdoor light affects everything
  1937.                 }
  1938.                 else if ((m_light.m_Flags & (DLF_IGNORES_VISAREAS | DLF_THIS_AREA_ONLY)) == DLF_IGNORES_VISAREAS)
  1939.                 {
  1940.                 }
  1941.                 else
  1942.                         return;
  1943.         }
  1944.  
  1945.         if (CVisArea* pArea = (CVisArea*)GetEntityVisArea())
  1946.         {
  1947.                 // vis area lsource
  1948.                 IVisArea* pCameraVisArea = Get3DEngine()->GetVisAreaFromPos(passInfo.GetCamera().GetPosition());
  1949.  
  1950.                 // check if light is visible thru light area portal cameras
  1951.                 if (pArea->m_nRndFrameId == nEngineFrameID && pArea != (CVisArea*)pCameraVisArea)
  1952.                 {
  1953.                         int nCam = 0;
  1954.                         for (; nCam < pArea->m_lstCurCamerasLen; nCam++)
  1955.                                 if (CVisArea::s_tmpCameras[pArea->m_lstCurCamerasIdx + nCam].IsSphereVisible_F(sp))
  1956.                                         break;
  1957.  
  1958.                         if (nCam == pArea->m_lstCurCamerasLen)
  1959.                                 return; // invisible
  1960.                 }
  1961.  
  1962.                 // check if lsource is in visible area
  1963.                 if (!IsLightAreasVisible() && pCameraVisArea != pArea)
  1964.                 {
  1965.                         if (m_light.m_Flags & DLF_THIS_AREA_ONLY)
  1966.                         {
  1967.                                 if (pArea)
  1968.                                 {
  1969.                                         int nRndFrameId = pArea->GetVisFrameId();
  1970.                                         if (nEngineFrameID - nRndFrameId > MAX_FRAME_ID_STEP_PER_FRAME)
  1971.                                                 return; // area invisible
  1972.                                 }
  1973.                                 else
  1974.                                         return; // area invisible
  1975.                         }
  1976.                 }
  1977.         }
  1978.         else
  1979.         {
  1980.                 // outdoor lsource
  1981.                 if (!(m_light.m_Flags & DLF_DIRECTIONAL) && !IsLightAreasVisible())
  1982.                         return; // outdoor invisible
  1983.         }
  1984.  
  1985.         m_light.m_nStencilRef[0] = CClipVolumeManager::AffectsEverythingStencilRef;
  1986.         m_light.m_nStencilRef[1] = CClipVolumeManager::InactiveVolumeStencilRef;
  1987.  
  1988.         if (m_light.m_Flags & DLF_THIS_AREA_ONLY)
  1989.         {
  1990.                 // User assigned clip volumes. Note: ClipVolume 0 has already been assigned in AsyncOctreeUpdate
  1991.                 if ((m_light.m_Flags & DLF_HAS_CLIP_VOLUME) != 0 && m_light.m_pClipVolumes[1] != NULL)
  1992.                         m_light.m_nStencilRef[1] = m_light.m_pClipVolumes[1]->GetStencilRef();
  1993.  
  1994.                 m_light.m_nStencilRef[0] = (m_pTempData && m_pTempData->userData.m_pClipVolume) ? m_pTempData->userData.m_pClipVolume->GetStencilRef() : 0;
  1995.         }
  1996.  
  1997.         // associated clip volume invisible
  1998.         if (m_light.m_nStencilRef[0] == CClipVolumeManager::InactiveVolumeStencilRef && m_light.m_nStencilRef[1] == CClipVolumeManager::InactiveVolumeStencilRef)
  1999.                 return;
  2000.  
  2001.         IMaterial* pMat = GetMaterial();
  2002.         if (pMat)
  2003.         {
  2004.                 SAFE_RELEASE(m_light.m_Shader.m_pShader);
  2005.                 m_light.m_Shader = pMat->GetShaderItem();
  2006.                 if (m_light.m_Shader.m_pShader)
  2007.                         m_light.m_Shader.m_pShader->AddRef();
  2008.         }
  2009.  
  2010.         GetRenderer()->EF_UpdateDLight(&m_light);
  2011.  
  2012.         bool bAdded = false;
  2013.  
  2014.         //3dengine side - lightID assigning
  2015.         m_light.m_Id = int16(Get3DEngine()->GetDynamicLightSources()->Count() + passInfo.GetIRenderView()->GetLightsCount(eDLT_DeferredLight));
  2016.  
  2017.         if (!bAdded)
  2018.         {
  2019.                 if (passInfo.RenderShadows() && (m_light.m_Flags & DLF_CASTSHADOW_MAPS) && m_light.m_Id >= 0)
  2020.                 {
  2021.                         UpdateGSMLightSourceShadowFrustum(passInfo);
  2022.  
  2023.                         if (m_pShadowMapInfo)
  2024.                         {
  2025.                                 m_light.m_pShadowMapFrustums = reinterpret_cast<ShadowMapFrustum**>(m_pShadowMapInfo->pGSM);
  2026.                                 for (int nLod = 0; nLod < MAX_GSM_LODS_NUM && m_light.m_pShadowMapFrustums[nLod]; nLod++)
  2027.                                         m_light.m_pShadowMapFrustums[nLod]->nDLightId = m_light.m_Id;
  2028.                         }
  2029.                 }
  2030.  
  2031.                 if (GetCVars()->e_DynamicLights && m_fWSMaxViewDist)
  2032.                 {
  2033.                         if (GetCVars()->e_DynamicLights == 2)
  2034.                         {
  2035.                                 CDLight* pL = &m_light;
  2036.                                 float fSize = 0.05f * (sinf(GetCurTimeSec() * 10.f) + 2.0f);
  2037.                                 DrawSphere(pL->m_Origin, fSize, pL->m_Color);
  2038.                                 IRenderAuxText::DrawLabelF(pL->m_Origin, 1.3f, "id=%d, rad=%.1f, vdr=%d", pL->m_Id, pL->m_fRadius, (int)m_ucViewDistRatio);
  2039.                         }
  2040.  
  2041.                         const float mult = SATURATE(6.f * (1.f - (rParams.fDistance / m_fWSMaxViewDist)));
  2042.                         IF (m_light.m_Color.Luminance() * mult > 0, 1)
  2043.                         {
  2044.                                 if (passInfo.IsGeneralPass())
  2045.                                         Get3DEngine()->SetupLightScissors(&m_light, passInfo);
  2046.  
  2047.                                 Get3DEngine()->AddLightToRenderer(m_light, mult, passInfo);
  2048.                         }
  2049.                 }
  2050.         }
  2051. }
  2052.  
  2053. void CLightEntity::Hide(bool bHide)
  2054. {
  2055.         SetRndFlags(ERF_HIDDEN, bHide);
  2056.  
  2057.         if (bHide)
  2058.         {
  2059.                 m_light.m_Flags |= DLF_DISABLED;
  2060.         }
  2061.         else
  2062.         {
  2063.                 m_light.m_Flags &= ~DLF_DISABLED;
  2064.         }
  2065. }
  2066.  
  2067. void CLightEntity::SetViewDistRatio(int nViewDistRatio)
  2068. {
  2069.         IRenderNode::SetViewDistRatio(nViewDistRatio);
  2070.         m_fWSMaxViewDist = GetMaxViewDist();
  2071. }
  2072.  
  2073. #if defined(FEATURE_SVO_GI)
  2074. IRenderNode::EGIMode CLightEntity::GetGIMode() const
  2075. {
  2076.         if (IRenderNode::GetGIMode() == eGM_StaticVoxelization || IRenderNode::GetGIMode() == eGM_DynamicVoxelization || m_light.m_Flags & DLF_SUN)
  2077.         {
  2078.         if (!(m_light.m_Flags & (DLF_DISABLED | DLF_FAKE | DLF_VOLUMETRIC_FOG_ONLY | DLF_AMBIENT | DLF_DEFERRED_CUBEMAPS)) && !(m_dwRndFlags & ERF_HIDDEN))
  2079.         {
  2080.                 if (m_light.m_BaseColor.Luminance() > .01f && m_light.m_fBaseRadius > 0.5f)
  2081.                 {
  2082.                         if (m_light.m_Flags & DLF_SUN)
  2083.                         {
  2084.                                 if (GetCVars()->e_Sun)
  2085.                                                 return eGM_StaticVoxelization;
  2086.                                 else
  2087.                                                 return eGM_None;
  2088.                         }
  2089.  
  2090.                         return IRenderNode::GetGIMode();
  2091.                 }
  2092.         }
  2093. }
  2094.  
  2095.         return eGM_None;
  2096. }
  2097. #endif
  2098.  
  2099. void CLightEntity::SetOwnerEntity(IEntity* pEnt)
  2100. {
  2101.         IRenderNode::SetOwnerEntity(pEnt);
  2102.  
  2103.         SetRndFlags(ERF_GI_MODE_BIT0, (pEnt->GetFlagsExtended() & ENTITY_FLAG_EXTENDED_GI_MODE_BIT0) != 0);
  2104.         SetRndFlags(ERF_GI_MODE_BIT1, (pEnt->GetFlagsExtended() & ENTITY_FLAG_EXTENDED_GI_MODE_BIT1) != 0);
  2105.         SetRndFlags(ERF_GI_MODE_BIT2, (pEnt->GetFlagsExtended() & ENTITY_FLAG_EXTENDED_GI_MODE_BIT2) != 0);
  2106. }
  2107.  
  2108. void CLightEntity::OffsetPosition(const Vec3& delta)
  2109. {
  2110.         if (m_pTempData) m_pTempData->OffsetPosition(delta);
  2111.         m_light.m_Origin += delta;
  2112.         m_light.m_BaseOrigin += delta;
  2113.         m_Matrix.SetTranslation(m_Matrix.GetTranslation() + delta);
  2114.         m_WSBBox.Move(delta);
  2115. }
  2116.  
  2117. void CLightEntity::ProcessPerObjectFrustum(ShadowMapFrustum* pFr, struct SPerObjectShadow* pPerObjectShadow, ILightSource* pLightSource, const SRenderingPassInfo& passInfo)
  2118. {
  2119.         assert(pFr);
  2120.         CDLight& light = pLightSource->GetLightProperties();
  2121.  
  2122.         pFr->m_eFrustumType = ShadowMapFrustum::e_PerObject;
  2123.         pFr->RequestUpdate();
  2124.         pFr->ResetCasterLists();
  2125.         pFr->castersList.Add(pPerObjectShadow->pCaster);
  2126.  
  2127.         // get caster's bounding box and scale
  2128.         AABB objectBBox;
  2129.         pPerObjectShadow->pCaster->FillBBox(objectBBox);
  2130.         Vec3 vExtents = 0.5f * objectBBox.GetSize().CompMul(pPerObjectShadow->vBBoxScale);
  2131.         pFr->aabbCasters = AABB(objectBBox.GetCenter() - vExtents, objectBBox.GetCenter() + vExtents);
  2132.  
  2133.         pFr->m_Flags = light.m_Flags;
  2134.         pFr->bUseAdditiveBlending = true;
  2135.         uint nTexSize = pPerObjectShadow->nTexSize * GetCVars()->e_ShadowsPerObjectResolutionScale;
  2136.         nTexSize = clamp_tpl<uint>(nTexSize, 64, GetRenderer()->GetMaxTextureSize());
  2137.         pFr->nTexSize = 1 << IntegerLog2(nTexSize);
  2138.         pFr->nTextureWidth = pFr->nTexSize;
  2139.         pFr->nTextureHeight = pFr->nTexSize;
  2140.         pFr->bBlendFrustum = false;
  2141.  
  2142.         // now update frustum params based on object box
  2143.         AABB objectsBox = pFr->aabbCasters;
  2144.         const Vec3 lightPos = light.m_Origin - passInfo.GetCamera().GetPosition() + objectsBox.GetCenter();
  2145.         const Vec3 lookAt = objectsBox.GetCenter();
  2146.  
  2147.         pFr->vProjTranslation = objectsBox.GetCenter();
  2148.         pFr->vLightSrcRelPos = light.m_Origin - passInfo.GetCamera().GetPosition();
  2149.         pFr->fFOV = (float)RAD2DEG(atan_tpl(objectsBox.GetRadius() / (lookAt - lightPos).GetLength())) * 2.0f;
  2150.         pFr->fProjRatio = 1.0f;
  2151.         pFr->fNearDist = pFr->vLightSrcRelPos.GetLength() - objectsBox.GetRadius();
  2152.         pFr->fFarDist = pFr->vLightSrcRelPos.GetLength() + objectsBox.GetRadius();
  2153.  
  2154.         pFr->fDepthConstBias = pPerObjectShadow->fConstBias;
  2155.         pFr->fDepthSlopeBias = pPerObjectShadow->fSlopeBias;
  2156.         pFr->fWidthS = pPerObjectShadow->fJitter;
  2157.         pFr->fWidthT = pPerObjectShadow->fJitter;
  2158.         pFr->fBlurS = 0.0f;
  2159.         pFr->fBlurT = 0.0f;
  2160.  
  2161.         if (GetCVars()->e_ShadowsFrustums)
  2162.         {
  2163.                 pFr->DrawFrustum(GetRenderer(), (GetCVars()->e_ShadowsFrustums == 1) ? 1000 : 1);
  2164.                 Get3DEngine()->DrawBBox(pFr->aabbCasters, Col_Green);
  2165.         }
  2166. }
  2167.  
  2168. void CLightEntity::FillBBox(AABB& aabb)
  2169. {
  2170.         aabb = CLightEntity::GetBBox();
  2171. }
  2172.  
  2173. EERType CLightEntity::GetRenderNodeType()
  2174. {
  2175.         return eERType_Light;
  2176. }
  2177.  
  2178. float CLightEntity::GetMaxViewDist()
  2179. {
  2180.         if (m_light.m_Flags & DLF_SUN)
  2181.                 return 10.f * DISTANCE_TO_THE_SUN;
  2182.  
  2183.         if (GetMinSpecFromRenderNodeFlags(m_dwRndFlags) == CONFIG_DETAIL_SPEC)
  2184.                 return max(GetCVars()->e_ViewDistMin, CLightEntity::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatioDetail * GetViewDistRatioNormilized());
  2185.  
  2186.         return max(GetCVars()->e_ViewDistMin, CLightEntity::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatioLights * GetViewDistRatioNormilized());
  2187. }
  2188.  
  2189. Vec3 CLightEntity::GetPos(bool bWorldOnly) const
  2190. {
  2191.         assert(bWorldOnly);
  2192.         return m_light.m_Origin;
  2193. }
  2194.  
downloadLightEntity.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top