Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
5.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: particle system code
  4. //
  5. //===========================================================================//
  6. #include <algorithm>
  7. #include "tier0/platform.h"
  8. #include "tier0/vprof.h"
  9. #include "particles/particles.h"
  10. #include "psheet.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. static ALIGN16 ParticleRenderData_t s_SortedIndexList[MAX_PARTICLES_IN_A_SYSTEM] ALIGN16_POST;
  14. enum EParticleSortKeyType
  15. {
  16. SORT_KEY_NONE,
  17. SORT_KEY_DISTANCE,
  18. SORT_KEY_CREATION_TIME,
  19. };
  20. template<EParticleSortKeyType eSortKeyMode> void s_GenerateData( Vector CameraPos, CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles )
  21. {
  22. fltx4 *pOutUnSorted = reinterpret_cast<fltx4 *>( s_SortedIndexList );
  23. C4VAttributeIterator pXYZ( PARTICLE_ATTRIBUTE_XYZ, pParticles );
  24. CM128AttributeIterator pCreationTimeStamp( PARTICLE_ATTRIBUTE_CREATION_TIME, pParticles );
  25. CM128AttributeIterator pAlpha( PARTICLE_ATTRIBUTE_ALPHA, pParticles );
  26. CM128AttributeIterator pAlpha2( PARTICLE_ATTRIBUTE_ALPHA2, pParticles );
  27. CM128AttributeIterator pRadius( PARTICLE_ATTRIBUTE_RADIUS, pParticles );
  28. int nParticles = pParticles->m_nActiveParticles;
  29. FourVectors EyePos;
  30. EyePos.DuplicateVector( CameraPos );
  31. fltx4 fl4AlphaVis = ReplicateX4( pVisibilityData->m_flAlphaVisibility );
  32. fltx4 fl4RadVis = ReplicateX4( pVisibilityData->m_flRadiusVisibility );
  33. // indexing. We will generate the index as float and use magicf2i to convert to integer
  34. fltx4 fl4OutIdx = g_SIMD_0123; // 0 1 2 3
  35. fl4OutIdx = AddSIMD( fl4OutIdx, Four_2ToThe23s); // fix as int
  36. bool bUseVis = pVisibilityData->m_bUseVisibility;
  37. bool bCameraBias = pVisibilityData->m_flCameraBias != 0.0f;
  38. fltx4 fl4Bias = ReplicateX4( pVisibilityData->m_flCameraBias );
  39. fltx4 fl4AlphaScale = ReplicateX4( 255.0 );
  40. do
  41. {
  42. fltx4 fl4X = pXYZ->x;
  43. fltx4 fl4Y = pXYZ->y;
  44. fltx4 fl4Z = pXYZ->z;
  45. fltx4 fl4SortKey;
  46. if ( eSortKeyMode == SORT_KEY_DISTANCE )
  47. {
  48. fltx4 Xdiff = SubSIMD( EyePos.x, fl4X );
  49. fltx4 Ydiff = SubSIMD( EyePos.y, fl4Y );
  50. fltx4 Zdiff = SubSIMD( EyePos.z, fl4Z );
  51. if ( bCameraBias )
  52. {
  53. FourVectors v4CameraBias;
  54. v4CameraBias.x = Xdiff;
  55. v4CameraBias.y = Ydiff;
  56. v4CameraBias.z = Zdiff;
  57. //v4CameraBias = VectorNormalizeFast( v4CameraBias );
  58. v4CameraBias.VectorNormalizeFast();
  59. v4CameraBias *= fl4Bias;
  60. fl4X = SubSIMD( fl4X, v4CameraBias.x );
  61. fl4Y = SubSIMD( fl4Y, v4CameraBias.y );
  62. fl4Z = SubSIMD( fl4Z, v4CameraBias.z );
  63. Xdiff = SubSIMD( EyePos.x, fl4X );
  64. Ydiff = SubSIMD( EyePos.y, fl4Y );
  65. Zdiff = SubSIMD( EyePos.z, fl4Z );
  66. }
  67. fl4SortKey = AddSIMD( MulSIMD( Xdiff, Xdiff ),
  68. AddSIMD( MulSIMD( Ydiff, Ydiff ),
  69. MulSIMD( Zdiff, Zdiff ) ) );
  70. }
  71. else
  72. {
  73. Assert ( eSortKeyMode == SORT_KEY_CREATION_TIME || eSortKeyMode == SORT_KEY_NONE );
  74. fl4SortKey = *pCreationTimeStamp;
  75. }
  76. fltx4 fl4FinalAlpha = MulSIMD( *pAlpha, *pAlpha2 );
  77. fltx4 fl4FinalRadius = *pRadius;
  78. if ( bUseVis )
  79. {
  80. fl4FinalAlpha = MaxSIMD ( Four_Zeros, MinSIMD( Four_Ones, MulSIMD( fl4FinalAlpha, fl4AlphaVis) ) );
  81. fl4FinalRadius = MulSIMD( fl4FinalRadius, fl4RadVis );
  82. }
  83. // convert float 0..1 to int 0..255
  84. fl4FinalAlpha = AddSIMD( MulSIMD( fl4FinalAlpha, fl4AlphaScale ), Four_2ToThe23s );
  85. // now, we will use simd transpose to write the output
  86. fltx4 i4Indices = AndSIMD( fl4OutIdx, LoadAlignedSIMD( (float *) g_SIMD_Low16BitsMask ) );
  87. TransposeSIMD( fl4SortKey, i4Indices, fl4FinalRadius, fl4FinalAlpha );
  88. pOutUnSorted[0] = fl4SortKey;
  89. pOutUnSorted[1] = i4Indices;
  90. pOutUnSorted[2] = fl4FinalRadius;
  91. pOutUnSorted[3] = fl4FinalAlpha;
  92. pOutUnSorted += 4;
  93. fl4OutIdx = AddSIMD( fl4OutIdx, Four_Fours );
  94. nParticles -= 4;
  95. ++pXYZ;
  96. ++pAlpha;
  97. ++pAlpha2;
  98. ++pRadius;
  99. } while( nParticles > 0 ); // we're not called with 0
  100. }
  101. #define TREATASINT(x) ( *( ( (int32 const *)( &(x) ) ) ) )
  102. static bool SortLessFunc( const ParticleRenderData_t &left, const ParticleRenderData_t &right )
  103. {
  104. return TREATASINT( left.m_flSortKey ) < TREATASINT( right.m_flSortKey );
  105. }
  106. void CParticleCollection::GenerateSortedIndexList( Vector vecCamera, CParticleVisibilityData *pVisibilityData, bool bSorted )
  107. {
  108. VPROF_BUDGET( "CParticleCollection::GenerateSortedIndexList", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  109. if ( bSorted )
  110. {
  111. s_GenerateData<SORT_KEY_DISTANCE>( vecCamera, pVisibilityData, this );
  112. }
  113. else
  114. s_GenerateData<SORT_KEY_NONE>( vecCamera, pVisibilityData, this );
  115. // check data
  116. #if 0
  117. bool bBad = false;
  118. for( int i = 0; i < m_nActiveParticles; i++ )
  119. {
  120. Assert( s_SortedIndexList[i].m_nIndex == i );
  121. if ( s_SortedIndexList[i].m_nIndex != i )
  122. bBad = true;
  123. }
  124. if ( bBad )
  125. {
  126. s_GenerateData<SORT_KEY_NONE>( vecCamera, pVisibilityData, this );
  127. }
  128. #endif
  129. #ifndef SWDS
  130. if ( bSorted )
  131. {
  132. // sort the output in place
  133. std::make_heap( s_SortedIndexList, s_SortedIndexList + m_nActiveParticles, SortLessFunc );
  134. std::sort_heap( s_SortedIndexList, s_SortedIndexList + m_nActiveParticles, SortLessFunc );
  135. }
  136. #endif
  137. }
  138. const ParticleRenderData_t *CParticleCollection::GetRenderList( IMatRenderContext *pRenderContext, bool bSorted, int *pNparticles, CParticleVisibilityData *pVisibilityData)
  139. {
  140. if ( bSorted )
  141. bSorted = m_pDef->m_bShouldSort;
  142. Vector vecCamera;
  143. pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
  144. *pNparticles = m_nActiveParticles;
  145. GenerateSortedIndexList( vecCamera, pVisibilityData, bSorted );
  146. return s_SortedIndexList+m_nActiveParticles;
  147. }