BVB Source Codes

CRYENGINE Show FeatureRenderRibbon.cpp Source code

Return Download CRYENGINE: download FeatureRenderRibbon.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  Created:     04/05/2015 by Filipe amim
  5. //  Description:
  6. // -------------------------------------------------------------------------
  7. //
  8. ////////////////////////////////////////////////////////////////////////////
  9.  
  10. #include "StdAfx.h"
  11. #include "ParticleSystem/ParticleRender.h"
  12. #include "ParticleSystem/ParticleEmitter.h"
  13. #include <CryMath/RadixSort.h>
  14.  
  15. CRY_PFX2_DBG
  16.  
  17. namespace pfx2
  18. {
  19.  
  20.  
  21. EParticleDataType PDT(EPDT_RibbonId, TParticleId);
  22.  
  23. extern EParticleDataType EPDT_Alpha, EPDT_Color;
  24.  
  25.  
  26. SERIALIZATION_DECLARE_ENUM(ERibbonMode,
  27.                            Camera,
  28.                            Free
  29.                            )
  30.  
  31. SERIALIZATION_DECLARE_ENUM(ERibbonStreamSource,
  32.                            Age,
  33.                            Spawn
  34.                            )
  35.  
  36.  
  37. EParticleDataType DataType(ERibbonStreamSource source)
  38. {
  39.         return source == ERibbonStreamSource::Spawn ? EPDT_SpawnFraction : EPDT_NormalAge;
  40. }
  41.  
  42. class CFeatureRenderRibbon : public CParticleRenderBase
  43. {
  44. private:
  45.         typedef SParticleAxes (CFeatureRenderRibbon::* AxesFn)(CParticleComponentRuntime* pComponentRuntime, TParticleId particleId, const CCamera& camera, Vec3 movingPositions[3]);
  46.  
  47.         struct SRibbon
  48.         {
  49.                 uint m_firstIdx;
  50.                 uint m_lastIdx;
  51.         };
  52.  
  53. public:
  54.         typedef CParticleRenderBase           BaseClass;
  55.         typedef TParticleHeap::Array<SRibbon> TRibbons;
  56.  
  57. public:
  58.         CRY_PFX2_DECLARE_FEATURE
  59.  
  60.         CFeatureRenderRibbon();
  61.  
  62.         virtual void AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams) override;
  63.         virtual void Serialize(Serialization::IArchive& ar) override;
  64.         virtual void InitParticles(const SUpdateContext& context) override;
  65.         virtual void ComputeVertices(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, uint64 uRenderFlags, float fMaxPixels) override;
  66.  
  67. private:
  68.         void             MakeRibbons(CParticleComponentRuntime* pComponentRuntime, TParticleIdArray* pSortEntries, TRibbons* pRibbons, uint* pNumVertices);
  69.         void             WriteToGPUMem(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, const TParticleIdArray& pSortEntries, const TRibbons& pRibbons, uint numVertices);
  70.         template<typename TAxesSampler>
  71.         void             WriteToGPUMem(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, const TParticleIdArray& pSortEntries, const TRibbons& pRibbons, const TAxesSampler& axesSampler, uint numVertices);
  72.  
  73.         SParticleColorST VertexColorST(CParticleComponentRuntime* pComponentRuntime, TParticleId particleId, uint frameId, float animPos);
  74.  
  75.         SFloat              m_sortBias;
  76.         ERibbonMode         m_ribbonMode;
  77.         ERibbonStreamSource m_streamSource;
  78.         UFloat10            m_frequency;
  79.         bool                m_connectToOrigin;
  80. };
  81.  
  82. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureRenderRibbon, "Render", "Ribbon", colorRender);
  83.  
  84. CFeatureRenderRibbon::CFeatureRenderRibbon()
  85.         : m_ribbonMode(ERibbonMode::Camera)
  86.         , m_streamSource(ERibbonStreamSource::Age)
  87.         , m_connectToOrigin(false)
  88.         , m_frequency(1.0f)
  89.         , m_sortBias(0.0f)
  90. {
  91. }
  92.  
  93. void CFeatureRenderRibbon::AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams)
  94. {
  95.         BaseClass::AddToComponent(pComponent, pParams);
  96.         CParticleComponent* pParent = pComponent->GetParentComponent();
  97.         pComponent->AddToUpdateList(EUL_InitUpdate, this);
  98.         pComponent->AddParticleData(EPDT_ParentId);
  99.         pComponent->AddParticleData(EPDT_SpawnId);
  100.         if (pParent)
  101.                 pParent->AddParticleData(EPDT_SpawnId);
  102.         pComponent->AddParticleData(EPDT_RibbonId);
  103.         pComponent->AddParticleData(EPDT_Size);
  104.         pComponent->AddParticleData(EPDT_NormalAge);
  105.         pParams->m_shaderData.m_expansion[1] = 0.0f;
  106.         pParams->m_particleObjFlags |= CREParticle::ePOF_USE_VERTEX_PULL_MODEL;
  107.         pParams->m_renderObjectSortBias = m_sortBias;
  108.         if (m_ribbonMode == ERibbonMode::Free)
  109.                 pComponent->AddParticleData(EPQF_Orientation);
  110.         pComponent->AddParticleData(DataType(m_streamSource));
  111.         pParams->m_shaderData.m_textureFrequency = m_frequency;
  112. }
  113.  
  114. void CFeatureRenderRibbon::Serialize(Serialization::IArchive& ar)
  115. {
  116.         BaseClass::Serialize(ar);
  117.         ar(m_ribbonMode, "RibbonMode", "Ribbon Mode");
  118.         ar(m_streamSource, "StreamSource", "Stream Source");
  119.         ar(m_sortBias, "SortBias", "Sort Bias");
  120.         ar(m_connectToOrigin, "ConnectToOrigin", "Connect To Origin");
  121.         ar(m_frequency, "TextureFrequency", "Texture Frequency");
  122. }
  123.  
  124. void CFeatureRenderRibbon::InitParticles(const SUpdateContext& context)
  125. {
  126.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  127.  
  128.         CParticleContainer& container = context.m_container;
  129.         CParticleContainer& parentContainer = context.m_parentContainer;
  130.         IOUintStream ribbonIds = container.GetIOUintStream(EPDT_RibbonId);
  131.         IPidStream parentIds = container.GetIPidStream(EPDT_ParentId);
  132.         IUintStream parentSpawnIds = parentContainer.GetIUintStream(EPDT_SpawnId, 0);
  133.  
  134.         CRY_PFX2_FOR_SPAWNED_PARTICLES(context)
  135.         {
  136.                 const TParticleId parentId = parentIds.Load(particleId);
  137.                 const uint32 parentSpawnId = parentSpawnIds.SafeLoad(parentId);
  138.                 ribbonIds.Store(particleId, parentSpawnId);
  139.         }
  140.         CRY_PFX2_FOR_END;
  141. }
  142.  
  143. void CFeatureRenderRibbon::ComputeVertices(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, uint64 uRenderFlags, float fMaxPixels)
  144. {
  145.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  146.         PARTICLE_LIGHT_PROFILER();
  147.  
  148.         const uint32 threadId = JobManager::GetWorkerThreadId();
  149.         auto& memHep = GetPSystem()->GetMemHeap(threadId);
  150.         const CParticleContainer& container = pComponentRuntime->GetContainer();
  151.         const TParticleId lastParticleId = container.GetLastParticleId();
  152.  
  153.         if (lastParticleId == 0)
  154.                 return;
  155.  
  156.         uint numVertices;
  157.         TParticleIdArray sortEntries(memHep, lastParticleId);
  158.         TRibbons ribbons(memHep);
  159.         MakeRibbons(pComponentRuntime, &sortEntries, &ribbons, &numVertices);
  160.         WriteToGPUMem(pComponentRuntime, camInfo, pRE, sortEntries, ribbons, numVertices);
  161.  
  162.         int totalRenderedParticles = 0;
  163.         for (uint ribbonId = 0; ribbonId < uint(ribbons.size()); ++ribbonId)
  164.                 totalRenderedParticles += ribbons[ribbonId].m_lastIdx - ribbons[ribbonId].m_firstIdx;
  165.         pComponentRuntime->GetEmitter()->AddDrawCallCounts(totalRenderedParticles, 0);
  166.         GetPSystem()->GetProfiler().AddEntry(pComponentRuntime, EPS_RendereredParticles, uint(totalRenderedParticles));
  167. }
  168.  
  169. void CFeatureRenderRibbon::MakeRibbons(CParticleComponentRuntime* pComponentRuntime, TParticleIdArray* pSortEntries, TRibbons* pRibbons, uint* pNumVertices)
  170. {
  171.         CRY_PFX2_PROFILE_DETAIL;
  172.  
  173.         const uint32 threadId = JobManager::GetWorkerThreadId();
  174.         auto& memHep = GetPSystem()->GetMemHeap(threadId);
  175.         const SUpdateContext context = SUpdateContext(pComponentRuntime);
  176.         const CParticleContainer& container = pComponentRuntime->GetContainer();
  177.         const IUintStream ribbonIds = container.GetIUintStream(EPDT_RibbonId);
  178.         const IUintStream spawnIds = container.GetIUintStream(EPDT_SpawnId);
  179.         const TIStream<uint8> states = container.GetTIStream<uint8>(EPDT_State);
  180.         const TParticleId lastParticleId = container.GetLastParticleId();
  181.         uint numValidParticles = 0;
  182.  
  183.         {
  184.                 const uint64 noKey = uint64(-1);
  185.                 TParticleHeap::Array<uint64, uint, CRY_PFX2_PARTICLES_ALIGNMENT> sortEntries(memHep, lastParticleId);
  186.                 CRY_PFX2_FOR_ACTIVE_PARTICLES(context)
  187.                 {
  188.                         const TParticleId ribbonId = ribbonIds.Load(particleId);
  189.                         const uint32 spawnId = spawnIds.Load(particleId);
  190.                         const uint64 key = (uint64(ribbonId) << 32) | uint64(spawnId);
  191.                         const uint8 state = states.Load(particleId);
  192.                         const bool valid = (state & ESB_Dead) == 0;
  193.                         numValidParticles += uint(valid);
  194.                         sortEntries[particleId] = valid ? key : noKey;
  195.                 }
  196.                 CRY_PFX2_FOR_END;
  197.                 RadixSort(
  198.                   pSortEntries->begin(), pSortEntries->end(),
  199.                   sortEntries.begin(), sortEntries.end(), memHep);
  200.         }
  201.  
  202.         uint ribbonCount = 0;
  203.         uint lastRibbonId = ribbonIds.Load((*pSortEntries)[0]);
  204.         SRibbon ribbon;
  205.         ribbon.m_firstIdx = 0;
  206.         ribbon.m_lastIdx = 0;
  207.         for (; ribbon.m_lastIdx < numValidParticles; ++ribbon.m_lastIdx)
  208.         {
  209.                 const TParticleId particleId = (*pSortEntries)[ribbon.m_lastIdx];
  210.                 const TParticleId ribbonId = ribbonIds.Load(particleId);
  211.                 if (ribbonId != lastRibbonId)
  212.                 {
  213.                         if ((ribbon.m_lastIdx - ribbon.m_firstIdx) >= 2)
  214.                                 ++ribbonCount;
  215.                         ribbon.m_firstIdx = ribbon.m_lastIdx;
  216.                 }
  217.                 lastRibbonId = ribbonId;
  218.         }
  219.         if (ribbon.m_lastIdx - ribbon.m_firstIdx >= 2)
  220.                 ++ribbonCount;
  221.         pRibbons->reserve(ribbonCount);
  222.         ribbon.m_firstIdx = 0;
  223.         ribbon.m_lastIdx = 0;
  224.         for (; ribbon.m_lastIdx < numValidParticles; ++ribbon.m_lastIdx)
  225.         {
  226.                 const TParticleId particleId = (*pSortEntries)[ribbon.m_lastIdx];
  227.                 const TParticleId ribbonId = ribbonIds.Load(particleId);
  228.                 if (ribbonId != lastRibbonId)
  229.                 {
  230.                         if ((ribbon.m_lastIdx - ribbon.m_firstIdx) >= 2)
  231.                                 pRibbons->push_back(ribbon);
  232.                         ribbon.m_firstIdx = ribbon.m_lastIdx;
  233.                 }
  234.                 lastRibbonId = ribbonId;
  235.         }
  236.         if (ribbon.m_lastIdx - ribbon.m_firstIdx >= 2)
  237.                 pRibbons->push_back(ribbon);
  238.  
  239.         *pNumVertices = 0;
  240.         for (uint ribbonId = 0; ribbonId < uint(pRibbons->size()); ++ribbonId)
  241.         {
  242.                 const SRibbon ribbon = (*pRibbons)[ribbonId];
  243.                 const uint numSegments = ribbon.m_lastIdx - ribbon.m_firstIdx;
  244.                 *pNumVertices += numSegments + 1;
  245.                 if (m_connectToOrigin)
  246.                         ++*pNumVertices;
  247.         }
  248. }
  249.  
  250. class CRibbonAxesCamera
  251. {
  252. public:
  253.         CRibbonAxesCamera(const CParticleContainer& container, const CCamera& camera)
  254.                 : m_sizes(container.GetIFStream(EPDT_Size))
  255.                 , m_cameraPosition(camera.GetPosition()) {}
  256.  
  257.         ILINE SParticleAxes Sample(TParticleId particleId, Vec3 movingPositions[3]) const
  258.         {
  259.                 SParticleAxes axes;
  260.                 const float size = m_sizes.Load(particleId);
  261.                 const Vec3 front = movingPositions[1] - m_cameraPosition;
  262.                 const Vec3 dir0 = movingPositions[0] - movingPositions[1];
  263.                 const Vec3 dir1 = movingPositions[1] - movingPositions[2];
  264.                 const Vec3 up0 = dir0.Cross(front);
  265.                 const Vec3 up1 = dir1.Cross(front);
  266.                 const Vec3 up = (up0 + up1).GetNormalized();
  267.                 const Vec3 right = up.Cross(front).GetNormalized();
  268.  
  269.                 axes.xAxis = up * size;
  270.                 axes.yAxis = right * size;
  271.  
  272.                 return axes;
  273.         }
  274.  
  275. private:
  276.         const IFStream m_sizes;
  277.         Vec3           m_cameraPosition;
  278. };
  279.  
  280. class CRibbonAxesFree
  281. {
  282. public:
  283.         CRibbonAxesFree(const CParticleContainer& container)
  284.                 : m_orientations(container.GetIQuatStream(EPQF_Orientation))
  285.                 , m_sizes(container.GetIFStream(EPDT_Size)) {}
  286.  
  287.         ILINE SParticleAxes Sample(TParticleId particleId, Vec3 movingPositions[3]) const
  288.         {
  289.                 SParticleAxes axes;
  290.                 const float size = m_sizes.Load(particleId);
  291.                 const Quat orientation = m_orientations.Load(particleId);
  292.  
  293.                 axes.xAxis = orientation.GetColumn0() * size;
  294.                 axes.yAxis = -orientation.GetColumn1() * size;
  295.  
  296.                 return axes;
  297.         }
  298.  
  299. private:
  300.         const IQuatStream m_orientations;
  301.         const IFStream    m_sizes;
  302. };
  303.  
  304. class CRibbonColorSTs
  305. {
  306. public:
  307.         CRibbonColorSTs(const CParticleContainer& container, ERibbonStreamSource streamSource)
  308.                 : m_colors(container.GetIColorStream(EPDT_Color))
  309.                 , m_stream(container.GetIFStream(DataType(streamSource)))
  310.                 , m_sizes(container.GetIFStream(EPDT_Size))
  311.                 , m_alphas(container.GetIFStream(EPDT_Alpha, 1.0f))
  312.                 , m_hasColors(container.HasData(EPDT_Color)) {}
  313.  
  314.         ILINE SParticleColorST Sample(TParticleId particleId, uint frameId, float animPos) const
  315.         {
  316.                 SParticleColorST colorST;
  317.                 const float alpha = m_alphas.SafeLoad(particleId);
  318.                 const float stream = m_stream.Load(particleId);
  319.  
  320.                 colorST.color.dcolor = ~0;
  321.                 if (m_hasColors)
  322.                         colorST.color = m_colors.Load(particleId);
  323.                 colorST.color.a = FloatToUFrac8Saturate(alpha);
  324.  
  325.                 colorST.st.dcolor = 0;
  326.                 colorST.st.x = 0;
  327.                 colorST.st.y = FloatToUFrac8Saturate(stream);
  328.                 colorST.st.z = frameId;
  329.                 colorST.st.w = FloatToUFrac8Saturate(animPos - int(animPos));
  330.  
  331.                 return colorST;
  332.         }
  333.  
  334. private:
  335.         const IColorStream m_colors;
  336.         const IFStream     m_sizes;
  337.         const IFStream     m_stream;
  338.         const IFStream     m_alphas;
  339.         const bool         m_hasColors;
  340. };
  341.  
  342. void CFeatureRenderRibbon::WriteToGPUMem(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, const TParticleIdArray& sortEntries, const TRibbons& ribbons, uint numVertices)
  343. {
  344.         CRY_PFX2_PROFILE_DETAIL;
  345.  
  346.         const CParticleContainer& container = pComponentRuntime->GetContainer();
  347.         const CCamera& camera = *camInfo.pCamera;
  348.  
  349.         if (m_ribbonMode == ERibbonMode::Camera)
  350.                 WriteToGPUMem<CRibbonAxesCamera>(pComponentRuntime, camInfo, pRE, sortEntries, ribbons, CRibbonAxesCamera(container, camera), numVertices);
  351.         else
  352.                 WriteToGPUMem<CRibbonAxesFree>(pComponentRuntime, camInfo, pRE, sortEntries, ribbons, CRibbonAxesFree(container), numVertices);
  353. }
  354.  
  355. template<typename TAxesSampler>
  356. ILINE void CFeatureRenderRibbon::WriteToGPUMem(CParticleComponentRuntime* pComponentRuntime, const SCameraInfo& camInfo, CREParticle* pRE, const TParticleIdArray& sortEntries, const TRibbons& ribbons, const TAxesSampler& axesSampler, uint numVertices)
  357. {
  358.         const SComponentParams& params = pComponentRuntime->GetComponentParams();
  359.         const CParticleContainer& container = pComponentRuntime->GetContainer();
  360.         const CParticleContainer& parentContainer = pComponentRuntime->GetParentContainer();
  361.  
  362.         const IVec3Stream parentPositions = parentContainer.GetIVec3Stream(EPVF_Position);
  363.         const IVec3Stream positions = container.GetIVec3Stream(EPVF_Position);
  364.         const IPidStream parentIds = container.GetIPidStream(EPDT_ParentId);
  365.         const IFStream parentAges = parentContainer.GetIFStream(EPDT_NormalAge);
  366.         const uint extraVertices = m_connectToOrigin ? 2 : 1;
  367.         const CRibbonColorSTs colorSTsSampler = CRibbonColorSTs(container, m_streamSource);
  368.  
  369.         SRenderVertices* pRenderVertices = pRE->AllocPullVertices(numVertices);
  370.         CWriteCombinedBuffer<Vec3, vertexBufferSize, vertexChunckSize> localPositions(pRenderVertices->aPositions);
  371.         CWriteCombinedBuffer<SParticleAxes, vertexBufferSize, vertexChunckSize> localAxes(pRenderVertices->aAxes);
  372.         CWriteCombinedBuffer<SParticleColorST, vertexBufferSize, vertexChunckSize> localColorSTs(pRenderVertices->aColorSTs);
  373.  
  374.         for (uint ribbonId = 0; ribbonId < uint(ribbons.size()); ++ribbonId)
  375.         {
  376.                 const SRibbon ribbon = ribbons[ribbonId];
  377.                 const uint numSegments = ribbon.m_lastIdx - ribbon.m_firstIdx;
  378.                 const uint numVertices = numSegments + extraVertices;
  379.                 if (!localPositions.CheckAvailable(numVertices) || !localAxes.CheckAvailable(numVertices) || !localColorSTs.CheckAvailable(numVertices))
  380.                         break;
  381.  
  382.                 Vec3 movingPositions[3] =
  383.                 {
  384.                         positions.Load(sortEntries[ribbon.m_firstIdx]),
  385.                         movingPositions[0],
  386.                         positions.Load(sortEntries[ribbon.m_firstIdx + 1])
  387.                 };
  388.  
  389.                 const TParticleId ribbonParentId = parentIds.Load(sortEntries[ribbon.m_firstIdx]);
  390.                 const float parentAge = ribbonParentId != gInvalidId ? parentAges.Load(ribbonParentId) : 1.0f;
  391.                 const float animPos = parentAge * float(params.m_shaderData.m_frameCount);
  392.                 const uint frameId = int(min(animPos, params.m_shaderData.m_frameCount - 1));
  393.  
  394.                 Vec3 position;
  395.                 SParticleAxes axes;
  396.                 SParticleColorST colorST;
  397.  
  398.                 for (uint i = ribbon.m_firstIdx; i < ribbon.m_lastIdx; ++i)
  399.                 {
  400.                         const TParticleId particleId = sortEntries[i];
  401.  
  402.                         position = movingPositions[1];
  403.  
  404.                         axes = axesSampler.Sample(particleId, movingPositions);
  405.                         colorST = colorSTsSampler.Sample(particleId, frameId, animPos);
  406.  
  407.                         localPositions.Array().push_back(position);
  408.                         localAxes.Array().push_back(axes);
  409.                         localColorSTs.Array().push_back(colorST);
  410.  
  411.                         movingPositions[0] = movingPositions[1];
  412.                         movingPositions[1] = movingPositions[2];
  413.                         if (i + 2 < ribbon.m_lastIdx)
  414.                                 movingPositions[2] = positions.Load(sortEntries[i + 2]);
  415.                 }
  416.  
  417.                 if (m_connectToOrigin)
  418.                 {
  419.                         if (ribbonParentId != gInvalidId)
  420.                                 position = parentPositions.Load(ribbonParentId);
  421.                         colorST.st.y = 0;
  422.                         colorST.st.w = 0;
  423.                         localPositions.Array().push_back(position);
  424.                         localAxes.Array().push_back(axes);
  425.                         localColorSTs.Array().push_back(colorST);
  426.                 }
  427.  
  428.                 colorST.st.x = 255;
  429.                 localPositions.Array().push_back(position);
  430.                 localAxes.Array().push_back(axes);
  431.                 localColorSTs.Array().push_back(colorST);
  432.         }
  433. }
  434.  
  435. }
  436.  
downloadFeatureRenderRibbon.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