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.

464 lines
15 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Episodic screen-space effects
  4. //
  5. #include "cbase.h"
  6. #include "ScreenSpaceEffects.h"
  7. #include "rendertexture.h"
  8. #include "materialsystem/imaterialsystemhardwareconfig.h"
  9. #include "materialsystem/imaterialsystem.h"
  10. #include "materialsystem/imaterialvar.h"
  11. #include "cdll_client_int.h"
  12. #include "materialsystem/itexture.h"
  13. #include "KeyValues.h"
  14. #include "clienteffectprecachesystem.h"
  15. #include "episodic_screenspaceeffects.h"
  16. //-----------------------------------------------------------------------------
  17. // Purpose:
  18. //-----------------------------------------------------------------------------
  19. #ifdef _X360
  20. #define STUN_TEXTURE "_rt_FullFrameFB2"
  21. #else
  22. #define STUN_TEXTURE "_rt_WaterRefraction"
  23. #endif
  24. //-----------------------------------------------------------------------------
  25. // Purpose:
  26. //-----------------------------------------------------------------------------
  27. void CStunEffect::Init( void )
  28. {
  29. m_flDuration = 0.0f;
  30. m_flFinishTime = 0.0f;
  31. m_bUpdateView = true;
  32. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  33. pVMTKeyValues->SetString( "$basetexture", STUN_TEXTURE );
  34. m_EffectMaterial.Init( "__stuneffect", TEXTURE_GROUP_CLIENT_EFFECTS, pVMTKeyValues );
  35. m_StunTexture.Init( STUN_TEXTURE, TEXTURE_GROUP_CLIENT_EFFECTS );
  36. }
  37. void CStunEffect::Shutdown( void )
  38. {
  39. m_EffectMaterial.Shutdown();
  40. m_StunTexture.Shutdown();
  41. }
  42. //------------------------------------------------------------------------------
  43. // Purpose: Pick up changes in our parameters
  44. //------------------------------------------------------------------------------
  45. void CStunEffect::SetParameters( KeyValues *params )
  46. {
  47. if( params->FindKey( "duration" ) )
  48. {
  49. m_flDuration = params->GetFloat( "duration" );
  50. m_flFinishTime = gpGlobals->curtime + m_flDuration;
  51. m_bUpdateView = true;
  52. }
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Purpose: Render the effect
  56. //-----------------------------------------------------------------------------
  57. void CStunEffect::Render( int x, int y, int w, int h )
  58. {
  59. // Make sure we're ready to play this effect
  60. if ( m_flFinishTime < gpGlobals->curtime )
  61. return;
  62. CMatRenderContextPtr pRenderContext( materials );
  63. // Set ourselves to the proper rendermode
  64. pRenderContext->MatrixMode( MATERIAL_VIEW );
  65. pRenderContext->PushMatrix();
  66. pRenderContext->LoadIdentity();
  67. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  68. pRenderContext->PushMatrix();
  69. pRenderContext->LoadIdentity();
  70. // Draw the texture if we're using it
  71. if ( m_bUpdateView )
  72. {
  73. // Save off this pass
  74. Rect_t srcRect;
  75. srcRect.x = x;
  76. srcRect.y = y;
  77. srcRect.width = w;
  78. srcRect.height = h;
  79. pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
  80. m_bUpdateView = false;
  81. }
  82. float flEffectPerc = ( m_flFinishTime - gpGlobals->curtime ) / m_flDuration;
  83. float viewOffs = ( flEffectPerc * 32.0f ) * ( cos( gpGlobals->curtime * 40.0f ) * sin( gpGlobals->curtime * 17.0f ) );
  84. float vX = x + viewOffs;
  85. if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80 )
  86. {
  87. if ( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
  88. {
  89. m_EffectMaterial->ColorModulate( 1.0f, 1.0f, 1.0f );
  90. }
  91. else
  92. {
  93. // This is a stupid fix, but I don't have time to do a cleaner implementation. Since
  94. // the introblur.vmt material uses unlit generic, it will tone map, so I need to undo the tone mapping
  95. // using color modulate. The proper fix would be to use a different material type that
  96. // supports alpha blending but not tone mapping, which I don't think exists. Whatever. This works when
  97. // the tone mapping scalar is less than 1.0, which it is in the cases it's used in game.
  98. float flUnTonemap = pow( 1.0f / pRenderContext->GetToneMappingScaleLinear().x, 1.0f / 2.2f );
  99. m_EffectMaterial->ColorModulate( flUnTonemap, flUnTonemap, flUnTonemap );
  100. }
  101. // Set alpha blend value
  102. float flOverlayAlpha = clamp( ( 150.0f / 255.0f ) * flEffectPerc, 0.0f, 1.0f );
  103. m_EffectMaterial->AlphaModulate( flOverlayAlpha );
  104. // Draw full screen alpha-blended quad
  105. pRenderContext->DrawScreenSpaceRectangle( m_EffectMaterial, 0, 0, w, h,
  106. vX, 0, (m_StunTexture->GetActualWidth()-1)+vX, (m_StunTexture->GetActualHeight()-1),
  107. m_StunTexture->GetActualWidth(), m_StunTexture->GetActualHeight() );
  108. }
  109. // Save off this pass
  110. Rect_t srcRect;
  111. srcRect.x = x;
  112. srcRect.y = y;
  113. srcRect.width = w;
  114. srcRect.height = h;
  115. pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
  116. // Restore our state
  117. pRenderContext->MatrixMode( MATERIAL_VIEW );
  118. pRenderContext->PopMatrix();
  119. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  120. pRenderContext->PopMatrix();
  121. }
  122. // ================================================================================================================
  123. //
  124. // Ep 1. Intro blur
  125. //
  126. // ================================================================================================================
  127. //-----------------------------------------------------------------------------
  128. // Purpose:
  129. //-----------------------------------------------------------------------------
  130. void CEP1IntroEffect::Init( void )
  131. {
  132. m_flDuration = 0.0f;
  133. m_flFinishTime = 0.0f;
  134. m_bUpdateView = true;
  135. m_bFadeOut = false;
  136. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  137. pVMTKeyValues->SetString( "$basetexture", STUN_TEXTURE );
  138. m_EffectMaterial.Init( "__ep1introeffect", TEXTURE_GROUP_CLIENT_EFFECTS, pVMTKeyValues );
  139. m_StunTexture.Init( STUN_TEXTURE, TEXTURE_GROUP_CLIENT_EFFECTS );
  140. }
  141. void CEP1IntroEffect::Shutdown( void )
  142. {
  143. m_EffectMaterial.Shutdown();
  144. m_StunTexture.Shutdown();
  145. }
  146. //------------------------------------------------------------------------------
  147. // Purpose: Pick up changes in our parameters
  148. //------------------------------------------------------------------------------
  149. void CEP1IntroEffect::SetParameters( KeyValues *params )
  150. {
  151. if( params->FindKey( "duration" ) )
  152. {
  153. m_flDuration = params->GetFloat( "duration" );
  154. m_flFinishTime = gpGlobals->curtime + m_flDuration;
  155. }
  156. if( params->FindKey( "fadeout" ) )
  157. {
  158. m_bFadeOut = ( params->GetInt( "fadeout" ) == 1 );
  159. }
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Purpose: Get the alpha value depending on various factors and time
  163. //-----------------------------------------------------------------------------
  164. inline unsigned char CEP1IntroEffect::GetFadeAlpha( void )
  165. {
  166. // Find our percentage between fully "on" and "off" in the pulse range
  167. float flEffectPerc = ( m_flDuration == 0.0f ) ? 0.0f : ( m_flFinishTime - gpGlobals->curtime ) / m_flDuration;
  168. flEffectPerc = clamp( flEffectPerc, 0.0f, 1.0f );
  169. if ( m_bFadeOut )
  170. {
  171. // HDR requires us to be more subtle, or we get uber-brightening
  172. if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
  173. return (unsigned char) clamp( 50.0f * flEffectPerc, 0.0f, 50.0f );
  174. // Non-HDR
  175. return (unsigned char) clamp( 64.0f * flEffectPerc, 0.0f, 64.0f );
  176. }
  177. else
  178. {
  179. // HDR requires us to be more subtle, or we get uber-brightening
  180. if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
  181. return (unsigned char) clamp( 64.0f * flEffectPerc, 50.0f, 64.0f );
  182. // Non-HDR
  183. return (unsigned char) clamp( 128.0f * flEffectPerc, 64.0f, 128.0f );
  184. }
  185. }
  186. //-----------------------------------------------------------------------------
  187. // Purpose: Render the effect
  188. //-----------------------------------------------------------------------------
  189. void CEP1IntroEffect::Render( int x, int y, int w, int h )
  190. {
  191. if ( ( m_flFinishTime == 0 ) || ( IsEnabled() == false ) )
  192. return;
  193. CMatRenderContextPtr pRenderContext( materials );
  194. // Set ourselves to the proper rendermode
  195. pRenderContext->MatrixMode( MATERIAL_VIEW );
  196. pRenderContext->PushMatrix();
  197. pRenderContext->LoadIdentity();
  198. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  199. pRenderContext->PushMatrix();
  200. pRenderContext->LoadIdentity();
  201. // Draw the texture if we're using it
  202. if ( m_bUpdateView )
  203. {
  204. // Save off this pass
  205. Rect_t srcRect;
  206. srcRect.x = x;
  207. srcRect.y = y;
  208. srcRect.width = w;
  209. srcRect.height = h;
  210. pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
  211. m_bUpdateView = false;
  212. }
  213. byte overlaycolor[4] = { 255, 255, 255, 0 };
  214. // Get our fade value depending on our fade duration
  215. overlaycolor[3] = GetFadeAlpha();
  216. if ( g_pMaterialSystemHardwareConfig->UsesSRGBCorrectBlending() )
  217. {
  218. // For DX10 cards, alpha blending happens in linear space, so try to adjust by hacking alpha to 50%
  219. overlaycolor[3] *= 0.7f;
  220. }
  221. // Disable overself if we're done fading out
  222. if ( m_bFadeOut && overlaycolor[3] == 0 )
  223. {
  224. // Takes effect next frame (we don't want to hose our matrix stacks here)
  225. g_pScreenSpaceEffects->DisableScreenSpaceEffect( "episodic_intro" );
  226. m_bUpdateView = true;
  227. }
  228. // Calculate some wavey noise to jitter the view by
  229. float vX = 2.0f * -fabs( cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 6.0 ) );
  230. float vY = 2.0f * cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 5.0 );
  231. // Scale percentage
  232. float flScalePerc = 0.02f + ( 0.01f * cosf( gpGlobals->curtime * 2.0f ) * cosf( gpGlobals->curtime * 0.5f ) );
  233. // Scaled offsets for the UVs (as texels)
  234. float flUOffset = ( m_StunTexture->GetActualWidth() - 1 ) * flScalePerc * 0.5f;
  235. float flVOffset = ( m_StunTexture->GetActualHeight() - 1 ) * flScalePerc * 0.5f;
  236. // New UVs with scaling offsets
  237. float flU1 = flUOffset;
  238. float flU2 = ( m_StunTexture->GetActualWidth() - 1 ) - flUOffset;
  239. float flV1 = flVOffset;
  240. float flV2 = ( m_StunTexture->GetActualHeight() - 1 ) - flVOffset;
  241. // Draw the "zoomed" overlay
  242. pRenderContext->DrawScreenSpaceRectangle( m_EffectMaterial, vX, vY, w, h,
  243. flU1, flV1,
  244. flU2, flV2,
  245. m_StunTexture->GetActualWidth(), m_StunTexture->GetActualHeight() );
  246. render->ViewDrawFade( overlaycolor, m_EffectMaterial );
  247. // Save off this pass
  248. Rect_t srcRect;
  249. srcRect.x = x;
  250. srcRect.y = y;
  251. srcRect.width = w;
  252. srcRect.height = h;
  253. pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
  254. // Restore our state
  255. pRenderContext->MatrixMode( MATERIAL_VIEW );
  256. pRenderContext->PopMatrix();
  257. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  258. pRenderContext->PopMatrix();
  259. }
  260. // ================================================================================================================
  261. //
  262. // Ep 2. Groggy-player view
  263. //
  264. // ================================================================================================================
  265. //-----------------------------------------------------------------------------
  266. // Purpose:
  267. //-----------------------------------------------------------------------------
  268. void CEP2StunEffect::Init( void )
  269. {
  270. m_flDuration = 0.0f;
  271. m_flFinishTime = 0.0f;
  272. m_bUpdateView = true;
  273. m_bFadeOut = false;
  274. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  275. pVMTKeyValues->SetString( "$basetexture", STUN_TEXTURE );
  276. m_EffectMaterial.Init( "__ep2stuneffect", TEXTURE_GROUP_CLIENT_EFFECTS, pVMTKeyValues );
  277. m_StunTexture.Init( STUN_TEXTURE, TEXTURE_GROUP_CLIENT_EFFECTS );
  278. }
  279. void CEP2StunEffect::Shutdown( void )
  280. {
  281. m_EffectMaterial.Shutdown();
  282. m_StunTexture.Shutdown();
  283. }
  284. //------------------------------------------------------------------------------
  285. // Purpose: Pick up changes in our parameters
  286. //------------------------------------------------------------------------------
  287. void CEP2StunEffect::SetParameters( KeyValues *params )
  288. {
  289. if( params->FindKey( "duration" ) )
  290. {
  291. m_flDuration = params->GetFloat( "duration" );
  292. m_flFinishTime = gpGlobals->curtime + m_flDuration;
  293. }
  294. if( params->FindKey( "fadeout" ) )
  295. {
  296. m_bFadeOut = ( params->GetInt( "fadeout" ) == 1 );
  297. }
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Purpose: Get the alpha value depending on various factors and time
  301. //-----------------------------------------------------------------------------
  302. inline unsigned char CEP2StunEffect::GetFadeAlpha( void )
  303. {
  304. // Find our percentage between fully "on" and "off" in the pulse range
  305. float flEffectPerc = ( m_flDuration == 0.0f ) ? 0.0f : ( m_flFinishTime - gpGlobals->curtime ) / m_flDuration;
  306. flEffectPerc = clamp( flEffectPerc, 0.0f, 1.0f );
  307. if ( m_bFadeOut )
  308. {
  309. // HDR requires us to be more subtle, or we get uber-brightening
  310. if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
  311. return (unsigned char) clamp( 50.0f * flEffectPerc, 0.0f, 50.0f );
  312. // Non-HDR
  313. return (unsigned char) clamp( 64.0f * flEffectPerc, 0.0f, 64.0f );
  314. }
  315. else
  316. {
  317. // HDR requires us to be more subtle, or we get uber-brightening
  318. if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
  319. return (unsigned char) clamp( 164.0f * flEffectPerc, 128.0f, 164.0f );
  320. // Non-HDR
  321. return (unsigned char) clamp( 164.0f * flEffectPerc, 128.0f, 164.0f );
  322. }
  323. }
  324. //-----------------------------------------------------------------------------
  325. // Purpose: Render the effect
  326. //-----------------------------------------------------------------------------
  327. void CEP2StunEffect::Render( int x, int y, int w, int h )
  328. {
  329. if ( ( m_flFinishTime == 0 ) || ( IsEnabled() == false ) )
  330. return;
  331. CMatRenderContextPtr pRenderContext( materials );
  332. // Set ourselves to the proper rendermode
  333. pRenderContext->MatrixMode( MATERIAL_VIEW );
  334. pRenderContext->PushMatrix();
  335. pRenderContext->LoadIdentity();
  336. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  337. pRenderContext->PushMatrix();
  338. pRenderContext->LoadIdentity();
  339. if ( m_bUpdateView )
  340. {
  341. // Save off this pass
  342. Rect_t srcRect;
  343. srcRect.x = x;
  344. srcRect.y = y;
  345. srcRect.width = w;
  346. srcRect.height = h;
  347. pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
  348. m_bUpdateView = false;
  349. }
  350. byte overlaycolor[4] = { 255, 255, 255, 0 };
  351. // Get our fade value depending on our fade duration
  352. overlaycolor[3] = GetFadeAlpha();
  353. // Disable overself if we're done fading out
  354. if ( m_bFadeOut && overlaycolor[3] == 0 )
  355. {
  356. // Takes effect next frame (we don't want to hose our matrix stacks here)
  357. g_pScreenSpaceEffects->DisableScreenSpaceEffect( "ep2_groggy" );
  358. m_bUpdateView = true;
  359. }
  360. // Calculate some wavey noise to jitter the view by
  361. float vX = 4.0f * cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 6.0 );
  362. float vY = 2.0f * cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 5.0 );
  363. float flBaseScale = 0.2f + 0.005f * sinf( gpGlobals->curtime * 4.0f );
  364. // Scale percentage
  365. float flScalePerc = flBaseScale + ( 0.01f * cosf( gpGlobals->curtime * 2.0f ) * cosf( gpGlobals->curtime * 0.5f ) );
  366. // Scaled offsets for the UVs (as texels)
  367. float flUOffset = ( m_StunTexture->GetActualWidth() - 1 ) * flScalePerc * 0.5f;
  368. float flVOffset = ( m_StunTexture->GetActualHeight() - 1 ) * flScalePerc * 0.5f;
  369. // New UVs with scaling offsets
  370. float flU1 = flUOffset;
  371. float flU2 = ( m_StunTexture->GetActualWidth() - 1 ) - flUOffset;
  372. float flV1 = flVOffset;
  373. float flV2 = ( m_StunTexture->GetActualHeight() - 1 ) - flVOffset;
  374. // Draw the "zoomed" overlay
  375. pRenderContext->DrawScreenSpaceRectangle( m_EffectMaterial, vX, vY, w, h,
  376. flU1, flV1,
  377. flU2, flV2,
  378. m_StunTexture->GetActualWidth(), m_StunTexture->GetActualHeight() );
  379. render->ViewDrawFade( overlaycolor, m_EffectMaterial );
  380. // Save off this pass
  381. Rect_t srcRect;
  382. srcRect.x = x;
  383. srcRect.y = y;
  384. srcRect.width = w;
  385. srcRect.height = h;
  386. pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
  387. // Restore our state
  388. pRenderContext->MatrixMode( MATERIAL_VIEW );
  389. pRenderContext->PopMatrix();
  390. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  391. pRenderContext->PopMatrix();
  392. }