BVB Source Codes

CRYENGINE Show FeatureRenderSprites.cpp Source code

Return Download CRYENGINE: download FeatureRenderSprites.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 "ParticleSystem/ParticleRender.h"
  5. #include "ParticleSystem/ParticleEmitter.h"
  6. #include <CryMath/RadixSort.h>
  7.  
  8. CRY_PFX2_DBG
  9.  
  10. namespace pfx2
  11. {
  12.  
  13. extern EParticleDataType EPDT_Alpha, EPDT_Color, EPDT_Angle2D, EPDT_Tile;
  14.  
  15. SERIALIZATION_DECLARE_ENUM(ESortMode,
  16.                            None,
  17.                            BackToFront,
  18.                            FrontToBack,
  19.                            OldToNew,
  20.                            NewToOld
  21.                            )
  22.  
  23. SERIALIZATION_DECLARE_ENUM(EFacingMode,
  24.                            Screen,
  25.                            Camera,
  26.                            Velocity,
  27.                            Free
  28.                            )
  29.  
  30. struct SSpritesContext
  31. {
  32.         SSpritesContext(CParticleComponentRuntime* pComponentRuntime, const SComponentParams& params, const SCameraInfo& camInfo, const SVisEnviron& visEnviron, const SPhysEnviron& physEnviron, CREParticle* pRE, TParticleHeap& memHeap, size_t numParticles)
  33.                 : m_context(pComponentRuntime)
  34.                 , m_params(params)
  35.                 , m_camInfo(camInfo)
  36.                 , m_visEnviron(visEnviron)
  37.                 , m_physEnviron(physEnviron)
  38.                 , m_pRE(pRE)
  39.                 , m_particleIds(memHeap, numParticles)
  40.                 , m_spriteAlphas(memHeap, numParticles)
  41.                 , m_numParticles(numParticles)
  42.                 , m_numSprites(0)
  43.                 , m_renderFlags(0)
  44.                 , m_rangeId(0)
  45.         {
  46.         }
  47.         const SUpdateContext              m_context;
  48.         const SComponentParams&           m_params;
  49.         const SCameraInfo&                m_camInfo;
  50.         const SVisEnviron&                m_visEnviron;
  51.         const SPhysEnviron&               m_physEnviron;
  52.         AABB                              m_bounds;
  53.         CREParticle*                      m_pRE;
  54.         TParticleHeap::Array<TParticleId> m_particleIds;
  55.         TParticleHeap::Array<float>       m_spriteAlphas;
  56.         size_t                            m_numParticles;
  57.         size_t                            m_numSprites;
  58.         uint64                            m_renderFlags;
  59.         size_t                            m_rangeId;
  60. };
  61.  
  62. class CFeatureRenderSprites : public CParticleRenderBase
  63. {
  64. private:
  65.         typedef CParticleRenderBase                     BaseClass;
  66.         typedef SParticleAxes (CFeatureRenderSprites::* AxesFn)(const SSpritesContext& context, TParticleId particleId);
  67.  
  68. public:
  69.         CRY_PFX2_DECLARE_FEATURE
  70.  
  71.         CFeatureRenderSprites();
  72.  
  73.         virtual void AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams) override;
  74.         virtual void ComputeVertices(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, uint64 uRenderFlags, float fMaxPixels) override;
  75.         virtual void Serialize(Serialization::IArchive& ar) override;
  76.  
  77. protected:
  78.         bool SupportsWaterCulling() const override { return true; }
  79.  
  80. private:
  81.         void CullParticles(SSpritesContext* pSpritesContext);
  82.         void SortSprites(SSpritesContext* pSpritesContext);
  83.         void WriteToGPUMem(const SSpritesContext& spritesContext);
  84.  
  85.         void WritePositions(const SSpritesContext& spritesContext, FixedDynArray<Vec3>& gpuPositions);
  86.         template<const bool hasAngles2D>
  87.         void WriteAxes(const SSpritesContext& spritesContext, FixedDynArray<SParticleAxes>& gpuAxes);
  88.         template<typename TAxesSampler, const bool hasAngles2D>
  89.         void WriteAxes(const SSpritesContext& spritesContext, FixedDynArray<SParticleAxes>& gpuAxes, const TAxesSampler& axesSampler);
  90.         template<bool hasColors, bool hasTiling, bool hasAnimation>
  91.         void WriteColorSTs(const SSpritesContext& spritesContext, FixedDynArray<SParticleColorST>& gpuColorSTs);
  92.  
  93.         ESortMode   m_sortMode;
  94.         EFacingMode m_facingMode;
  95.         UFloat10    m_aspectRatio;
  96.         UFloat10    m_axisScale;
  97.         UUnitFloat  m_sphericalProjection;
  98.         SFloat      m_sortBias;
  99.         bool        m_flipU, m_flipV;
  100. };
  101.  
  102. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureRenderSprites, "Render", "Sprites", colorRender);
  103.  
  104. //////////////////////////////////////////////////////////////////////////
  105.  
  106. CFeatureRenderSprites::CFeatureRenderSprites()
  107.         : m_sortMode(ESortMode::None)
  108.         , m_facingMode(EFacingMode::Screen)
  109.         , m_aspectRatio(1.0f)
  110.         , m_axisScale(0.1f)
  111.         , m_sphericalProjection(0.0f)
  112.         , m_sortBias(0.0f)
  113.         , m_flipU(false)
  114.         , m_flipV(false)
  115. {
  116. }
  117.  
  118. void CFeatureRenderSprites::AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams)
  119. {
  120.         BaseClass::AddToComponent(pComponent, pParams);
  121.         pParams->m_renderObjectFlags |= FOB_POINT_SPRITE;
  122.         pParams->m_particleObjFlags |= CREParticle::ePOF_USE_VERTEX_PULL_MODEL;
  123.         if (m_facingMode == EFacingMode::Velocity)
  124.                 pComponent->AddParticleData(EPVF_Velocity);
  125.         else if (m_facingMode == EFacingMode::Free)
  126.                 pComponent->AddParticleData(EPQF_Orientation);
  127.         if (m_facingMode != EFacingMode::Free)
  128.                 pParams->m_shaderData.m_sphericalApproximation = m_sphericalProjection;
  129.         else
  130.                 pParams->m_shaderData.m_sphericalApproximation = 0.0f;
  131.         pParams->m_renderObjectSortBias = m_sortBias;
  132. }
  133.  
  134. void CFeatureRenderSprites::Serialize(Serialization::IArchive& ar)
  135. {
  136.         BaseClass::Serialize(ar);
  137.         ar(m_sortMode, "SortMode", "Sort Mode");
  138.         ar(m_facingMode, "FacingMode", "Facing Mode");
  139.         ar(m_aspectRatio, "AspectRatio", "Aspect Ratio");
  140.         if (m_facingMode == EFacingMode::Velocity)
  141.                 ar(m_axisScale, "AxisScale", "Axis Scale");
  142.         if (m_facingMode != EFacingMode::Free)
  143.                 ar(m_sphericalProjection, "SphericalProjection", "Spherical Projection");
  144.         ar(m_sortBias, "SortBias", "Sort Bias");
  145.         ar(m_flipU, "FlipU", "Flip U");
  146.         ar(m_flipV, "FlipV", "Flip V");
  147. }
  148.  
  149. void CFeatureRenderSprites::ComputeVertices(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, uint64 uRenderFlags, float fMaxPixels)
  150. {
  151.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  152.         PARTICLE_LIGHT_PROFILER();
  153.  
  154.         CParticleContainer& container = pComponentRuntime->GetContainer();
  155.         const CParticleEmitter* pEmitter = pComponentRuntime->GetEmitter();
  156.  
  157.         TParticleId lastParticleId = container.GetLastParticleId();
  158.         if (lastParticleId == 0)
  159.                 return;
  160.  
  161.         const auto bounds = pComponentRuntime->GetBounds();
  162.         const auto& physEnv = pEmitter->GetPhysicsEnv();
  163.         const bool isAfterWater = (uRenderFlags & FOB_AFTER_WATER) != 0;
  164.         if ((isAfterWater && physEnv.m_tUnderWater.Value == ETrinaryNames::If_True) ||
  165.             (!isAfterWater && physEnv.m_tUnderWater.Value == ETrinaryNames::If_False))
  166.                 return;
  167.  
  168.         uint32 threadId = JobManager::GetWorkerThreadId();
  169.         TParticleHeap& memHeap = GetPSystem()->GetMemHeap(threadId);
  170.  
  171.         SSpritesContext spritesContext(
  172.           pComponentRuntime, pComponentRuntime->GetComponentParams(),
  173.           camInfo, pEmitter->GetVisEnv(),
  174.           physEnv, pRE, memHeap,
  175.           lastParticleId);
  176.         spritesContext.m_bounds = pEmitter->GetBBox();
  177.         spritesContext.m_renderFlags = uRenderFlags;
  178.  
  179.         CullParticles(&spritesContext);
  180.  
  181.         if (spritesContext.m_numSprites != 0)
  182.         {
  183.                 SortSprites(&spritesContext);
  184.                 WriteToGPUMem(spritesContext);
  185.                 pComponentRuntime->GetEmitter()->AddDrawCallCounts(
  186.                   spritesContext.m_numSprites,
  187.                   spritesContext.m_numParticles - spritesContext.m_numSprites);
  188.                 GetPSystem()->GetProfiler().AddEntry(pComponentRuntime, EPS_RendereredParticles, uint(spritesContext.m_numSprites));
  189.         }
  190. }
  191.  
  192. void CFeatureRenderSprites::CullParticles(SSpritesContext* pSpritesContext)
  193. {
  194.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  195.  
  196.         const SUpdateContext& context = pSpritesContext->m_context;
  197.         const SVisibilityParams& visibility = context.m_params.m_visibility;
  198.         const CParticleEmitter& emitter = *context.m_runtime.GetEmitter();
  199.         const CCamera& camera = *pSpritesContext->m_camInfo.pCamera;
  200.  
  201.         // frustum culling
  202.         Matrix34 invViewTM = pSpritesContext->m_camInfo.pCamera->GetViewMatrix();
  203.         float projectH;
  204.         float projectV;
  205.  
  206.         const bool cullFrustum = camera.IsAABBVisible_FH(pSpritesContext->m_bounds) != CULL_INCLUSION;
  207.         if (cullFrustum)
  208.         {
  209.                 Vec3 frustum = camera.GetEdgeP();
  210.                 float invX = abs(1.0f / frustum.x);
  211.                 float invZ = abs(1.0f / frustum.z);
  212.  
  213.                 non_const(invViewTM.GetRow4(0)) *= frustum.y * invX;
  214.                 non_const(invViewTM.GetRow4(2)) *= frustum.y * invZ;
  215.  
  216.                 projectH = sqrt_tpl(sqr(frustum.x) + sqr(frustum.y)) * invX;
  217.                 projectV = sqrt_tpl(sqr(frustum.z) + sqr(frustum.y)) * invZ;
  218.         }
  219.  
  220.         // size and distance culling
  221.         const float camAng = camera.GetFov();
  222.         const float camNearClip = m_facingMode == EFacingMode::Screen ? 0.0f : camera.GetEdgeN().GetLength();
  223.         const float nearDist = pSpritesContext->m_bounds.GetDistance(camera.GetPosition());
  224.         const float farDist = pSpritesContext->m_bounds.GetFarDistance(camera.GetPosition());
  225.         const float maxScreen = min(+visibility.m_maxScreenSize, GetCVars()->e_ParticlesMaxDrawScreen);
  226.  
  227.         const float minCamDist = max(+visibility.m_minCameraDistance, camNearClip);
  228.         const float maxCamDist = ZeroIsHuge(visibility.m_maxCameraDistance);
  229.         const float invMaxAng = 1.0f / (maxScreen * camAng * 0.5f);
  230.         const float invMinAng = pSpritesContext->m_context.m_pSystem->GetMaxAngularDensity(camera) * emitter.GetViewDistRatio() * visibility.m_viewDistanceMultiple;
  231.  
  232.         const bool cullNear = nearDist < minCamDist * 2.0f
  233.                               || maxScreen < 2 && nearDist < context.m_params.m_maxParticleSize * invMaxAng * 2.0f;
  234.         const bool cullFar = farDist > maxCamDist * 0.75f
  235.                              || GetCVars()->e_ParticlesMinDrawPixels > 0.0f;
  236.  
  237.         const bool culling = cullFrustum || cullNear || cullFar;
  238.  
  239.         CParticleContainer& container = pSpritesContext->m_context.m_container;
  240.         TIOStream<uint8> states = container.GetTIOStream<uint8>(EPDT_State);
  241.         IFStream alphas = container.GetIFStream(EPDT_Alpha, 1.0f);
  242.         IFStream sizes = container.GetIFStream(EPDT_Size);
  243.         IVec3Stream positions = container.GetIVec3Stream(EPVF_Position);
  244.         auto& particleIds = pSpritesContext->m_particleIds;
  245.         auto& spriteAlphas = pSpritesContext->m_spriteAlphas;
  246.  
  247.         // camera culling
  248.         CRY_PFX2_FOR_ACTIVE_PARTICLES(context)
  249.         {
  250.                 const uint8 state = states.Load(particleId);
  251.                 if (!(state & ESB_Alive))
  252.                         continue;
  253.  
  254.                 float cull = 1.0f;
  255.                 const float size = sizes.Load(particleId);
  256.                 if (!cullFar)
  257.                         cull = (size > 0.0f);
  258.  
  259.                 if (culling)
  260.                 {
  261.                         const Vec3 position = positions.Load(particleId);
  262.                         Vec3 posCam = invViewTM * position;
  263.  
  264.                         if (cullFrustum)
  265.                         {
  266.                                 if (max(abs(posCam.x) - size * projectH, abs(posCam.z) - size * projectV) >= posCam.y)
  267.                                         continue;
  268.                         }
  269.  
  270.                         if (cullNear + cullFar)
  271.                         {
  272.                                 const float invDist = isqrt_fast_tpl(posCam.GetLengthSquared());
  273.                                 if (cullNear)
  274.                                 {
  275.                                         const float ratio = max(size * invMaxAng, minCamDist) * invDist;
  276.                                         cull *= min((1.0f - ratio) * 2.0f, 1.0f);
  277.                                 }
  278.                                 if (cullFar)
  279.                                 {
  280.                                         const float ratio = min(size * invMinAng, maxCamDist) * invDist;
  281.                                         cull *= min((ratio - 1.0f) * 3.0f, 1.0f);
  282.                                 }
  283.                         }
  284.                 }
  285.  
  286.                 const float alpha = alphas.SafeLoad(particleId) * cull;
  287.                 if (alpha > 0.0f)
  288.                 {
  289.                         particleIds[pSpritesContext->m_numSprites++] = particleId;
  290.                         spriteAlphas[particleId] = alpha;
  291.                 }
  292.         }
  293.         CRY_PFX2_FOR_END;
  294.  
  295.         if ((GetCVars()->e_ParticlesDebug & AlphaBit('c')) == 0)
  296.         {
  297.                 // vis area clipping
  298.                 CRY_PFX2_ASSERT(container.HasData(EPDT_Size));
  299.                 Matrix34 viewTM = pSpritesContext->m_camInfo.pCamera->GetMatrix();
  300.                 Vec3 normal = -viewTM.GetColumn0();
  301.                 IVisArea* pVisArea = pSpritesContext->m_visEnviron.GetClipVisArea(pSpritesContext->m_camInfo.pCameraVisArea, pSpritesContext->m_bounds);
  302.  
  303.                 if (pVisArea)
  304.                 {
  305.                         const uint count = pSpritesContext->m_numSprites;
  306.                         for (uint i = 0, j = 0; i < count; ++i)
  307.                         {
  308.                                 TParticleId particleId = particleIds[i];
  309.  
  310.                                 Sphere sphere;
  311.                                 const float radius = sizes.Load(particleId) * 0.5f;
  312.                                 sphere.center = positions.Load(particleId);
  313.                                 sphere.radius = radius;
  314.                                 if (pSpritesContext->m_visEnviron.ClipVisAreas(pVisArea, sphere, normal))
  315.                                         spriteAlphas[particleId] *= (sphere.radius - radius) > 0.0f;
  316.  
  317.                                 if (spriteAlphas[particleId] > 0.0f)
  318.                                         particleIds[j++] = particleId;
  319.                                 else
  320.                                         --pSpritesContext->m_numSprites;
  321.                         }
  322.                 }
  323.         }
  324.  
  325.         // water clipping
  326.         //    PFX2_TODO : Optimize : this routine is *!REALLY!* slow when there are water volumes on the map
  327.         const bool doCullWater = (pSpritesContext->m_physEnviron.m_tUnderWater.Value == ETrinaryNames::Both);
  328.         if (doCullWater)
  329.         {
  330.                 CRY_PFX2_ASSERT(container.HasData(EPDT_Size));
  331.                 const bool isAfterWater = (pSpritesContext->m_renderFlags & FOB_AFTER_WATER) != 0;
  332.                 const bool isCameraUnderWater = pSpritesContext->m_camInfo.bCameraUnderwater;
  333.  
  334.                 Plane waterPlane;
  335.                 const float clipWaterSign = (isCameraUnderWater == isAfterWater) ? -1.0f : 1.0f;
  336.                 const float offsetMult = isAfterWater ? 2.0f : 0.0f;
  337.                 const uint count = pSpritesContext->m_numSprites;
  338.  
  339.                 for (uint i = 0, j = 0; i < count; ++i)
  340.                 {
  341.                         TParticleId particleId = particleIds[i];
  342.  
  343.                         const float radius = sizes.Load(particleId) * 0.5f;
  344.                         const Vec3 position = positions.Load(particleId);
  345.                         const float distToWaterPlane = pSpritesContext->m_physEnviron.GetWaterPlane(waterPlane, position, radius);
  346.                         const float waterDist = MAdd(radius, offsetMult, distToWaterPlane) * clipWaterSign;
  347.                         const float waterAlpha = saturate(waterDist * rcp_fast(radius));
  348.                         spriteAlphas[particleId] *= waterAlpha;
  349.  
  350.                         if (waterAlpha > 0.0f)
  351.                                 particleIds[j++] = particleId;
  352.                         else
  353.                                 --pSpritesContext->m_numSprites;
  354.                 }
  355.         }
  356. }
  357.  
  358. void CFeatureRenderSprites::SortSprites(SSpritesContext* pSpritesContext)
  359. {
  360.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  361.  
  362.         if (m_sortMode == ESortMode::None || GetCVars()->e_ParticlesSortQuality == 0)
  363.                 return;
  364.  
  365.         uint32 threadId = JobManager::GetWorkerThreadId();
  366.         TParticleHeap& memHeap = GetPSystem()->GetMemHeap(threadId);
  367.         const uint numSprites = pSpritesContext->m_numSprites;
  368.  
  369.         TParticleHeap::Array<uint32, uint, CRY_PFX2_PARTICLES_ALIGNMENT> indices(memHeap, numSprites);
  370.         TParticleHeap::Array<float, uint, CRY_PFX2_PARTICLES_ALIGNMENT> keys(memHeap, numSprites);
  371.         auto& particleIds = pSpritesContext->m_particleIds;
  372.  
  373.         const CParticleContainer& container = pSpritesContext->m_context.m_container;
  374.         const bool byAge = (m_sortMode == ESortMode::NewToOld) || (m_sortMode == ESortMode::OldToNew);
  375.         const bool byDistance = (m_sortMode == ESortMode::FrontToBack) || (m_sortMode == ESortMode::BackToFront);
  376.         const bool invertKey = (m_sortMode == ESortMode::OldToNew) || (m_sortMode == ESortMode::FrontToBack);
  377.  
  378.         if (byAge)
  379.         {
  380.                 CRY_PFX2_ASSERT(container.HasData(EPDT_NormalAge));
  381.                 CRY_PFX2_ASSERT(container.HasData(EPDT_LifeTime));
  382.                 IFStream ages = container.GetIFStream(EPDT_NormalAge);
  383.                 IFStream lifeTimes = container.GetIFStream(EPDT_LifeTime);
  384.  
  385.                 for (size_t i = 0; i < numSprites; ++i)
  386.                 {
  387.                         const TParticleId particleId = particleIds[i];
  388.                         const float age = ages.Load(particleId) * lifeTimes.Load(particleId);
  389.                         keys[i] = age;
  390.                 }
  391.         }
  392.         else if (byDistance)
  393.         {
  394.                 IVec3Stream positions = container.GetIVec3Stream(EPVF_Position);
  395.  
  396.                 Vec3 camPos = pSpritesContext->m_camInfo.pCamera->GetPosition();
  397.                 for (size_t i = 0; i < numSprites; ++i)
  398.                 {
  399.                         const TParticleId particleId = particleIds[i];
  400.                         const Vec3 pPos = positions.Load(particleId);
  401.                         const float dist = rcp_fast(camPos.GetSquaredDistance(pPos));
  402.                         keys[i] = dist;
  403.                 }
  404.         }
  405.         if (invertKey)
  406.         {
  407.                 for (size_t i = 0; i < numSprites; ++i)
  408.                         keys[i] = rcp_fast(keys[i]);
  409.         }
  410.  
  411.         RadixSort(indices.begin(), indices.end(), keys.begin(), keys.end(), memHeap);
  412.  
  413.         for (size_t i = 0; i < numSprites; ++i)
  414.                 indices[i] = particleIds[indices[i]];
  415.         memcpy(particleIds.data(), indices.data(), sizeof(uint32) * indices.size());
  416. }
  417.  
  418. void CFeatureRenderSprites::WriteToGPUMem(const SSpritesContext& spritesContext)
  419. {
  420.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  421.  
  422.         const CParticleContainer& container = spritesContext.m_context.m_container;
  423.         const bool hasAngles2D = container.HasData(EPDT_Angle2D);
  424.         const bool hasColors = container.HasData(EPDT_Color);
  425.         const bool hasTiling = container.HasData(EPDT_Tile);
  426.         const bool hasAnimation = spritesContext.m_params.m_textureAnimation.IsAnimating();
  427.         const uint numSprites = spritesContext.m_numSprites;
  428.  
  429.         SRenderVertices* pRenderVertices = spritesContext.m_pRE->AllocPullVertices(numSprites);
  430.  
  431.         WritePositions(spritesContext, pRenderVertices->aPositions);
  432.         if (hasAngles2D)
  433.                 WriteAxes<true>(spritesContext, pRenderVertices->aAxes);
  434.         else
  435.                 WriteAxes<false>(spritesContext, pRenderVertices->aAxes);
  436.  
  437.         switch (hasColors + hasTiling * 2 + hasAnimation * 4)
  438.         {
  439.         case 0:
  440.                 WriteColorSTs<false, false, false>(spritesContext, pRenderVertices->aColorSTs);
  441.                 break;
  442.         case 1:
  443.                 WriteColorSTs<true, false, false>(spritesContext, pRenderVertices->aColorSTs);
  444.                 break;
  445.         case 2:
  446.                 WriteColorSTs<false, true, false>(spritesContext, pRenderVertices->aColorSTs);
  447.                 break;
  448.         case 3:
  449.                 WriteColorSTs<true, true, false>(spritesContext, pRenderVertices->aColorSTs);
  450.                 break;
  451.         case 4:
  452.                 WriteColorSTs<false, false, true>(spritesContext, pRenderVertices->aColorSTs);
  453.                 break;
  454.         case 5:
  455.                 WriteColorSTs<true, false, true>(spritesContext, pRenderVertices->aColorSTs);
  456.                 break;
  457.         case 6:
  458.                 WriteColorSTs<false, true, true>(spritesContext, pRenderVertices->aColorSTs);
  459.                 break;
  460.         case 7:
  461.                 WriteColorSTs<true, true, true>(spritesContext, pRenderVertices->aColorSTs);
  462.                 break;
  463.         }
  464. }
  465.  
  466. void CFeatureRenderSprites::WritePositions(const SSpritesContext& spritesContext, FixedDynArray<Vec3>& gpuPositions)
  467. {
  468.         CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  469.  
  470.         const CParticleContainer& container = spritesContext.m_context.m_container;
  471.         IVec3Stream positions = container.GetIVec3Stream(EPVF_Position);
  472.         const auto& particleIds = spritesContext.m_particleIds;
  473.         CWriteCombinedBuffer<Vec3, vertexBufferSize, vertexChunckSize> wcPositions(gpuPositions);
  474.         const uint numSprites = spritesContext.m_numSprites;
  475.  
  476.         const uint spritesPerChunk = vertexChunckSize / sizeof(Vec3);
  477.         const uint numChunks = (numSprites / spritesPerChunk) + 1;
  478.         for (uint chunk = 0, spriteIdx = 0; chunk < numChunks; ++chunk)
  479.         {
  480.                 const uint chunkSprites = min(spritesPerChunk, numSprites - chunk * spritesPerChunk);
  481.                 if (!wcPositions.CheckAvailable(chunkSprites))
  482.                         break;
  483.  
  484.                 for (uint sprite = 0; sprite < chunkSprites; ++sprite, ++spriteIdx)
  485.                 {
  486.                         const TParticleId particleId = particleIds[spriteIdx];
  487.                         const Vec3 position = positions.Load(particleId);
  488.                         wcPositions.Array().push_back(position);
  489.                 }
  490.         }
  491. }
  492.  
  493. class CSpriteFacingModeScreen
  494. {
  495. public:
  496.         CSpriteFacingModeScreen(const CParticleContainer& container, const CCamera& camera)
  497.                 : m_sizes(container.GetIFStream(EPDT_Size))
  498.         {
  499.                 Matrix34 viewTM = camera.GetMatrix();
  500.                 m_xAxis = viewTM.GetColumn0();
  501.                 m_yAxis = -viewTM.GetColumn2();
  502.         }
  503.  
  504.         ILINE SParticleAxes Sample(TParticleId particleId) const
  505.         {
  506.                 SParticleAxes axes;
  507.                 const float size = m_sizes.Load(particleId);
  508.                 axes.xAxis = m_xAxis * size;
  509.                 axes.yAxis = m_yAxis * size;
  510.                 return axes;
  511.         }
  512.  
  513. private:
  514.         const IFStream m_sizes;
  515.         Vec3           m_xAxis;
  516.         Vec3           m_yAxis;
  517. };
  518.  
  519. class CSpriteFacingModeCamera
  520. {
  521. public:
  522.         CSpriteFacingModeCamera(const CParticleContainer& container, const CCamera& camera)
  523.                 : m_positions(container.GetIVec3Stream(EPVF_Position))
  524.                 , m_sizes(container.GetIFStream(EPDT_Size))
  525.                 , m_cameraPosition(camera.GetPosition()) {}
  526.  
  527.         ILINE SParticleAxes Sample(TParticleId particleId) const
  528.         {
  529.                 SParticleAxes axes;
  530.                 const Vec3 particlePosition = m_positions.Load(particleId);
  531.                 const float size = m_sizes.Load(particleId);
  532.  
  533.                 const Vec3 up = Vec3(0.0f, 0.0f, 1.0f);
  534.                 const Vec3 normal = particlePosition - m_cameraPosition;
  535.                 axes.xAxis = -up.Cross(normal).GetNormalized() * size;
  536.                 axes.yAxis = -axes.xAxis.Cross(normal).GetNormalized() * size;
  537.  
  538.                 return axes;
  539.         }
  540.  
  541. private:
  542.         const IVec3Stream m_positions;
  543.         const IFStream    m_sizes;
  544.         Vec3              m_cameraPosition;
  545. };
  546.  
  547. class CSpriteFacingModeVelocity
  548. {
  549. public:
  550.         CSpriteFacingModeVelocity(const CParticleContainer& container, const CCamera& camera, float axisScale)
  551.                 : m_positions(container.GetIVec3Stream(EPVF_Position))
  552.                 , m_velocities(container.GetIVec3Stream(EPVF_Velocity))
  553.                 , m_sizes(container.GetIFStream(EPDT_Size))
  554.                 , m_cameraPosition(camera.GetPosition())
  555.                 , m_cameraXAxis(camera.GetMatrix().GetColumn0())
  556.                 , m_axisScale(axisScale) {}
  557.  
  558.         ILINE SParticleAxes Sample(TParticleId particleId) const
  559.         {
  560.                 SParticleAxes axes;
  561.                 const Vec3 particlePosition = m_positions.Load(particleId);
  562.                 const Vec3 particleVelocity = m_velocities.Load(particleId);
  563.                 const float size = m_sizes.Load(particleId);
  564.  
  565.                 const Vec3 moveDirection = particleVelocity.GetNormalizedSafe(m_cameraXAxis);
  566.                 const Vec3 normal = (particlePosition - m_cameraPosition).GetNormalized();
  567.                 const float axisSize = max(size, particleVelocity.GetLength() * m_axisScale);
  568.                 axes.xAxis = moveDirection * axisSize;
  569.                 axes.yAxis = -moveDirection.Cross(normal) * size;
  570.  
  571.                 return axes;
  572.         }
  573.  
  574. private:
  575.         const IVec3Stream m_positions;
  576.         const IVec3Stream m_velocities;
  577.         const IFStream    m_sizes;
  578.         Vec3              m_cameraPosition;
  579.         Vec3              m_cameraXAxis;
  580.         float             m_axisScale;
  581. };
  582.  
  583. class CSpriteFacingModeFree
  584. {
  585. public:
  586.         CSpriteFacingModeFree(const CParticleContainer& container)
  587.                 : m_orientations(container.GetIQuatStream(EPQF_Orientation))
  588.                 , m_sizes(container.GetIFStream(EPDT_Size)) {}
  589.  
  590.         ILINE SParticleAxes Sample(TParticleId particleId) const
  591.         {
  592.                 SParticleAxes axes;
  593.                 const Quat orientation = m_orientations.Load(particleId);
  594.                 const float size = m_sizes.Load(particleId);
  595.                 axes.xAxis = orientation.GetColumn0() * size;
  596.                 axes.yAxis = -orientation.GetColumn1() * size;
  597.                 return axes;
  598.         }
  599.  
  600. private:
  601.         const IQuatStream m_orientations;
  602.         const IFStream    m_sizes;
  603. };
  604.  
  605. template<const bool hasAngles2D>
  606. void CFeatureRenderSprites::WriteAxes(const SSpritesContext& spritesContext, FixedDynArray<SParticleAxes>& gpuAxes)
  607. {
  608.         CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  609.  
  610.         const CParticleContainer& container = spritesContext.m_context.m_container;
  611.         const CCamera& camera = *spritesContext.m_camInfo.pCamera;
  612.  
  613.         switch (m_facingMode)
  614.         {
  615.         case EFacingMode::Screen:
  616.                 WriteAxes<CSpriteFacingModeScreen, hasAngles2D>(spritesContext, gpuAxes, CSpriteFacingModeScreen(container, camera));
  617.                 break;
  618.         case EFacingMode::Camera:
  619.                 WriteAxes<CSpriteFacingModeCamera, hasAngles2D>(spritesContext, gpuAxes, CSpriteFacingModeCamera(container, camera));
  620.                 break;
  621.         case EFacingMode::Velocity:
  622.                 WriteAxes<CSpriteFacingModeVelocity, hasAngles2D>(spritesContext, gpuAxes, CSpriteFacingModeVelocity(container, camera, m_axisScale));
  623.                 break;
  624.         case EFacingMode::Free:
  625.                 WriteAxes<CSpriteFacingModeFree, hasAngles2D>(spritesContext, gpuAxes, CSpriteFacingModeFree(container));
  626.                 break;
  627.         }
  628. }
  629.  
  630. template<typename TAxesSampler, const bool hasAngles2D>
  631. void CFeatureRenderSprites::WriteAxes(const SSpritesContext& spritesContext, FixedDynArray<SParticleAxes>& gpuAxes, const TAxesSampler& axesSampler)
  632. {
  633.         const CParticleContainer& container = spritesContext.m_context.m_container;
  634.         IFStream angles = container.GetIFStream(EPDT_Angle2D, 0.0f);
  635.         const auto& particleIds = spritesContext.m_particleIds;
  636.         CWriteCombinedBuffer<SParticleAxes, vertexBufferSize, vertexChunckSize> wcAxes(gpuAxes);
  637.         const uint numSprites = spritesContext.m_numSprites;
  638.         const float flipU = m_flipU ? -1.0f : 1.0f;
  639.         const float flipV = m_flipV ? -1.0f : 1.0f;
  640.  
  641.         const uint spritesPerChunk = vertexChunckSize / sizeof(SParticleAxes);
  642.         const uint numChunks = (numSprites / spritesPerChunk) + 1;
  643.         for (uint chunk = 0, spriteIdx = 0; chunk < numChunks; ++chunk)
  644.         {
  645.                 const uint chunkSprites = min(spritesPerChunk, numSprites - chunk * spritesPerChunk);
  646.                 if (!wcAxes.CheckAvailable(chunkSprites))
  647.                         break;
  648.  
  649.                 for (uint sprite = 0; sprite < chunkSprites; ++sprite, ++spriteIdx)
  650.                 {
  651.                         const TParticleId particleId = particleIds[spriteIdx];
  652.  
  653.                         SParticleAxes axes = axesSampler.Sample(particleId);
  654.                         if (hasAngles2D)
  655.                         {
  656.                                 const float angle = angles.Load(particleId);
  657.                                 RotateAxes(&axes.xAxis, &axes.yAxis, angle);
  658.                         }
  659.                         axes.xAxis *= m_aspectRatio * flipU;
  660.                         axes.yAxis *= flipV;
  661.  
  662.                         wcAxes.Array().push_back(axes);
  663.                 }
  664.         }
  665. }
  666.  
  667. template<bool hasColors, bool hasTiling, bool hasAnimation>
  668. void CFeatureRenderSprites::WriteColorSTs(const SSpritesContext& spritesContext, FixedDynArray<SParticleColorST>& gpuColorSTs)
  669. {
  670.         CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  671.  
  672.         const SComponentParams& params = spritesContext.m_params;
  673.         const CParticleContainer& container = spritesContext.m_context.m_container;
  674.         const uint numSprites = spritesContext.m_numSprites;
  675.         const auto& particleIds = spritesContext.m_particleIds;
  676.         const auto& spriteAlphas = spritesContext.m_spriteAlphas;
  677.         IFStream ages = container.GetIFStream(EPDT_NormalAge);
  678.         IFStream lifetimes = container.GetIFStream(EPDT_LifeTime);
  679.         IFStream alphas = container.GetIFStream(EPDT_Alpha, 1.0f);
  680.         IColorStream colors = container.GetIColorStream(EPDT_Color);
  681.         TIStream<uint8> tiles = container.GetTIStream<uint8>(EPDT_Tile);
  682.         CWriteCombinedBuffer<SParticleColorST, vertexBufferSize, vertexChunckSize> wcColorSTs(gpuColorSTs);
  683.  
  684.         const bool hasAbsFrameRate = params.m_textureAnimation.HasAbsoluteFrameRate();
  685.  
  686.         const uint spritesPerChunk = vertexChunckSize / sizeof(SParticleColorST);
  687.         const uint numChunks = (numSprites / spritesPerChunk) + 1;
  688.  
  689.         SParticleColorST colorSTDefault;
  690.         colorSTDefault.st.dcolor = 0;
  691.         colorSTDefault.st.z = uint8(params.m_shaderData.m_firstTile);
  692.         colorSTDefault.color.dcolor = ~0;
  693.  
  694.         for (uint chunk = 0, spriteIdx = 0; chunk < numChunks; ++chunk)
  695.         {
  696.                 const uint chunkSprites = min(spritesPerChunk, numSprites - chunk * spritesPerChunk);
  697.                 if (!wcColorSTs.CheckAvailable(chunkSprites))
  698.                         break;
  699.  
  700.                 for (uint sprite = 0; sprite < chunkSprites; ++sprite, ++spriteIdx)
  701.                 {
  702.                         const TParticleId particleId = particleIds[spriteIdx];
  703.  
  704.                         SParticleColorST colorST = colorSTDefault;
  705.  
  706.                         if (hasTiling)
  707.                                 colorST.st.z += tiles.Load(particleId);
  708.  
  709.                         if (hasAnimation)
  710.                         {
  711.                                 float age = ages.Load(particleId);
  712.                                 float animPos = hasAbsFrameRate ?
  713.                                                 params.m_textureAnimation.GetAnimPosAbsolute(age * lifetimes.Load(particleId))
  714.                                                 : params.m_textureAnimation.GetAnimPosRelative(age);
  715.  
  716.                                 colorST.st.z += int(animPos);
  717.                                 colorST.st.w = FloatToUFrac8Saturate(animPos - int(animPos));
  718.                         }
  719.  
  720.                         if (hasColors)
  721.                                 colorST.color = colors.Load(particleId);
  722.                         colorST.color.a = FloatToUFrac8Saturate(spriteAlphas[particleId]);
  723.  
  724.                         wcColorSTs.Array().push_back(colorST);
  725.                 }
  726.         }
  727. }
  728.  
  729. }
  730.  
downloadFeatureRenderSprites.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