BVB Source Codes

CRYENGINE Show LightVolumeManager.cpp Source code

Return Download CRYENGINE: download LightVolumeManager.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 "LightVolumeManager.h"
  5. #include "ClipVolumeManager.h"
  6.  
  7. void CLightVolumesMgr::Init()
  8. {
  9.         m_bUpdateLightVolumes = false;
  10.         m_pLightVolsInfo.reserve(LV_MAX_COUNT);
  11.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  12.                 m_pLightVolumes[i].reserve(LV_MAX_COUNT);
  13.         memset(m_nWorldCells, 0, sizeof(m_nWorldCells));
  14.         memset(m_pWorldLightCells, 0, sizeof(m_pWorldLightCells));
  15. }
  16.  
  17. void CLightVolumesMgr::Reset()
  18. {
  19.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  20.                 stl::free_container(m_pLightVolumes[i]);
  21.  
  22.         m_bUpdateLightVolumes = false;
  23.         memset(m_nWorldCells, 0, sizeof(m_nWorldCells));
  24.         memset(m_pWorldLightCells, 0, sizeof(m_pWorldLightCells));
  25. }
  26.  
  27. uint16 CLightVolumesMgr::RegisterVolume(const Vec3& vPos, f32 fRadius, uint8 nClipVolumeRef, const SRenderingPassInfo& passInfo)
  28. {
  29.         IF ((m_bUpdateLightVolumes & (m_pLightVolsInfo.size() < LV_MAX_COUNT)) && fRadius < 256.0f, 1)
  30.         {
  31.                 FUNCTION_PROFILER_3DENGINE;
  32.  
  33.                 int32 nPosx = (int32)(floorf(vPos.x * LV_CELL_RSIZEX));
  34.                 int32 nPosy = (int32)(floorf(vPos.y * LV_CELL_RSIZEY));
  35.                 int32 nPosz = (int32)(floorf(vPos.z * LV_CELL_RSIZEZ));
  36.  
  37.                 // Check if world cell has any light volume, else add new one
  38.                 uint16 nHashIndex = GetWorldHashBucketKey(nPosx, nPosy, nPosz);
  39.                 uint16* pCurrentVolumeID = &m_nWorldCells[nHashIndex];
  40.  
  41.                 while (*pCurrentVolumeID != 0)
  42.                 {
  43.                         SLightVolInfo& sVolInfo = m_pLightVolsInfo[*pCurrentVolumeID - 1];
  44.  
  45.                         int32 nVolumePosx = (int32)(floorf(sVolInfo.vVolume.x * LV_CELL_RSIZEX));
  46.                         int32 nVolumePosy = (int32)(floorf(sVolInfo.vVolume.y * LV_CELL_RSIZEY));
  47.                         int32 nVolumePosz = (int32)(floorf(sVolInfo.vVolume.z * LV_CELL_RSIZEZ));
  48.  
  49.                         if (nPosx == nVolumePosx &&
  50.                             nPosy == nVolumePosy &&
  51.                             nPosz == nVolumePosz &&
  52.                             nClipVolumeRef == sVolInfo.nClipVolumeID)
  53.                         {
  54.                                 return (uint16) * pCurrentVolumeID;
  55.                         }
  56.  
  57.                         pCurrentVolumeID = &sVolInfo.nNextVolume;
  58.                 }
  59.  
  60.                 // create new volume
  61.                 size_t nIndex = ~0;
  62.                 SLightVolInfo* pLightVolInfo = ::new(m_pLightVolsInfo.push_back_new(nIndex))SLightVolInfo(vPos, fRadius, nClipVolumeRef);
  63.                 *pCurrentVolumeID = static_cast<uint16>(nIndex + 1);
  64.  
  65.                 return *pCurrentVolumeID;
  66.         }
  67.  
  68.         return 0;
  69. }
  70.  
  71. void CLightVolumesMgr::RegisterLight(const CDLight& pDL, uint32 nLightID, const SRenderingPassInfo& passInfo)
  72. {
  73.         IF ((m_bUpdateLightVolumes & !(pDL.m_Flags & LV_DLF_LIGHTVOLUMES_MASK)), 1)
  74.         {
  75.                 FUNCTION_PROFILER_3DENGINE;
  76.  
  77.                 const f32 fColCheck = (f32) __fsel(pDL.m_Color.r + pDL.m_Color.g + pDL.m_Color.b - 0.333f, 1.0f, 0.0f); //light color > threshold
  78.                 const f32 fRadCheck = (f32) __fsel(pDL.m_fRadius - 0.5f, 1.0f, 0.0f);                                   //light radius > threshold
  79.                 if (fColCheck * fRadCheck)
  80.                 {
  81.                         int32 nMiny = (int32)(floorf((pDL.m_Origin.y - pDL.m_fRadius) * LV_LIGHT_CELL_R_SIZE));
  82.                         int32 nMaxy = (int32)(floorf((pDL.m_Origin.y + pDL.m_fRadius) * LV_LIGHT_CELL_R_SIZE));
  83.                         int32 nMinx = (int32)(floorf((pDL.m_Origin.x - pDL.m_fRadius) * LV_LIGHT_CELL_R_SIZE));
  84.                         int32 nMaxx = (int32)(floorf((pDL.m_Origin.x + pDL.m_fRadius) * LV_LIGHT_CELL_R_SIZE));
  85.  
  86.                         // Register light into all cells touched by light radius
  87.                         for (int32 y = nMiny, ymax = nMaxy; y <= ymax; ++y)
  88.                         {
  89.                                 for (int32 x = nMinx, xmax = nMaxx; x <= xmax; ++x)
  90.                                 {
  91.                                         SLightCell& lightCell = m_pWorldLightCells[GetWorldHashBucketKey(x, y, 1, LV_LIGHTS_WORLD_BUCKET_SIZE)];
  92.                                         CryPrefetch(&lightCell);
  93.                                         lightCell.nLightID[lightCell.nLightCount] = nLightID;
  94.                                         lightCell.nLightCount = (lightCell.nLightCount + 1) & (LV_LIGHTS_MAX_COUNT - 1);
  95.                                 }
  96.                         }
  97.                 }
  98.         }
  99. }
  100.  
  101. void CLightVolumesMgr::AddLight(const SRenderLight& pLight, const SLightVolInfo* __restrict pVolInfo, SLightVolume& pVolume)
  102. {
  103.         // Check for clip volume
  104.         if (pLight.m_nStencilRef[0] == pVolInfo->nClipVolumeID || pLight.m_nStencilRef[1] == pVolInfo->nClipVolumeID ||
  105.             pLight.m_nStencilRef[0] == CClipVolumeManager::AffectsEverythingStencilRef)
  106.         {
  107.                 const Vec3 position = pLight.m_Origin;
  108.                 const float radius = pLight.m_fRadius;
  109.                 const Vec4& vVolume = pVolInfo->vVolume;
  110.                 const f32 fDimCheck = (f32) __fsel(radius - vVolume.w * 0.1f, 1.0f, 0.0f);  //light radius not more than 10x smaller than volume radius
  111.                 const f32 fOverlapCheck = (f32) __fsel(sqr(vVolume.x - position.x) + sqr(vVolume.y - position.y) + sqr(vVolume.z - position.z) - sqr(vVolume.w + radius), 0.0f, 1.0f);// touches volumes
  112.                 if (fDimCheck * fOverlapCheck)
  113.                 {
  114.                         float fAttenuationBulbSize = pLight.m_fAttenuationBulbSize;
  115.                         Vec3 lightColor = pLight.m_Color.toVec3();
  116.  
  117.                         // Adjust light intensity so that the intended brightness is reached 1 meter from the light's surface
  118.                         IF (!(pLight.m_Flags & (DLF_AREA_LIGHT | DLF_AMBIENT)), 1)
  119.                         {
  120.                                 fAttenuationBulbSize = max(fAttenuationBulbSize, 0.001f);
  121.  
  122.                                 // Solve I * 1 / (1 + d/lightsize)^2 = 1
  123.                                 float intensityMul = 1.0f + 1.0f / fAttenuationBulbSize;
  124.                                 intensityMul *= intensityMul;
  125.                                 lightColor *= intensityMul;
  126.                         }
  127.  
  128.                         pVolume.pData.push_back();
  129.                         SLightVolume::SLightData& lightData = pVolume.pData[pVolume.pData.size() - 1];
  130.                         lightData.position = position;
  131.                         lightData.radius = radius;
  132.                         lightData.color = lightColor;
  133.                         lightData.buldRadius = fAttenuationBulbSize;
  134.                         if (pLight.m_Flags & DLF_PROJECT)
  135.                         {
  136.                                 lightData.projectorDirection = pLight.m_ObjMatrix.GetColumn0();
  137.                                 lightData.projectorCosAngle = cos_tpl(DEG2RAD(pLight.m_fLightFrustumAngle));
  138.                         }
  139.                         else
  140.                         {
  141.                                 lightData.projectorDirection = Vec3(ZERO);
  142.                                 lightData.projectorCosAngle = 0.0f;
  143.                         }
  144.                 }
  145.         }
  146. }
  147.  
  148. void CLightVolumesMgr::Update(const SRenderingPassInfo& passInfo)
  149. {
  150.         if (!m_bUpdateLightVolumes || m_pLightVolsInfo.empty() || !passInfo.IsGeneralPass())
  151.                 return;
  152.  
  153.         FUNCTION_PROFILER_3DENGINE;
  154.         m_pLightVolsInfo.CoalesceMemory();
  155.         const uint32 nLightCount = passInfo.GetIRenderView()->GetLightsCount(eDLT_DeferredLight);
  156.  
  157.         uint32 nLightVols = m_pLightVolsInfo.size();
  158.         LightVolumeVector& lightVols = m_pLightVolumes[passInfo.ThreadID()];
  159.         lightVols.resize(nLightVols);
  160.  
  161.         if (!nLightCount)
  162.         {
  163.                 for (uint32 v = 0; v < nLightVols; ++v)
  164.                         lightVols[v].pData.resize(0);
  165.  
  166.                 return;
  167.         }
  168.  
  169.         uint64 _nLightProcessed[128] = { 0 };
  170.         uint8* nLightProcessed = (uint8*)&_nLightProcessed[0];
  171.  
  172.         for (uint32 v = 0; v < nLightVols; ++v)
  173.         {
  174.                 const Vec4* __restrict vBVol = &m_pLightVolsInfo[v].vVolume;
  175.                 int32 nMiny = (int32)(floorf((vBVol->y - vBVol->w) * LV_LIGHT_CELL_R_SIZE));
  176.                 int32 nMaxy = (int32)(floorf((vBVol->y + vBVol->w) * LV_LIGHT_CELL_R_SIZE));
  177.                 int32 nMinx = (int32)(floorf((vBVol->x - vBVol->w) * LV_LIGHT_CELL_R_SIZE));
  178.                 int32 nMaxx = (int32)(floorf((vBVol->x + vBVol->w) * LV_LIGHT_CELL_R_SIZE));
  179.  
  180.                 lightVols[v].pData.resize(0);
  181.  
  182.                 // Loop through active light cells touching bounding volume (~avg 2 cells)
  183.                 for (int32 y = nMiny, ymax = nMaxy; y <= ymax; ++y)
  184.                 {
  185.                         for (int32 x = nMinx, xmax = nMaxx; x <= xmax; ++x)
  186.                         {
  187.                                 const SLightCell& lightCell = m_pWorldLightCells[GetWorldHashBucketKey(x, y, 1, LV_LIGHTS_WORLD_BUCKET_SIZE)];
  188.                                 CryPrefetch(&lightCell);
  189.  
  190.                                 const SRenderLight& pFirstDL = passInfo.GetIRenderView()->GetLight(eDLT_DeferredLight, lightCell.nLightID[0]);
  191.                                 CryPrefetch(&pFirstDL);
  192.                                 CryPrefetch(&pFirstDL.m_ObjMatrix);
  193.                                 for (uint32 l = 0; (l < lightCell.nLightCount) & (lightVols[v].pData.size() < LIGHTVOLUME_MAXLIGHTS); ++l)
  194.                                 {
  195.                                         const int32 nLightId = lightCell.nLightID[l];
  196.                                         const SRenderLight& pDL = passInfo.GetIRenderView()->GetLight(eDLT_DeferredLight, nLightId);
  197.                                         const int32 nNextLightId = lightCell.nLightID[(l + 1) & (LIGHTVOLUME_MAXLIGHTS - 1)];
  198.                                         const SRenderLight& pNextDL = passInfo.GetIRenderView()->GetLight(eDLT_DeferredLight, nNextLightId);
  199.                                         CryPrefetch(&pNextDL);
  200.                                         CryPrefetch(&pNextDL.m_ObjMatrix);
  201.  
  202.                                         IF (nLightProcessed[nLightId] != v + 1, 1)
  203.                                         {
  204.                                                 nLightProcessed[nLightId] = v + 1;
  205.                                                 AddLight(pDL, &m_pLightVolsInfo[v], lightVols[v]);
  206.                                         }
  207.                                 }
  208.                         }
  209.                 }
  210.         }
  211. }
  212.  
  213. void CLightVolumesMgr::Clear(const SRenderingPassInfo& passInfo)
  214. {
  215.         m_bUpdateLightVolumes = false;
  216.         if (GetCVars()->e_LightVolumes && passInfo.IsGeneralPass() && GetCVars()->e_DynamicLights)
  217.         {
  218.                 memset(m_nWorldCells, 0, sizeof(m_nWorldCells));
  219.                 memset(m_pWorldLightCells, 0, sizeof(m_pWorldLightCells));
  220.                 m_pLightVolsInfo.clear();
  221.                 m_bUpdateLightVolumes = (GetCVars()->e_LightVolumes == 1) ? true : false;
  222.         }
  223. }
  224.  
  225. void CLightVolumesMgr::GetLightVolumes(threadID nThreadID, SLightVolume*& pLightVols, uint32& nNumVols)
  226. {
  227.         pLightVols = 0;
  228.         nNumVols = 0;
  229.         if (GetCVars()->e_LightVolumes == 1 && GetCVars()->e_DynamicLights && !m_pLightVolumes[nThreadID].empty())
  230.         {
  231.                 pLightVols = &m_pLightVolumes[nThreadID][0];
  232.                 nNumVols = m_pLightVolumes[nThreadID].size();
  233.         }
  234. }
  235.  
  236. void C3DEngine::GetLightVolumes(threadID nThreadID, SLightVolume*& pLightVols, uint32& nNumVols)
  237. {
  238.         m_LightVolumesMgr.GetLightVolumes(nThreadID, pLightVols, nNumVols);
  239. }
  240.  
  241. void CLightVolumesMgr::DrawDebug(const SRenderingPassInfo& passInfo)
  242. {
  243. #ifndef _RELEASE
  244.         IRenderer* pRenderer = GetRenderer();
  245.         IRenderAuxGeom* pAuxGeom = GetRenderer()->GetIRenderAuxGeom();
  246.         if (!pAuxGeom || !passInfo.IsGeneralPass())
  247.                 return;
  248.  
  249.         ColorF cWhite = ColorF(1, 1, 1, 1);
  250.         ColorF cBad = ColorF(1.0f, 0.0, 0.0f, 1.0f);
  251.         ColorF cWarning = ColorF(1.0f, 1.0, 0.0f, 1.0f);
  252.         ColorF cGood = ColorF(0.0f, 0.5, 1.0f, 1.0f);
  253.         ColorF cSingleCell = ColorF(0.0f, 1.0, 0.0f, 1.0f);
  254.  
  255.         const uint32 nLightVols = m_pLightVolsInfo.size();
  256.         LightVolumeVector& lightVols = m_pLightVolumes[passInfo.ThreadID()];
  257.         const Vec3 vCamPos = passInfo.GetCamera().GetPosition();
  258.  
  259.         float fYLine = 8.0f, fYStep = 20.0f;
  260.         IRenderAuxText::Draw2dLabel(8.0f, fYLine += fYStep, 2.0f, (float*)&cWhite.r, false, "Light Volumes Info (count %d)", nLightVols);
  261.  
  262.         for (uint32 v = 0; v < nLightVols; ++v)  // draw each light volume
  263.         {
  264.                 SLightVolume& lv = lightVols[v];
  265.                 SLightVolInfo& lvInfo = m_pLightVolsInfo[v];
  266.  
  267.                 ColorF& cCol = (lv.pData.size() >= 10) ? cBad : ((lv.pData.size() >= 5) ? cWarning : cGood);
  268.                 const Vec3 vPos = Vec3(lvInfo.vVolume.x, lvInfo.vVolume.y, lvInfo.vVolume.z);
  269.                 const float fCamDistSq = (vPos - vCamPos).len2();
  270.                 cCol.a = max(0.25f, min(1.0f, 1024.0f / (fCamDistSq + 1e-6f)));
  271.  
  272.                 IRenderAuxText::DrawLabelExF(vPos, 1.3f, (float*)&cCol.r, true, true, "Id: %d\nPos: %.2f %.2f %.2f\nRadius: %.2f\nLights: %d\nOutLights: %d",
  273.                                        v, vPos.x, vPos.y, vPos.z, lvInfo.vVolume.w, lv.pData.size(), (*(int32*)&lvInfo.vVolume.w) & (1 << 31) ? 1 : 0);
  274.  
  275.                 if (GetCVars()->e_LightVolumesDebug == 2)
  276.                 {
  277.                         const float fSideSize = 0.707f * sqrtf(lvInfo.vVolume.w * lvInfo.vVolume.w * 2);
  278.                         pAuxGeom->DrawAABB(AABB(vPos - Vec3(fSideSize), vPos + Vec3(fSideSize)), false, cCol, eBBD_Faceted);
  279.                 }
  280.  
  281.                 if (GetCVars()->e_LightVolumesDebug == 3)
  282.                 {
  283.                         cBad.a = 1.0f;
  284.                         const Vec3 vCellPos = Vec3(floorf((lvInfo.vVolume.x) * LV_CELL_RSIZEX) * LV_CELL_SIZEX,
  285.                                                    floorf((lvInfo.vVolume.y) * LV_CELL_RSIZEY) * LV_CELL_SIZEY,
  286.                                                    floorf((lvInfo.vVolume.z) * LV_CELL_RSIZEZ) * LV_CELL_SIZEZ);
  287.  
  288.                         const Vec3 vMin = vCellPos;
  289.                         const Vec3 vMax = vMin + Vec3(LV_CELL_SIZEX, LV_CELL_SIZEY, LV_CELL_SIZEZ);
  290.                         pAuxGeom->DrawAABB(AABB(vMin, vMax), false, cBad, eBBD_Faceted);
  291.                 }
  292.         }
  293. #endif
  294. }
  295.  
downloadLightVolumeManager.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