BVB Source Codes

CRYENGINE Show FogVolumeRenderNode.cpp Source code

Return Download CRYENGINE: download FogVolumeRenderNode.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 "FogVolumeRenderNode.h"
  5. #include "VisAreas.h"
  6. #include <CryRenderer/RenderElements/CREFogVolume.h>
  7. #include <CryMath/Cry_Geo.h>
  8. #include "ObjMan.h"
  9. #include "ClipVolumeManager.h"
  10.  
  11. #include <limits>
  12.  
  13. AABB CFogVolumeRenderNode::s_tracableFogVolumeArea(Vec3(0, 0, 0), Vec3(0, 0, 0));
  14. CFogVolumeRenderNode::CachedFogVolumes CFogVolumeRenderNode::s_cachedFogVolumes;
  15. CFogVolumeRenderNode::GlobalFogVolumeMap CFogVolumeRenderNode::s_globalFogVolumeMap;
  16. bool CFogVolumeRenderNode::s_forceTraceableAreaUpdate(false);
  17.  
  18. void CFogVolumeRenderNode::StaticReset()
  19. {
  20.         stl::free_container(s_cachedFogVolumes);
  21. }
  22.  
  23. void CFogVolumeRenderNode::ForceTraceableAreaUpdate()
  24. {
  25.         s_forceTraceableAreaUpdate = true;
  26. }
  27.  
  28. void CFogVolumeRenderNode::SetTraceableArea(const AABB& traceableArea, const SRenderingPassInfo& passInfo)
  29. {
  30.         // do we bother?
  31.         if (!GetCVars()->e_Fog || !GetCVars()->e_FogVolumes)
  32.                 return;
  33.  
  34.         if (GetCVars()->e_VolumetricFog != 0)
  35.                 return;
  36.  
  37.         // is update of traceable areas necessary
  38.         if (!s_forceTraceableAreaUpdate)
  39.                 if ((s_tracableFogVolumeArea.GetCenter() - traceableArea.GetCenter()).GetLengthSquared() < 1e-4f && (s_tracableFogVolumeArea.GetSize() - traceableArea.GetSize()).GetLengthSquared() < 1e-4f)
  40.                         return;
  41.  
  42.         // set new area and reset list of traceable fog volumes
  43.         s_tracableFogVolumeArea = traceableArea;
  44.         s_cachedFogVolumes.resize(0);
  45.  
  46.         // collect all candidates
  47.         Vec3 traceableAreaCenter(s_tracableFogVolumeArea.GetCenter());
  48.         IVisArea* pVisAreaOfCenter(GetVisAreaManager() ? GetVisAreaManager()->GetVisAreaFromPos(traceableAreaCenter) : NULL);
  49.  
  50.         GlobalFogVolumeMap::const_iterator itEnd(s_globalFogVolumeMap.end());
  51.         for (GlobalFogVolumeMap::const_iterator it(s_globalFogVolumeMap.begin()); it != itEnd; ++it)
  52.         {
  53.                 const CFogVolumeRenderNode* pFogVolume(*it);
  54.                 if (pVisAreaOfCenter || (!pVisAreaOfCenter && !pFogVolume->GetEntityVisArea())) // if outside only add fog volumes which are outside as well
  55.                         if (Overlap::AABB_AABB(s_tracableFogVolumeArea, pFogVolume->m_WSBBox))        // bb of fog volume overlaps with traceable area
  56.                                 s_cachedFogVolumes.push_back(SCachedFogVolume(pFogVolume, Vec3(pFogVolume->m_pos - traceableAreaCenter).GetLengthSquared()));
  57.         }
  58.  
  59.         // sort by distance
  60.         std::sort(s_cachedFogVolumes.begin(), s_cachedFogVolumes.end());
  61.  
  62.         // reset force-update flags
  63.         s_forceTraceableAreaUpdate = false;
  64. }
  65.  
  66. void CFogVolumeRenderNode::RegisterFogVolume(const CFogVolumeRenderNode* pFogVolume)
  67. {
  68.         GlobalFogVolumeMap::const_iterator it(s_globalFogVolumeMap.find(pFogVolume));
  69.         assert(it == s_globalFogVolumeMap.end() &&
  70.                "CFogVolumeRenderNode::RegisterFogVolume() -- Fog volume already registered!");
  71.         if (it == s_globalFogVolumeMap.end())
  72.         {
  73.                 s_globalFogVolumeMap.insert(pFogVolume);
  74.                 ForceTraceableAreaUpdate();
  75.         }
  76. }
  77.  
  78. void CFogVolumeRenderNode::UnregisterFogVolume(const CFogVolumeRenderNode* pFogVolume)
  79. {
  80.         GlobalFogVolumeMap::iterator it(s_globalFogVolumeMap.find(pFogVolume));
  81.         assert(it != s_globalFogVolumeMap.end() &&
  82.                "CFogVolumeRenderNode::UnRegisterFogVolume() -- Fog volume previously not registered!");
  83.         if (it != s_globalFogVolumeMap.end())
  84.         {
  85.                 s_globalFogVolumeMap.erase(it);
  86.                 ForceTraceableAreaUpdate();
  87.         }
  88. }
  89.  
  90. CFogVolumeRenderNode::CFogVolumeRenderNode()
  91.         : m_matNodeWS()
  92.         , m_matWS()
  93.         , m_matWSInv()
  94.         , m_volumeType(IFogVolumeRenderNode::eFogVolumeType_Ellipsoid)
  95.         , m_pos(0, 0, 0)
  96.         , m_x(1, 0, 0)
  97.         , m_y(0, 1, 0)
  98.         , m_z(0, 0, 1)
  99.         , m_scale(1, 1, 1)
  100.         , m_globalDensity(1)
  101.         , m_densityOffset(0)
  102.         , m_nearCutoff(0)
  103.         , m_fHDRDynamic(0)
  104.         , m_softEdges(1)
  105.         , m_color(1, 1, 1, 1)
  106.         , m_useGlobalFogColor(false)
  107.         , m_affectsThisAreaOnly(false)
  108.         , m_rampParams(0, 1, 0)
  109.         , m_updateFrameID(0)
  110.         , m_windInfluence(1)
  111.         , m_noiseElapsedTime(-5000.0f)
  112.         , m_densityNoiseScale(0)
  113.         , m_densityNoiseOffset(0)
  114.         , m_densityNoiseTimeFrequency(0)
  115.         , m_densityNoiseFrequency(1, 1, 1)
  116.         , m_emission(0, 0, 0)
  117.         , m_heightFallOffDir(0, 0, 1)
  118.         , m_heightFallOffDirScaled(0, 0, 1)
  119.         , m_heightFallOffShift(0, 0, 0)
  120.         , m_heightFallOffBasePoint(0, 0, 0)
  121.         , m_localBounds(Vec3(-1, -1, -1), Vec3(1, 1, 1))
  122.         , m_globalDensityFader()
  123.         , m_pMatFogVolEllipsoid(0)
  124.         , m_pMatFogVolBox(0)
  125.         , m_WSBBox()
  126.         , m_cachedSoftEdgesLerp(1, 0)
  127.         , m_cachedFogColor(1, 1, 1, 1)
  128. {
  129.         GetInstCount(GetRenderNodeType())++;
  130.  
  131.         m_matNodeWS.SetIdentity();
  132.  
  133.         m_matWS.SetIdentity();
  134.         m_matWSInv.SetIdentity();
  135.  
  136.         m_windOffset.x = cry_random(0.0f, 1000.0f);
  137.         m_windOffset.y = cry_random(0.0f, 1000.0f);
  138.         m_windOffset.z = cry_random(0.0f, 1000.0f);
  139.  
  140.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  141.         {
  142.                 m_pFogVolumeRenderElement[i] = GetRenderer() ? ((CREFogVolume*) GetRenderer()->EF_CreateRE(eDATA_FogVolume)) : nullptr;
  143.         }
  144.  
  145.         m_pMatFogVolEllipsoid = Get3DEngine()->m_pMatFogVolEllipsoid;
  146.         m_pMatFogVolBox = Get3DEngine()->m_pMatFogVolBox;
  147.  
  148.         //Get3DEngine()->RegisterEntity( this );
  149.         RegisterFogVolume(this);
  150. }
  151.  
  152. CFogVolumeRenderNode::~CFogVolumeRenderNode()
  153. {
  154.         GetInstCount(GetRenderNodeType())--;
  155.  
  156.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  157.         {
  158.                 if (m_pFogVolumeRenderElement[i])
  159.                 {
  160.                         m_pFogVolumeRenderElement[i]->Release(false);
  161.                         m_pFogVolumeRenderElement[i] = 0;
  162.                 }
  163.         }
  164.  
  165.         UnregisterFogVolume(this);
  166.         Get3DEngine()->FreeRenderNodeState(this);
  167. }
  168.  
  169. void CFogVolumeRenderNode::UpdateFogVolumeMatrices()
  170. {
  171.         // update matrices used for ray tracing, distance sorting, etc.
  172.         Matrix34 mtx = Matrix34::CreateFromVectors(m_scale.x * m_x, m_scale.y * m_y, m_scale.z * m_z, m_pos);
  173.         m_matWS = mtx;
  174.         m_matWSInv = mtx.GetInverted();
  175. }
  176.  
  177. void CFogVolumeRenderNode::UpdateWorldSpaceBBox()
  178. {
  179.         // update bounding box in world space used for culling
  180.         m_WSBBox.SetTransformedAABB(m_matNodeWS, m_localBounds);
  181. }
  182.  
  183. void CFogVolumeRenderNode::UpdateHeightFallOffBasePoint()
  184. {
  185.         m_heightFallOffBasePoint = m_pos + m_heightFallOffShift;
  186. }
  187.  
  188. void CFogVolumeRenderNode::SetFogVolumeProperties(const SFogVolumeProperties& properties)
  189. {
  190.         m_globalDensityFader.SetInvalid();
  191.  
  192.         assert(properties.m_size.x > 0 && properties.m_size.y > 0 && properties.m_size.z > 0);
  193.         Vec3 scale(properties.m_size * 0.5f);
  194.         if ((m_scale - scale).GetLengthSquared() > 1e-4)
  195.         {
  196.                 m_scale = properties.m_size * 0.5f;
  197.                 m_localBounds.min = Vec3(-1, -1, -1).CompMul(m_scale);
  198.                 m_localBounds.max = -m_localBounds.min;
  199.                 UpdateWorldSpaceBBox();
  200.         }
  201.  
  202.         m_volumeType = clamp_tpl<int32>(properties.m_volumeType,
  203.                                         IFogVolumeRenderNode::eFogVolumeType_Ellipsoid,
  204.                                         IFogVolumeRenderNode::eFogVolumeType_Box);
  205.         m_color = properties.m_color;
  206.         assert(properties.m_globalDensity >= 0);
  207.         m_useGlobalFogColor = properties.m_useGlobalFogColor;
  208.         m_globalDensity = properties.m_globalDensity;
  209.         m_densityOffset = properties.m_densityOffset;
  210.         m_nearCutoff = properties.m_nearCutoff;
  211.         m_fHDRDynamic = properties.m_fHDRDynamic;
  212.         assert(properties.m_softEdges >= 0 && properties.m_softEdges <= 1);
  213.         m_softEdges = properties.m_softEdges;
  214.  
  215.         // IgnoreVisArea and AffectsThisAreaOnly don't work concurrently.
  216.         SetRndFlags(ERF_RENDER_ALWAYS, properties.m_ignoresVisAreas && !properties.m_affectsThisAreaOnly);
  217.  
  218.         m_affectsThisAreaOnly = properties.m_affectsThisAreaOnly;
  219.  
  220.         float latiArc(DEG2RAD(90.0f - properties.m_heightFallOffDirLati));
  221.         float longArc(DEG2RAD(properties.m_heightFallOffDirLong));
  222.         float sinLati(sinf(latiArc));
  223.         float cosLati(cosf(latiArc));
  224.         float sinLong(sinf(longArc));
  225.         float cosLong(cosf(longArc));
  226.         m_heightFallOffDir = Vec3(sinLati * cosLong, sinLati * sinLong, cosLati);
  227.         m_heightFallOffShift = m_heightFallOffDir * properties.m_heightFallOffShift;
  228.         m_heightFallOffDirScaled = m_heightFallOffDir * properties.m_heightFallOffScale;
  229.         UpdateHeightFallOffBasePoint();
  230.  
  231.         m_rampParams = Vec3(properties.m_rampStart, properties.m_rampEnd, properties.m_rampInfluence);
  232.  
  233.         m_windInfluence = properties.m_windInfluence;
  234.         m_densityNoiseScale = properties.m_densityNoiseScale;
  235.         m_densityNoiseOffset = properties.m_densityNoiseOffset + 1.0f;
  236.         m_densityNoiseTimeFrequency = properties.m_densityNoiseTimeFrequency;
  237.         m_densityNoiseFrequency = properties.m_densityNoiseFrequency * 0.01f;// scale the value to useful range
  238.         m_emission = properties.m_emission;
  239. }
  240.  
  241. const Matrix34& CFogVolumeRenderNode::GetMatrix() const
  242. {
  243.         return m_matNodeWS;
  244. }
  245.  
  246. void CFogVolumeRenderNode::GetLocalBounds(AABB& bbox)
  247. {
  248.         bbox = m_localBounds;
  249. };
  250.  
  251. void CFogVolumeRenderNode::SetMatrix(const Matrix34& mat)
  252. {
  253.         m_matNodeWS = mat;
  254.  
  255.         // get translation and rotational part of fog volume from entity matrix
  256.         // scale is specified explicitly as fog volumes can be non-uniformly scaled
  257.         m_pos = mat.GetTranslation();
  258.         m_x = mat.GetColumn(0);
  259.         m_y = mat.GetColumn(1);
  260.         m_z = mat.GetColumn(2);
  261.  
  262.         UpdateFogVolumeMatrices();
  263.         UpdateWorldSpaceBBox();
  264.         UpdateHeightFallOffBasePoint();
  265.  
  266.         Get3DEngine()->RegisterEntity(this);
  267.         ForceTraceableAreaUpdate();
  268. }
  269.  
  270. void CFogVolumeRenderNode::FadeGlobalDensity(float fadeTime, float newGlobalDensity)
  271. {
  272.         if (newGlobalDensity >= 0)
  273.         {
  274.                 if (fadeTime == 0)
  275.                 {
  276.                         m_globalDensity = newGlobalDensity;
  277.                         m_globalDensityFader.SetInvalid();
  278.                 }
  279.                 else if (fadeTime > 0)
  280.                 {
  281.                         float curFrameTime(gEnv->pTimer->GetCurrTime());
  282.                         m_globalDensityFader.Set(curFrameTime, curFrameTime + fadeTime, m_globalDensity, newGlobalDensity);
  283.                 }
  284.         }
  285. }
  286.  
  287. const char* CFogVolumeRenderNode::GetEntityClassName() const
  288. {
  289.         return "FogVolume";
  290. }
  291.  
  292. const char* CFogVolumeRenderNode::GetName() const
  293. {
  294.         return "FogVolume";
  295. }
  296.  
  297. ColorF CFogVolumeRenderNode::GetFogColor() const
  298. {
  299.         //FUNCTION_PROFILER_3DENGINE
  300.         Vec3 fogColor(m_color.r, m_color.g, m_color.b);
  301.  
  302.         bool bVolFogEnabled = (GetCVars()->e_VolumetricFog != 0);
  303.         if (bVolFogEnabled)
  304.         {
  305.                 if (m_useGlobalFogColor)
  306.                 {
  307.                         Get3DEngine()->GetGlobalParameter(E3DPARAM_VOLFOG2_COLOR, fogColor);
  308.                 }
  309.         }
  310.         else
  311.         {
  312.                 if (m_useGlobalFogColor)
  313.                 {
  314.                         fogColor = Get3DEngine()->GetFogColor();
  315.                 }
  316.         }
  317.  
  318.         bool bHDRModeEnabled = false;
  319.         GetRenderer()->EF_Query(EFQ_HDRModeEnabled, bHDRModeEnabled);
  320.         if (bHDRModeEnabled)
  321.                 fogColor *= powf(HDRDynamicMultiplier, m_fHDRDynamic);
  322.  
  323.         return fogColor;
  324. }
  325.  
  326. Vec2 CFogVolumeRenderNode::GetSoftEdgeLerp(const Vec3& viewerPosOS) const
  327. {
  328.         // Volumetric fog doesn't need special treatment when camera is in the ellipsoid.
  329.         if (GetCVars()->e_VolumetricFog != 0)
  330.         {
  331.                 return Vec2(m_softEdges, 1.0f - m_softEdges);
  332.         }
  333.  
  334.         //FUNCTION_PROFILER_3DENGINE
  335.         // ramp down soft edge factor as soon as camera enters the ellipsoid
  336.         float softEdge(m_softEdges * clamp_tpl((viewerPosOS.GetLength() - 0.95f) * 20.0f, 0.0f, 1.0f));
  337.         return Vec2(softEdge, 1.0f - softEdge);
  338. }
  339.  
  340. bool CFogVolumeRenderNode::IsViewerInsideVolume(const SRenderingPassInfo& passInfo) const
  341. {
  342.         const CCamera& cam(passInfo.GetCamera());
  343.  
  344.         // check if fog volumes bounding box intersects the near clipping plane
  345.         const Plane* pNearPlane(cam.GetFrustumPlane(FR_PLANE_NEAR));
  346.         Vec3 pntOnNearPlane(cam.GetPosition() - pNearPlane->DistFromPlane(cam.GetPosition()) * pNearPlane->n);
  347.         Vec3 pntOnNearPlaneOS(m_matWSInv.TransformPoint(pntOnNearPlane));
  348.  
  349.         Vec3 nearPlaneOS_n(m_matWSInv.TransformVector(pNearPlane->n) /*.GetNormalized()*/);
  350.         f32 nearPlaneOS_d(-nearPlaneOS_n.Dot(pntOnNearPlaneOS));
  351.  
  352.         // get extreme lengths
  353.         float t(fabsf(nearPlaneOS_n.x) + fabsf(nearPlaneOS_n.y) + fabsf(nearPlaneOS_n.z));
  354.         //float t( 0.0f );
  355.         //if( nearPlaneOS_n.x >= 0 ) t += -nearPlaneOS_n.x; else t += nearPlaneOS_n.x;
  356.         //if( nearPlaneOS_n.y >= 0 ) t += -nearPlaneOS_n.y; else t += nearPlaneOS_n.y;
  357.         //if( nearPlaneOS_n.z >= 0 ) t += -nearPlaneOS_n.z; else t += nearPlaneOS_n.z;
  358.  
  359.         float t0 = t + nearPlaneOS_d;
  360.         float t1 = -t + nearPlaneOS_d;
  361.  
  362.         return t0 * t1 < 0.0f;
  363. }
  364.  
  365. void CFogVolumeRenderNode::Render(const SRendParams& rParam, const SRenderingPassInfo& passInfo)
  366. {
  367.         FUNCTION_PROFILER_3DENGINE;
  368.  
  369.         // anything to render?
  370.         if (passInfo.IsRecursivePass())
  371.                 return;
  372.  
  373.         if (!m_pMatFogVolBox || !m_pMatFogVolEllipsoid || GetCVars()->e_Fog == 0 || GetCVars()->e_FogVolumes == 0)
  374.                 return;
  375.  
  376.         const int32 fillThreadID = passInfo.ThreadID();
  377.  
  378.         if (!m_pFogVolumeRenderElement[fillThreadID])
  379.                 return;
  380.  
  381.         if (m_globalDensityFader.IsValid())
  382.         {
  383.                 float curFrameTime(gEnv->pTimer->GetCurrTime());
  384.                 m_globalDensity = m_globalDensityFader.GetValue(curFrameTime);
  385.                 if (!m_globalDensityFader.IsTimeInRange(curFrameTime))
  386.                         m_globalDensityFader.SetInvalid();
  387.         }
  388.  
  389.         // transform camera into fog volumes object space (where fog volume is a unit-sphere at (0,0,0))
  390.         const CCamera& cam(passInfo.GetCamera());
  391.         Vec3 viewerPosWS(cam.GetPosition());
  392.         Vec3 viewerPosOS(m_matWSInv * viewerPosWS);
  393.  
  394.         m_cachedFogColor = GetFogColor();
  395.         m_cachedSoftEdgesLerp = GetSoftEdgeLerp(viewerPosOS);
  396.  
  397.         bool bVolFog = (GetCVars()->e_VolumetricFog != 0);
  398.  
  399.         // reset elapsed time for noise when FogVolume stayed out of viewport for 30 frames.
  400.         // this prevents the time from being too large number.
  401.         if ((m_updateFrameID + 30) < passInfo.GetMainFrameID() && m_noiseElapsedTime > 5000.0f)
  402.         {
  403.                 m_noiseElapsedTime = -5000.0f;
  404.         }
  405.  
  406.         if (bVolFog && m_densityNoiseScale > 0.0f && m_updateFrameID != passInfo.GetMainFrameID())
  407.         {
  408.                 Vec3 wind = Get3DEngine()->GetGlobalWind(false);
  409.                 const float elapsedTime = gEnv->pTimer->GetFrameTime();
  410.  
  411.                 m_windOffset = ((-m_windInfluence * elapsedTime) * wind) + m_windOffset;
  412.  
  413.                 const float windOffsetSpan = 1000.0f;// it should match the constant value in FogVolume.cfx
  414.                 m_windOffset.x = m_windOffset.x - floor(m_windOffset.x / windOffsetSpan) * windOffsetSpan;
  415.                 m_windOffset.y = m_windOffset.y - floor(m_windOffset.y / windOffsetSpan) * windOffsetSpan;
  416.                 m_windOffset.z = m_windOffset.z - floor(m_windOffset.z / windOffsetSpan) * windOffsetSpan;
  417.  
  418.                 m_noiseElapsedTime += m_densityNoiseTimeFrequency * elapsedTime;
  419.  
  420.                 m_updateFrameID = passInfo.GetMainFrameID();
  421.         }
  422.  
  423.         float densityOffset = bVolFog ? (m_densityOffset * 0.001f) : m_densityOffset;// scale the value to useful range
  424.  
  425.         // set render element attributes
  426.         m_pFogVolumeRenderElement[fillThreadID]->m_center = m_pos;
  427.         m_pFogVolumeRenderElement[fillThreadID]->m_viewerInsideVolume = IsViewerInsideVolume(passInfo) ? 1 : 0;
  428.         m_pFogVolumeRenderElement[fillThreadID]->m_affectsThisAreaOnly = m_affectsThisAreaOnly ? 1 : 0;
  429.         m_pFogVolumeRenderElement[fillThreadID]->m_stencilRef = rParam.nClipVolumeStencilRef;
  430.         m_pFogVolumeRenderElement[fillThreadID]->m_volumeType = m_volumeType;
  431.         m_pFogVolumeRenderElement[fillThreadID]->m_localAABB = m_localBounds;
  432.         m_pFogVolumeRenderElement[fillThreadID]->m_matWSInv = m_matWSInv;
  433.         m_pFogVolumeRenderElement[fillThreadID]->m_fogColor = m_cachedFogColor;
  434.         m_pFogVolumeRenderElement[fillThreadID]->m_globalDensity = m_globalDensity;
  435.         m_pFogVolumeRenderElement[fillThreadID]->m_densityOffset = densityOffset;
  436.         m_pFogVolumeRenderElement[fillThreadID]->m_nearCutoff = m_nearCutoff;
  437.         m_pFogVolumeRenderElement[fillThreadID]->m_softEdgesLerp = m_cachedSoftEdgesLerp;
  438.         m_pFogVolumeRenderElement[fillThreadID]->m_heightFallOffDirScaled = m_heightFallOffDirScaled;
  439.         m_pFogVolumeRenderElement[fillThreadID]->m_heightFallOffBasePoint = m_heightFallOffBasePoint;
  440.         m_pFogVolumeRenderElement[fillThreadID]->m_eyePosInWS = viewerPosWS;
  441.         m_pFogVolumeRenderElement[fillThreadID]->m_eyePosInOS = viewerPosOS;
  442.         m_pFogVolumeRenderElement[fillThreadID]->m_rampParams = m_rampParams;
  443.         m_pFogVolumeRenderElement[fillThreadID]->m_windOffset = m_windOffset;
  444.         m_pFogVolumeRenderElement[fillThreadID]->m_noiseScale = m_densityNoiseScale;
  445.         m_pFogVolumeRenderElement[fillThreadID]->m_noiseFreq = m_densityNoiseFrequency;
  446.         m_pFogVolumeRenderElement[fillThreadID]->m_noiseOffset = m_densityNoiseOffset;
  447.         m_pFogVolumeRenderElement[fillThreadID]->m_noiseElapsedTime = m_noiseElapsedTime;
  448.         m_pFogVolumeRenderElement[fillThreadID]->m_emission = m_emission;
  449.  
  450.         if (bVolFog)
  451.         {
  452.                 IRenderView* pRenderView = passInfo.GetIRenderView();
  453.                 pRenderView->AddFogVolume(m_pFogVolumeRenderElement[fillThreadID]);
  454.         }
  455.         else
  456.         {
  457.                 IRenderer* pRenderer = GetRenderer();
  458.                 CRenderObject* pRenderObject = pRenderer->EF_GetObject_Temp(fillThreadID);
  459.  
  460.                 if (!pRenderObject)
  461.                         return;
  462.  
  463.                 // set basic render object properties
  464.                 pRenderObject->m_II.m_Matrix = m_matNodeWS;
  465.                 pRenderObject->m_ObjFlags |= FOB_TRANS_MASK;
  466.                 pRenderObject->m_fSort = 0;
  467.  
  468.                 int nAfterWater = GetObjManager()->IsAfterWater(m_pos, passInfo.GetCamera().GetPosition(), passInfo, Get3DEngine()->GetWaterLevel()) ? 1 : 0;
  469.  
  470.                 // TODO: add constant factor to sortID to make fog volumes render before all other alpha transparent geometry (or have separate render list?)
  471.                 pRenderObject->m_fSort = WATER_LEVEL_SORTID_OFFSET * 0.5f;
  472.  
  473.                 // get shader item
  474.                 IMaterial* pMaterial =
  475.                   (m_volumeType == IFogVolumeRenderNode::eFogVolumeType_Box)
  476.                   ? m_pMatFogVolBox
  477.                   : m_pMatFogVolEllipsoid;
  478.                 pMaterial = (rParam.pMaterial != nullptr) ? rParam.pMaterial : pMaterial;
  479.                 SShaderItem& shaderItem = pMaterial->GetShaderItem(0);
  480.  
  481.                 // add to renderer
  482.                 GetRenderer()->EF_AddEf(m_pFogVolumeRenderElement[fillThreadID], shaderItem, pRenderObject, passInfo, EFSLIST_TRANSP, nAfterWater);
  483.         }
  484. }
  485.  
  486. IPhysicalEntity* CFogVolumeRenderNode::GetPhysics() const
  487. {
  488.         return 0;
  489. }
  490.  
  491. void CFogVolumeRenderNode::SetPhysics(IPhysicalEntity*)
  492. {
  493. }
  494.  
  495. void CFogVolumeRenderNode::SetMaterial(IMaterial* pMat)
  496. {
  497. }
  498.  
  499. void CFogVolumeRenderNode::GetMemoryUsage(ICrySizer* pSizer) const
  500. {
  501.         SIZER_COMPONENT_NAME(pSizer, "FogVolumeNode");
  502.         pSizer->AddObject(this, sizeof(*this));
  503. }
  504.  
  505. void CFogVolumeRenderNode::OffsetPosition(const Vec3& delta)
  506. {
  507.         if (m_pTempData) m_pTempData->OffsetPosition(delta);
  508.         m_pos += delta;
  509.         m_matNodeWS.SetTranslation(m_matNodeWS.GetTranslation() + delta);
  510.         m_matWS.SetTranslation(m_matWS.GetTranslation() + delta);
  511.         m_matWSInv = m_matWS.GetInverted();
  512.         m_heightFallOffBasePoint += delta;
  513.         m_WSBBox.Move(delta);
  514. }
  515.  
  516. ///////////////////////////////////////////////////////////////////////////////
  517. inline static float expf_s(float arg)
  518. {
  519.         return expf(clamp_tpl(arg, -80.0f, 80.0f));
  520. }
  521.  
  522. ///////////////////////////////////////////////////////////////////////////////
  523. ///////////////////////////////////////////////////////////////////////////////
  524. void CFogVolumeRenderNode::TraceFogVolumes(const Vec3& worldPos, ColorF& fogColor, const SRenderingPassInfo& passInfo)
  525. {
  526.         FUNCTION_PROFILER_3DENGINE;
  527.         PrefetchLine(&s_tracableFogVolumeArea, 0);
  528.  
  529.         // init default result
  530.         ColorF localFogColor = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
  531.  
  532.         // trace is needed when volumetric fog is off.
  533.         if (GetCVars()->e_Fog && GetCVars()->e_FogVolumes && (GetCVars()->e_VolumetricFog == 0))
  534.         {
  535.                 // init view ray
  536.                 Vec3 camPos(s_tracableFogVolumeArea.GetCenter());
  537.                 Lineseg lineseg(camPos, worldPos);
  538.  
  539. #ifdef _DEBUG
  540.                 const SCachedFogVolume* prev(0);
  541. #endif
  542.  
  543.                 // loop over all traceable fog volumes
  544.                 CachedFogVolumes::const_iterator itEnd(s_cachedFogVolumes.end());
  545.                 for (CachedFogVolumes::const_iterator it(s_cachedFogVolumes.begin()); it != itEnd; ++it)
  546.                 {
  547.                         // get current fog volume
  548.                         const CFogVolumeRenderNode* pFogVol((*it).m_pFogVol);
  549.  
  550.                         // only trace visible fog volumes
  551.                         if (!(pFogVol->GetRndFlags() & ERF_HIDDEN))
  552.                         {
  553.                                 // check if view ray intersects with bounding box of current fog volume
  554.                                 if (Overlap::Lineseg_AABB(lineseg, pFogVol->m_WSBBox))
  555.                                 {
  556.                                         // compute contribution of current fog volume
  557.                                         ColorF color;
  558.                                         if (0 == pFogVol->m_volumeType)
  559.                                                 pFogVol->GetVolumetricFogColorEllipsoid(worldPos, passInfo, color);
  560.                                         else
  561.                                                 pFogVol->GetVolumetricFogColorBox(worldPos, passInfo, color);
  562.  
  563.                                         color.a = 1.0f - color.a;   // 0 = transparent, 1 = opaque
  564.  
  565.                                                                                                                                                         // blend fog colors
  566.                                         localFogColor.r = Lerp(localFogColor.r, color.r, color.a);
  567.                                         localFogColor.g = Lerp(localFogColor.g, color.g, color.a);
  568.                                         localFogColor.b = Lerp(localFogColor.b, color.b, color.a);
  569.                                         localFogColor.a = Lerp(localFogColor.a, 1.0f, color.a);
  570.                                 }
  571.                         }
  572.  
  573. #ifdef _DEBUG
  574.                         if (prev)
  575.                         {
  576.                                 assert(prev->m_distToCenterSq >= (*it).m_distToCenterSq);
  577.                                 prev = &(*it);
  578.                         }
  579. #endif
  580.  
  581.                 }
  582.  
  583.                 const float fDivisor = (float)__fsel(-localFogColor.a, 1.0f, localFogColor.a);
  584.                 const float fMultiplier = (float)__fsel(-localFogColor.a, 0.0f, 1.0f / fDivisor);
  585.  
  586.                 localFogColor.r *= fMultiplier;
  587.                 localFogColor.g *= fMultiplier;
  588.                 localFogColor.b *= fMultiplier;
  589.         }
  590.  
  591.         localFogColor.a = 1.0f - localFogColor.a;
  592.  
  593.         fogColor = localFogColor;
  594. }
  595.  
  596. ///////////////////////////////////////////////////////////////////////////////
  597. void CFogVolumeRenderNode::GetVolumetricFogColorEllipsoid(const Vec3& worldPos, const SRenderingPassInfo& passInfo, ColorF& resultColor) const
  598. {
  599.         const CCamera& cam(passInfo.GetCamera());
  600.         Vec3 camPos(cam.GetPosition());
  601.         Vec3 camDir(cam.GetViewdir());
  602.         Vec3 cameraLookDir(worldPos - camPos);
  603.  
  604.         resultColor = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
  605.  
  606.         if (cameraLookDir.GetLengthSquared() > 1e-4f)
  607.         {
  608.                 // setup ray tracing in OS
  609.                 Vec3 cameraPosInOSx2(m_matWSInv.TransformPoint(camPos) * 2.0f);
  610.                 Vec3 cameraLookDirInOS(m_matWSInv.TransformVector(cameraLookDir));
  611.  
  612.                 float tI(sqrtf(cameraLookDirInOS.Dot(cameraLookDirInOS)));
  613.                 float invOfScaledCamDirLength(1.0f / tI);
  614.                 cameraLookDirInOS *= invOfScaledCamDirLength;
  615.  
  616.                 // calc coefficients for ellipsoid parametrization (just a simple unit-sphere in its own space)
  617.                 float B(cameraPosInOSx2.Dot(cameraLookDirInOS));
  618.                 float Bsq(B * B);
  619.                 float C(cameraPosInOSx2.Dot(cameraPosInOSx2) - 4.0f);
  620.  
  621.                 // solve quadratic equation
  622.                 float discr(Bsq - C);
  623.                 if (discr >= 0.0)
  624.                 {
  625.                         float discrSqrt = sqrtf(discr);
  626.  
  627.                         // ray hit
  628.                         Vec3 cameraPosInWS(camPos);
  629.                         Vec3 cameraLookDirInWS((worldPos - camPos) * invOfScaledCamDirLength);
  630.  
  631.                         //////////////////////////////////////////////////////////////////////////
  632.  
  633.                         float tS(max(0.5f * (-B - discrSqrt), 0.0f));       // clamp to zero so front ray-ellipsoid intersection is NOT behind camera
  634.                         float tE(max(0.5f * (-B + discrSqrt), 0.0f));       // clamp to zero so back ray-ellipsoid intersection is NOT behind camera
  635.                                                                                                                                                                                                                                         //float tI( ( worldPos - camPos ).Dot( camDir ) / cameraLookDirInWS.Dot( camDir ) );
  636.                         tI = max(tS, min(tI, tE));     // clamp to range [tS, tE]
  637.  
  638.                         Vec3 front(tS * cameraLookDirInWS + cameraPosInWS);
  639.                         Vec3 dist((tI - tS) * cameraLookDirInWS);
  640.                         float distLength(dist.GetLength());
  641.                         float fogInt(distLength * expf_s(-(front - m_heightFallOffBasePoint).Dot(m_heightFallOffDirScaled)));
  642.  
  643.                         //////////////////////////////////////////////////////////////////////////
  644.  
  645.                         float heightDiff(dist.Dot(m_heightFallOffDirScaled));
  646.                         if (fabsf(heightDiff) > 0.001f)
  647.                                 fogInt *= (1.0f - expf_s(-heightDiff)) / heightDiff;
  648.  
  649.                         float softArg(clamp_tpl(discr * m_cachedSoftEdgesLerp.x + m_cachedSoftEdgesLerp.y, 0.0f, 1.0f));
  650.                         fogInt *= softArg * (2.0f - softArg);
  651.  
  652.                         float fog(expf_s(-m_globalDensity * fogInt));
  653.  
  654.                         resultColor = ColorF(m_cachedFogColor.r, m_cachedFogColor.g, m_cachedFogColor.b, min(fog, 1.0f));
  655.                 }
  656.         }
  657. }
  658.  
  659. ///////////////////////////////////////////////////////////////////////////////
  660. void CFogVolumeRenderNode::GetVolumetricFogColorBox(const Vec3& worldPos, const SRenderingPassInfo& passInfo, ColorF& resultColor) const
  661. {
  662.         const CCamera& cam(passInfo.GetCamera());
  663.         Vec3 camPos(cam.GetPosition());
  664.         Vec3 cameraLookDir(worldPos - camPos);
  665.  
  666.         resultColor = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
  667.  
  668.         if (cameraLookDir.GetLengthSquared() > 1e-4f)
  669.         {
  670.                 // setup ray tracing in OS
  671.                 Vec3 cameraPosInOS(m_matWSInv.TransformPoint(camPos));
  672.                 Vec3 cameraLookDirInOS(m_matWSInv.TransformVector(cameraLookDir));
  673.  
  674.                 float tI(sqrtf(cameraLookDirInOS.Dot(cameraLookDirInOS)));
  675.                 float invOfScaledCamDirLength(1.0f / tI);
  676.                 cameraLookDirInOS *= invOfScaledCamDirLength;
  677.  
  678.                 const float fMax = std::numeric_limits<float>::max();
  679.                 float tS(0), tE(fMax);
  680.  
  681.                 //TODO:
  682.                 //      May be worth profiling use of a loop here, iterating over elements of vector;
  683.                 //      might save on i-cache, but suspect we'll lose instruction interleaving and hit
  684.                 //      more register dependency issues.
  685.  
  686.                 //These fsels mean that the result is ignored if cameraLookDirInOS.x is 0.0f,
  687.                 //      avoiding a floating point compare. Avoiding the fcmp is ~15% faster
  688.                 const float fXSelect = -fabsf(cameraLookDirInOS.x);
  689.                 const float fXDivisor = (float)__fsel(fXSelect, 1.0f, cameraLookDirInOS.x);
  690.                 const float fXMultiplier = (float)__fsel(fXSelect, 0.0f, 1.0f);
  691.                 const float fXInvMultiplier = 1.0f - fXMultiplier;
  692.  
  693.                 //Accurate to 255/256ths on console
  694.                 float invCameraDirInOSx = __fres(fXDivisor); //(1.0f / fXDivisor);
  695.  
  696.                 float tPosPlane((1 - cameraPosInOS.x) * invCameraDirInOSx);
  697.                 float tNegPlane((-1 - cameraPosInOS.x) * invCameraDirInOSx);
  698.  
  699.                 float tFrontFace = (float)__fsel(-cameraLookDirInOS.x, tPosPlane, tNegPlane);
  700.                 float tBackFace = (float)__fsel(-cameraLookDirInOS.x, tNegPlane, tPosPlane);
  701.  
  702.                 tS = max(tS, tFrontFace * fXMultiplier);
  703.                 tE = min(tE, (tBackFace * fXMultiplier) + (fXInvMultiplier * fMax));
  704.  
  705.                 const float fYSelect = -fabsf(cameraLookDirInOS.y);
  706.                 const float fYDivisor = (float)__fsel(fYSelect, 1.0f, cameraLookDirInOS.y);
  707.                 const float fYMultiplier = (float)__fsel(fYSelect, 0.0f, 1.0f);
  708.                 const float fYInvMultiplier = 1.0f - fYMultiplier;
  709.  
  710.                 //Accurate to 255/256ths on console
  711.                 float invCameraDirInOSy = __fres(fYDivisor); //(1.0f / fYDivisor);
  712.  
  713.                 tPosPlane = ((1 - cameraPosInOS.y) * invCameraDirInOSy);
  714.                 tNegPlane = ((-1 - cameraPosInOS.y) * invCameraDirInOSy);
  715.  
  716.                 tFrontFace = (float)__fsel(-cameraLookDirInOS.y, tPosPlane, tNegPlane);
  717.                 tBackFace = (float)__fsel(-cameraLookDirInOS.y, tNegPlane, tPosPlane);
  718.  
  719.                 tS = max(tS, tFrontFace * fYMultiplier);
  720.                 tE = min(tE, (tBackFace * fYMultiplier) + (fYInvMultiplier * fMax));
  721.  
  722.                 const float fZSelect = -fabsf(cameraLookDirInOS.z);
  723.                 const float fZDivisor = (float)__fsel(fZSelect, 1.0f, cameraLookDirInOS.z);
  724.                 const float fZMultiplier = (float)__fsel(fZSelect, 0.0f, 1.0f);
  725.                 const float fZInvMultiplier = 1.0f - fZMultiplier;
  726.  
  727.                 //Accurate to 255/256ths on console
  728.                 float invCameraDirInOSz = __fres(fZDivisor); //(1.0f / fZDivisor);
  729.  
  730.                 tPosPlane = ((1 - cameraPosInOS.z) * invCameraDirInOSz);
  731.                 tNegPlane = ((-1 - cameraPosInOS.z) * invCameraDirInOSz);
  732.  
  733.                 tFrontFace = (float)__fsel(-cameraLookDirInOS.z, tPosPlane, tNegPlane);
  734.                 tBackFace = (float)__fsel(-cameraLookDirInOS.z, tNegPlane, tPosPlane);
  735.  
  736.                 tS = max(tS, tFrontFace * fZMultiplier);
  737.                 tE = min(tE, (tBackFace * fZMultiplier) + (fZInvMultiplier * fMax));
  738.  
  739.                 tE = max(tE, 0.0f);
  740.  
  741.                 if (tS <= tE)
  742.                 {
  743.                         Vec3 cameraPosInWS(camPos);
  744.                         Vec3 cameraLookDirInWS((worldPos - camPos) * invOfScaledCamDirLength);
  745.  
  746.                         //////////////////////////////////////////////////////////////////////////
  747.  
  748.                         tI = max(tS, min(tI, tE));     // clamp to range [tS, tE]
  749.  
  750.                         Vec3 front(tS * cameraLookDirInWS + cameraPosInWS);
  751.                         Vec3 dist((tI - tS) * cameraLookDirInWS);
  752.                         float distLength(dist.GetLength());
  753.                         float fogInt(distLength * expf_s(-(front - m_heightFallOffBasePoint).Dot(m_heightFallOffDirScaled)));
  754.  
  755.                         //////////////////////////////////////////////////////////////////////////
  756.  
  757.                         float heightDiff(dist.Dot(m_heightFallOffDirScaled));
  758.  
  759.                         //heightDiff = fabsf( heightDiff ) > 0.001f ? heightDiff : 0.001f
  760.                         heightDiff = (float)__fsel((-fabsf(heightDiff) + 0.001f), 0.001f, heightDiff);
  761.  
  762.                         fogInt *= (1.0f - expf_s(-heightDiff)) * __fres(heightDiff);
  763.  
  764.                         float fog(expf_s(-m_globalDensity * fogInt));
  765.  
  766.                         resultColor = ColorF(m_cachedFogColor.r, m_cachedFogColor.g, m_cachedFogColor.b, min(fog, 1.0f));
  767.                 }
  768.         }
  769. }
  770.  
  771. ///////////////////////////////////////////////////////////////////////////////
  772. void CFogVolumeRenderNode::FillBBox(AABB& aabb)
  773. {
  774.         aabb = CFogVolumeRenderNode::GetBBox();
  775. }
  776.  
  777. ///////////////////////////////////////////////////////////////////////////////
  778. EERType CFogVolumeRenderNode::GetRenderNodeType()
  779. {
  780.         return eERType_FogVolume;
  781. }
  782.  
  783. ///////////////////////////////////////////////////////////////////////////////
  784. float CFogVolumeRenderNode::GetMaxViewDist()
  785. {
  786.         if (GetMinSpecFromRenderNodeFlags(m_dwRndFlags) == CONFIG_DETAIL_SPEC)
  787.                 return max(GetCVars()->e_ViewDistMin, CFogVolumeRenderNode::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatioDetail * GetViewDistRatioNormilized());
  788.  
  789.         return max(GetCVars()->e_ViewDistMin, CFogVolumeRenderNode::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatio * GetViewDistRatioNormilized());
  790.  
  791. }
  792.  
  793. ///////////////////////////////////////////////////////////////////////////////
  794. Vec3 CFogVolumeRenderNode::GetPos(bool bWorldOnly) const
  795. {
  796.         return m_pos;
  797. }
  798.  
  799. ///////////////////////////////////////////////////////////////////////////////
  800. IMaterial* CFogVolumeRenderNode::GetMaterial(Vec3* pHitPos) const
  801. {
  802.         return 0;
  803. }
  804.  
downloadFogVolumeRenderNode.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