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.

270 lines
7.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmematerialoverlayfxclip.h"
  7. #include "datamodel/dmelementfactoryhelper.h"
  8. #include "materialsystem/imesh.h"
  9. #include "materialsystem/imaterial.h"
  10. #include "tier1/KeyValues.h"
  11. #include "tier1/convar.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. //-----------------------------------------------------------------------------
  15. // CDmeClip - common base class for filmclips, soundclips, and channelclips
  16. //-----------------------------------------------------------------------------
  17. IMPLEMENT_FX_CLIP_ELEMENT_FACTORY( DmeMaterialOverlayFXClip, CDmeMaterialOverlayFXClip, "Material Overlay Effect" );
  18. void CDmeMaterialOverlayFXClip::OnConstruction()
  19. {
  20. m_Material.Init( this, "material" );
  21. m_Color.Init( this, "overlaycolor" );
  22. m_nLeft.Init( this, "left" );
  23. m_nTop.Init( this, "top" );
  24. m_nWidth.Init( this, "width" );
  25. m_nHeight.Init( this, "height" );
  26. m_bFullScreen.Init( this, "fullscreen" );
  27. m_bUseSubRect.Init( this, "useSubRect" );
  28. m_flMovementAngle.Init( this, "movementAngle" );
  29. m_flMovementSpeed.Init( this, "movementSpeed" );
  30. m_nSubRectLeft.Init( this, "subRectLeft" );
  31. m_nSubRectTop.Init( this, "subRectTop" );
  32. m_nSubRectWidth.Init( this, "subRectWidth" );
  33. m_nSubRectHeight.Init( this, "subRectHeight" );
  34. m_Color.SetColor( 255, 255, 255, 255 );
  35. m_bFullScreen = true;
  36. m_nLeft = m_nTop = 0;
  37. m_nWidth = m_nHeight = 1;
  38. }
  39. void CDmeMaterialOverlayFXClip::OnDestruction()
  40. {
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Resolve
  44. //-----------------------------------------------------------------------------
  45. void CDmeMaterialOverlayFXClip::Resolve()
  46. {
  47. if ( m_Material.IsDirty() )
  48. {
  49. m_OverlayMaterial.Shutdown();
  50. const char *pName = m_Material.Get();
  51. if ( pName && pName[0] )
  52. {
  53. m_OverlayMaterial.Init( pName, NULL, false );
  54. }
  55. m_Material.GetAttribute()->RemoveFlag( FATTRIB_DIRTY );
  56. }
  57. }
  58. //-----------------------------------------------------------------------------
  59. // Helper for overlays
  60. //-----------------------------------------------------------------------------
  61. void CDmeMaterialOverlayFXClip::SetOverlayEffect( const char *pMaterialName )
  62. {
  63. m_Material = pMaterialName;
  64. }
  65. void CDmeMaterialOverlayFXClip::SetAlpha( float flAlpha )
  66. {
  67. m_Color.SetAlpha( flAlpha * 255 );
  68. }
  69. float CDmeMaterialOverlayFXClip::GetAlpha( void )
  70. {
  71. return ( (float)m_Color.a() ) / 255.0f;
  72. }
  73. bool CDmeMaterialOverlayFXClip::HasOpaqueOverlay( void )
  74. {
  75. if ( m_OverlayMaterial )
  76. return ( !m_OverlayMaterial->IsTranslucent() && ( m_Color.a() == 255 ) && m_bFullScreen );
  77. // no material overlay set
  78. return false;
  79. }
  80. IMaterial *CDmeMaterialOverlayFXClip::GetMaterial()
  81. {
  82. return m_OverlayMaterial;
  83. }
  84. //-----------------------------------------------------------------------------
  85. // All effects must be able to apply their effect
  86. //-----------------------------------------------------------------------------
  87. void CDmeMaterialOverlayFXClip::ApplyEffect( DmeTime_t time, Rect_t &currentRect, Rect_t &totalRect, ITexture *pTextures[MAX_FX_INPUT_TEXTURES] )
  88. {
  89. if ( !m_OverlayMaterial || m_Color.a() == 0 )
  90. return;
  91. time = ToChildMediaTime( time, false );
  92. // Clip the overlay rectangle to the currently drawn one
  93. int x, y, w, h;
  94. int tx, ty, tw, th;
  95. if ( m_bFullScreen )
  96. {
  97. x = currentRect.x;
  98. y = currentRect.y;
  99. w = currentRect.width;
  100. h = currentRect.height;
  101. tx = ty = 0;
  102. tw = totalRect.width;
  103. th = totalRect.height;
  104. }
  105. else
  106. {
  107. x = clamp( m_nLeft, currentRect.x, currentRect.x + currentRect.width );
  108. y = clamp( m_nTop, currentRect.y, currentRect.y + currentRect.height );
  109. int x1 = clamp( m_nLeft + m_nWidth, currentRect.x, currentRect.x + currentRect.width );
  110. int y1 = clamp( m_nTop + m_nHeight, currentRect.y, currentRect.y + currentRect.height );
  111. w = x1 - x;
  112. h = y1 - y;
  113. tx = m_nLeft;
  114. ty = m_nTop;
  115. tw = m_nWidth;
  116. th = m_nHeight;
  117. // Clipped...
  118. if ( w <= 0 || h <= 0 )
  119. return;
  120. }
  121. if ( tw == 0 || th == 0 )
  122. return;
  123. // Compute texture coordinate range of the entire texture
  124. int mw = m_OverlayMaterial->GetMappingWidth();
  125. int mh = m_OverlayMaterial->GetMappingHeight();
  126. // Compute the texture coords in texels we want over the entire image
  127. float uMin = 0;
  128. float uMax = mw;
  129. float vMin = 0;
  130. float vMax = mh;
  131. if ( m_bUseSubRect )
  132. {
  133. uMin = m_nSubRectLeft;
  134. vMin = m_nSubRectTop;
  135. uMax = uMin + m_nSubRectWidth;
  136. vMax = vMin + m_nSubRectHeight;
  137. }
  138. if ( m_flMovementSpeed )
  139. {
  140. float flRadians = M_PI * m_flMovementAngle / 180.0f;
  141. float dUdT = -m_flMovementSpeed * cos( flRadians );
  142. float dVdT = m_flMovementSpeed * sin( flRadians );
  143. float dU = time.GetSeconds() * dUdT;
  144. float dV = time.GetSeconds() * dVdT;
  145. uMin += dU; uMax += dU;
  146. vMin += dV; vMax += dV;
  147. }
  148. // This is the range of normalizes (u,v) coordinates over the *total* image
  149. uMin = ( uMin + 0.5f ) / mw;
  150. vMin = ( vMin + 0.5f ) / mh;
  151. uMax = ( uMax - 0.5f ) / mw;
  152. vMax = ( vMax - 0.5f ) / mh;
  153. // Now determine the subrange we should use given we're rendering a portion of the image
  154. float u0, v0, u1, v1, f;
  155. f = ( x - tx ) / tw;
  156. u0 = Lerp( f, uMin, uMax );
  157. f = ( x + w - tx ) / tw;
  158. u1 = Lerp( f, uMin, uMax );
  159. f = ( y - ty ) / th;
  160. v0 = Lerp( f, vMin, vMax );
  161. f = ( y + h - ty ) / th;
  162. v1 = Lerp( f, vMin, vMax );
  163. x -= currentRect.x;
  164. y -= currentRect.y;
  165. if ( m_OverlayMaterial->NeedsPowerOfTwoFrameBufferTexture() )
  166. {
  167. CMatRenderContextPtr pRenderContext( materials );
  168. ITexture *pTexture = materials->FindTexture( "_rt_PowerOfTwoFB", TEXTURE_GROUP_RENDER_TARGET );
  169. // forced or only once per frame
  170. Rect_t rect;
  171. rect.x = 0;
  172. rect.y = 0;
  173. rect.width = currentRect.width;
  174. rect.height = currentRect.height;
  175. pRenderContext->CopyRenderTargetToTextureEx( pTexture, 0, &rect, NULL );
  176. pRenderContext->SetFrameBufferCopyTexture( pTexture );
  177. }
  178. float r, g, b, a;
  179. m_OverlayMaterial->GetColorModulation( &r, &g, &b );
  180. a = m_OverlayMaterial->GetAlphaModulation();
  181. m_OverlayMaterial->ColorModulate( m_Color.r() / 255.0f, m_Color.g() / 255.0f, m_Color.b() / 255.0f );
  182. m_OverlayMaterial->AlphaModulate( m_Color.a() / 255.0f );
  183. CMatRenderContextPtr pRenderContext( materials );
  184. pRenderContext->Bind( m_OverlayMaterial );
  185. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  186. CMeshBuilder meshBuilder;
  187. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 );
  188. meshBuilder.Position3f( x, y, 0.0f );
  189. meshBuilder.BoneWeight( 0, 1.0f );
  190. meshBuilder.BoneMatrix( 0, 0 );
  191. meshBuilder.Color4ub( 255, 255, 255, 255 );
  192. meshBuilder.TexCoord2f( 0, u0, v0 );
  193. meshBuilder.TexCoord2f( 1, 0.0f, 0.0f );
  194. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  195. meshBuilder.AdvanceVertex();
  196. meshBuilder.Position3f( x, y+h, 0.0f );
  197. meshBuilder.BoneWeight( 0, 1.0f );
  198. meshBuilder.BoneMatrix( 0, 0 );
  199. meshBuilder.Color4ub( 255, 255, 255, 255 );
  200. meshBuilder.TexCoord2f( 0, u0, v1 );
  201. meshBuilder.TexCoord2f( 1, 0.0f, 1.0f );
  202. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  203. meshBuilder.AdvanceVertex();
  204. meshBuilder.Position3f( x+w, y, 0.0f );
  205. meshBuilder.BoneWeight( 0, 1.0f );
  206. meshBuilder.BoneMatrix( 0, 0 );
  207. meshBuilder.Color4ub( 255, 255, 255, 255 );
  208. meshBuilder.TexCoord2f( 0, u1, v0 );
  209. meshBuilder.TexCoord2f( 1, 1.0f, 0.0f );
  210. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  211. meshBuilder.AdvanceVertex();
  212. meshBuilder.Position3f( x+w, y+h, 0.0f );
  213. meshBuilder.BoneWeight( 0, 1.0f );
  214. meshBuilder.BoneMatrix( 0, 0 );
  215. meshBuilder.Color4ub( 255, 255, 255, 255 );
  216. meshBuilder.TexCoord2f( 0, u1, v1 );
  217. meshBuilder.TexCoord2f( 1, 1.0f, 1.0f );
  218. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  219. meshBuilder.AdvanceVertex();
  220. meshBuilder.End();
  221. pMesh->Draw();
  222. m_OverlayMaterial->ColorModulate( r, g, b );
  223. m_OverlayMaterial->AlphaModulate( a );
  224. }