Counter Strike : Global Offensive Source Code
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.

339 lines
12 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // Functionality to render a glowing outline around client renderable objects.
  4. //
  5. //===============================================================================
  6. #ifndef GLOW_OUTLINE_EFFECT_H
  7. #define GLOW_OUTLINE_EFFECT_H
  8. #if defined( COMPILER_MSVC )
  9. #pragma once
  10. #endif
  11. #include "utlvector.h"
  12. #include "mathlib/vector.h"
  13. class C_BaseEntity;
  14. class CViewSetup;
  15. class CMatRenderContextPtr;
  16. static const int GLOW_FOR_ALL_SPLIT_SCREEN_SLOTS = -1;
  17. enum GlowRenderStyle_t
  18. {
  19. GLOWRENDERSTYLE_DEFAULT = 0,
  20. GLOWRENDERSTYLE_RIMGLOW3D,
  21. GLOWRENDERSTYLE_EDGE_HIGHLIGHT,
  22. GLOWRENDERSTYLE_EDGE_HIGHLIGHT_PULSE,
  23. GLOWRENDERSTYLE_COUNT,
  24. };
  25. class CGlowObjectManager
  26. {
  27. public:
  28. CGlowObjectManager() :
  29. m_nFirstFreeSlot( GlowObjectDefinition_t::END_OF_FREE_LIST )
  30. {
  31. }
  32. int RegisterGlowObject( C_BaseEntity *pEntity, const Vector &vGlowColor, float flGlowAlpha, bool bRenderWhenOccluded, bool bRenderWhenUnoccluded, int nSplitScreenSlot )
  33. {
  34. int nIndex;
  35. if ( m_nFirstFreeSlot == GlowObjectDefinition_t::END_OF_FREE_LIST )
  36. {
  37. nIndex = m_GlowObjectDefinitions.AddToTail();
  38. }
  39. else
  40. {
  41. nIndex = m_nFirstFreeSlot;
  42. m_nFirstFreeSlot = m_GlowObjectDefinitions[nIndex].m_nNextFreeSlot;
  43. }
  44. m_GlowObjectDefinitions[nIndex].m_flGlowPulseOverdrive = 0.0f;
  45. m_GlowObjectDefinitions[nIndex].m_bGlowAlphaCappedByRenderAlpha = false;
  46. m_GlowObjectDefinitions[nIndex].m_flGlowAlphaFunctionOfMaxVelocity = 0.0f;
  47. m_GlowObjectDefinitions[nIndex].m_flGlowAlphaMax = 1.0f;
  48. m_GlowObjectDefinitions[nIndex].m_pEntity = pEntity;
  49. m_GlowObjectDefinitions[nIndex].m_vGlowColor = vGlowColor;
  50. m_GlowObjectDefinitions[nIndex].m_flGlowAlpha = flGlowAlpha;
  51. m_GlowObjectDefinitions[nIndex].m_bRenderWhenOccluded = bRenderWhenOccluded;
  52. m_GlowObjectDefinitions[nIndex].m_bRenderWhenUnoccluded = bRenderWhenUnoccluded;
  53. m_GlowObjectDefinitions[nIndex].m_bFullBloomRender = false;
  54. m_GlowObjectDefinitions[nIndex].m_nFullBloomStencilTestValue = 0;
  55. m_GlowObjectDefinitions[nIndex].m_nSplitScreenSlot = nSplitScreenSlot;
  56. m_GlowObjectDefinitions[nIndex].m_nNextFreeSlot = GlowObjectDefinition_t::ENTRY_IN_USE;
  57. m_GlowObjectDefinitions[nIndex].m_nRenderStyle = GLOWRENDERSTYLE_DEFAULT;
  58. return nIndex;
  59. }
  60. int AddGlowBox( Vector vecOrigin, QAngle angOrientation, Vector mins, Vector maxs, Color colColor, float flLifetime )
  61. {
  62. int nIndex = m_GlowBoxDefinitions.AddToTail();
  63. m_GlowBoxDefinitions[nIndex].m_vPosition = vecOrigin;
  64. m_GlowBoxDefinitions[nIndex].m_angOrientation = angOrientation;
  65. m_GlowBoxDefinitions[nIndex].m_vMins = mins;
  66. m_GlowBoxDefinitions[nIndex].m_vMaxs = maxs;
  67. m_GlowBoxDefinitions[nIndex].m_colColor = colColor;
  68. m_GlowBoxDefinitions[nIndex].m_flBirthTimeIndex = gpGlobals->curtime;
  69. m_GlowBoxDefinitions[nIndex].m_flTerminationTimeIndex = gpGlobals->curtime + flLifetime;
  70. return nIndex;
  71. }
  72. void UnregisterGlowObject( int nGlowObjectHandle )
  73. {
  74. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  75. m_GlowObjectDefinitions[nGlowObjectHandle].m_nNextFreeSlot = m_nFirstFreeSlot;
  76. m_GlowObjectDefinitions[nGlowObjectHandle].m_pEntity = NULL;
  77. m_nFirstFreeSlot = nGlowObjectHandle;
  78. }
  79. void UnregisterGlowObject( C_BaseEntity *pEntity )
  80. {
  81. for ( int i=0; i<m_GlowObjectDefinitions.Count(); i++ )
  82. {
  83. if ( m_GlowObjectDefinitions[i].m_pEntity == pEntity )
  84. {
  85. UnregisterGlowObject(i);
  86. return;
  87. }
  88. }
  89. }
  90. void SetGlowAlphaPulseOverdrive( int nGlowObjectHandle, float flAdditionalAlpha )
  91. {
  92. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  93. m_GlowObjectDefinitions[nGlowObjectHandle].m_flGlowPulseOverdrive = flAdditionalAlpha;
  94. }
  95. void UnregisterAllGlowBoxes()
  96. {
  97. m_GlowBoxDefinitions.RemoveAll();
  98. }
  99. void SetGlowAlphaCappedByRenderAlpha( int nGlowObjectHandle, bool bGlowAlphaCappedByRenderAlpha )
  100. {
  101. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  102. m_GlowObjectDefinitions[nGlowObjectHandle].m_bGlowAlphaCappedByRenderAlpha = bGlowAlphaCappedByRenderAlpha;
  103. }
  104. void SetGlowAlphaFunctionOfMaxVelocity( int nGlowObjectHandle, float flMaxVelocity )
  105. {
  106. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  107. m_GlowObjectDefinitions[nGlowObjectHandle].m_flGlowAlphaFunctionOfMaxVelocity = flMaxVelocity;
  108. }
  109. void SetGlowAlphaMax( int nGlowObjectHandle, float flGlowAlphaMax )
  110. {
  111. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  112. m_GlowObjectDefinitions[nGlowObjectHandle].m_flGlowAlphaMax = flGlowAlphaMax;
  113. }
  114. void SetEntity( int nGlowObjectHandle, C_BaseEntity *pEntity )
  115. {
  116. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  117. m_GlowObjectDefinitions[nGlowObjectHandle].m_pEntity = pEntity;
  118. }
  119. void SetColor( int nGlowObjectHandle, const Vector &vGlowColor )
  120. {
  121. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  122. m_GlowObjectDefinitions[nGlowObjectHandle].m_vGlowColor = vGlowColor;
  123. }
  124. void SetAlpha( int nGlowObjectHandle, float flAlpha )
  125. {
  126. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  127. m_GlowObjectDefinitions[nGlowObjectHandle].m_flGlowAlpha = flAlpha;
  128. }
  129. void SetRenderFlags( int nGlowObjectHandle, bool bRenderWhenOccluded, bool bRenderWhenUnoccluded )
  130. {
  131. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  132. m_GlowObjectDefinitions[nGlowObjectHandle].m_bRenderWhenOccluded = bRenderWhenOccluded;
  133. m_GlowObjectDefinitions[nGlowObjectHandle].m_bRenderWhenUnoccluded = bRenderWhenUnoccluded;
  134. }
  135. void SetRenderStyle( int nGlowObjectHandle, GlowRenderStyle_t nNewRenderStyle )
  136. {
  137. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  138. Assert( nNewRenderStyle >= GLOWRENDERSTYLE_DEFAULT && nNewRenderStyle < GLOWRENDERSTYLE_COUNT );
  139. m_GlowObjectDefinitions[nGlowObjectHandle].m_nRenderStyle = nNewRenderStyle;
  140. }
  141. void SetFullBloomRender( int nGlowObjectHandle, bool bFullBloomRender, int nStencilTestValue )
  142. {
  143. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  144. m_GlowObjectDefinitions[nGlowObjectHandle].m_bFullBloomRender = bFullBloomRender;
  145. m_GlowObjectDefinitions[nGlowObjectHandle].m_nFullBloomStencilTestValue = nStencilTestValue;
  146. }
  147. bool IsRenderingWhenOccluded( int nGlowObjectHandle ) const
  148. {
  149. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  150. return m_GlowObjectDefinitions[nGlowObjectHandle].m_bRenderWhenOccluded;
  151. }
  152. bool IsRenderingWhenUnoccluded( int nGlowObjectHandle ) const
  153. {
  154. Assert( !m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused() );
  155. return m_GlowObjectDefinitions[nGlowObjectHandle].m_bRenderWhenUnoccluded;
  156. }
  157. void RenderGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot );
  158. private:
  159. void ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h );
  160. void RenderGlowBoxes( int iPass, CMatRenderContextPtr &pRenderContext );
  161. struct GlowObjectDefinition_t
  162. {
  163. bool ShouldDraw( int nSlot ) const {
  164. return m_pEntity && ( m_nSplitScreenSlot == GLOW_FOR_ALL_SPLIT_SCREEN_SLOTS || m_nSplitScreenSlot == nSlot ) && ( m_bRenderWhenOccluded || m_bRenderWhenUnoccluded ) && m_pEntity->ShouldDraw();
  165. }
  166. bool IsUnused() const {
  167. return m_nNextFreeSlot != GlowObjectDefinition_t::ENTRY_IN_USE;
  168. }
  169. void DrawModel();
  170. C_BaseEntity* m_pEntity;
  171. Vector m_vGlowColor;
  172. float m_flGlowAlpha;
  173. bool m_bGlowAlphaCappedByRenderAlpha;
  174. float m_flGlowAlphaFunctionOfMaxVelocity;
  175. float m_flGlowAlphaMax;
  176. float m_flGlowPulseOverdrive;
  177. bool m_bRenderWhenOccluded;
  178. bool m_bRenderWhenUnoccluded;
  179. bool m_bFullBloomRender;
  180. int m_nFullBloomStencilTestValue; // only render full bloom objects if stencil is equal to this value (value of -1 implies no stencil test)
  181. int m_nRenderStyle;
  182. int m_nSplitScreenSlot;
  183. // Linked list of free slots
  184. int m_nNextFreeSlot;
  185. // Special values for GlowObjectDefinition_t::m_nNextFreeSlot
  186. static const int END_OF_FREE_LIST = -1;
  187. static const int ENTRY_IN_USE = -2;
  188. };
  189. void RenderGlowModels( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, CUtlVector<GlowObjectDefinition_t> &vecGlowObjects );
  190. void DownSampleAndBlurRT( const CViewSetup *pSetup, CMatRenderContextPtr &pRenderContext, float flBloomScale, ITexture *pRtFullFrame, ITexture *pRtQuarterSize0, ITexture *pRtQuarterSize1 );
  191. CUtlVector< GlowObjectDefinition_t > m_GlowObjectDefinitions;
  192. int m_nFirstFreeSlot;
  193. struct GlowBoxDefinition_t
  194. {
  195. Vector m_vPosition;
  196. QAngle m_angOrientation;
  197. Vector m_vMins;
  198. Vector m_vMaxs;
  199. float m_flBirthTimeIndex;
  200. float m_flTerminationTimeIndex; //when to die
  201. Color m_colColor;
  202. };
  203. CUtlVector< GlowBoxDefinition_t > m_GlowBoxDefinitions;
  204. };
  205. CGlowObjectManager &GlowObjectManager();
  206. class CGlowObject
  207. {
  208. public:
  209. CGlowObject( C_BaseEntity *pEntity, const Vector &vGlowColor = Vector( 1.0f, 1.0f, 1.0f ), float flGlowAlpha = 1.0f, bool bRenderWhenOccluded = false, bool bRenderWhenUnoccluded = false, int nSplitScreenSlot = GLOW_FOR_ALL_SPLIT_SCREEN_SLOTS )
  210. {
  211. m_nGlowObjectHandle = GlowObjectManager().RegisterGlowObject( pEntity, vGlowColor, flGlowAlpha, bRenderWhenOccluded, bRenderWhenUnoccluded, nSplitScreenSlot );
  212. }
  213. ~CGlowObject()
  214. {
  215. GlowObjectManager().UnregisterGlowObject( m_nGlowObjectHandle );
  216. }
  217. void SetGlowAlphaPulseOverdrive( float flAdditionalAlpha )
  218. {
  219. //this value is added to existing glow alpha, and fades away in a few frames
  220. GlowObjectManager().SetGlowAlphaPulseOverdrive( m_nGlowObjectHandle, flAdditionalAlpha );
  221. }
  222. void SetGlowAlphaCappedByRenderAlpha( bool bGlowAlphaCappedByRenderAlpha )
  223. {
  224. GlowObjectManager().SetGlowAlphaCappedByRenderAlpha( m_nGlowObjectHandle, bGlowAlphaCappedByRenderAlpha );
  225. }
  226. void SetGlowAlphaFunctionOfMaxVelocity( float flMaxVelocity )
  227. {
  228. GlowObjectManager().SetGlowAlphaFunctionOfMaxVelocity( m_nGlowObjectHandle, flMaxVelocity );
  229. }
  230. void SetGlowAlphaMax( float flGlowAlphaMax )
  231. {
  232. GlowObjectManager().SetGlowAlphaMax( m_nGlowObjectHandle, flGlowAlphaMax );
  233. }
  234. void SetEntity( C_BaseEntity *pEntity )
  235. {
  236. GlowObjectManager().SetEntity( m_nGlowObjectHandle, pEntity );
  237. }
  238. void SetColor( const Vector &vGlowColor )
  239. {
  240. GlowObjectManager().SetColor( m_nGlowObjectHandle, vGlowColor );
  241. }
  242. void SetAlpha( float flAlpha )
  243. {
  244. GlowObjectManager().SetAlpha( m_nGlowObjectHandle, flAlpha );
  245. }
  246. void SetRenderFlags( bool bRenderWhenOccluded, bool bRenderWhenUnoccluded )
  247. {
  248. GlowObjectManager().SetRenderFlags( m_nGlowObjectHandle, bRenderWhenOccluded, bRenderWhenUnoccluded );
  249. }
  250. void SetRenderStyle( GlowRenderStyle_t nNewRenderStyle )
  251. {
  252. GlowObjectManager().SetRenderStyle( m_nGlowObjectHandle, nNewRenderStyle );
  253. }
  254. void SetFullBloomRender( bool bFullBloomRender, int nStencilTestValue = -1 )
  255. {
  256. return GlowObjectManager().SetFullBloomRender( m_nGlowObjectHandle, bFullBloomRender, nStencilTestValue );
  257. }
  258. bool IsRenderingWhenOccluded() const
  259. {
  260. return GlowObjectManager().IsRenderingWhenOccluded( m_nGlowObjectHandle );
  261. }
  262. bool IsRenderingWhenUnoccluded() const
  263. {
  264. return GlowObjectManager().IsRenderingWhenUnoccluded( m_nGlowObjectHandle );
  265. }
  266. bool IsRendering() const
  267. {
  268. return IsRenderingWhenOccluded() || IsRenderingWhenUnoccluded();
  269. }
  270. // Add more accessors/mutators here as needed
  271. private:
  272. int m_nGlowObjectHandle;
  273. // Assignment & copy-construction disallowed
  274. CGlowObject( const CGlowObject &other );
  275. CGlowObject& operator=( const CGlowObject &other );
  276. };
  277. #endif // GLOW_OUTLINE_EFFECT_H