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.

323 lines
9.7 KiB

  1. //====== Copyright � 1996-2004, 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. // Set up the Blt material
  39. KeyValues *pVMTKeyValues = new KeyValues( "accumbuff4sample" );
  40. pVMTKeyValues->SetString( "$INPUT", "Effects/FilmScan256" ); // dummy
  41. KeyValues *pProxiesKV = pVMTKeyValues->FindKey( "proxies", true ); // create a subkey
  42. pProxiesKV->FindKey( "sfm_blt", true );
  43. m_BltMaterial.Init( "accumbuff4sample", pVMTKeyValues );
  44. m_BltMaterial->Refresh();
  45. }
  46. void CDmeMaterialOverlayFXClip::OnDestruction()
  47. {
  48. m_BltMaterial.Shutdown();
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Resolve
  52. //-----------------------------------------------------------------------------
  53. void CDmeMaterialOverlayFXClip::Resolve()
  54. {
  55. if ( m_Material.IsDirty() )
  56. {
  57. m_OverlayMaterial.Shutdown();
  58. const char *pName = m_Material.Get();
  59. if ( pName && pName[0] )
  60. {
  61. m_OverlayMaterial.Init( pName, NULL, false );
  62. }
  63. m_Material.GetAttribute()->RemoveFlag( FATTRIB_DIRTY );
  64. }
  65. }
  66. //-----------------------------------------------------------------------------
  67. // Helper for overlays
  68. //-----------------------------------------------------------------------------
  69. void CDmeMaterialOverlayFXClip::SetOverlayEffect( const char *pMaterialName )
  70. {
  71. m_Material = pMaterialName;
  72. }
  73. void CDmeMaterialOverlayFXClip::SetAlpha( float flAlpha )
  74. {
  75. m_Color.SetAlpha( flAlpha * 255 );
  76. }
  77. float CDmeMaterialOverlayFXClip::GetAlpha( void )
  78. {
  79. return ( (float)m_Color.a() ) / 255.0f;
  80. }
  81. bool CDmeMaterialOverlayFXClip::HasOpaqueOverlay( void )
  82. {
  83. if ( m_OverlayMaterial )
  84. return ( !m_OverlayMaterial->IsTranslucent() && ( m_Color.a() == 255 ) && m_bFullScreen );
  85. // no material overlay set
  86. return false;
  87. }
  88. IMaterial *CDmeMaterialOverlayFXClip::GetMaterial()
  89. {
  90. return m_OverlayMaterial;
  91. }
  92. void CDmeMaterialOverlayFXClip::DrawQuad( int x, int y, int w, int h, float u0, float v0, float u1, float v1 )
  93. {
  94. CMatRenderContextPtr pRenderContext( materials );
  95. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  96. CMeshBuilder meshBuilder;
  97. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 );
  98. meshBuilder.Position3f( x, y, 0.0f );
  99. meshBuilder.BoneWeight( 0, 1.0f );
  100. meshBuilder.BoneMatrix( 0, 0 );
  101. meshBuilder.Color4ub( 255, 255, 255, 255 );
  102. meshBuilder.TexCoord2f( 0, u0, v0 );
  103. meshBuilder.TexCoord2f( 1, 0.0f, 0.0f );
  104. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  105. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 3>();
  106. meshBuilder.Position3f( x, y+h, 0.0f );
  107. meshBuilder.BoneWeight( 0, 1.0f );
  108. meshBuilder.BoneMatrix( 0, 0 );
  109. meshBuilder.Color4ub( 255, 255, 255, 255 );
  110. meshBuilder.TexCoord2f( 0, u0, v1 );
  111. meshBuilder.TexCoord2f( 1, 0.0f, 1.0f );
  112. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  113. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 3>();
  114. meshBuilder.Position3f( x+w, y, 0.0f );
  115. meshBuilder.BoneWeight( 0, 1.0f );
  116. meshBuilder.BoneMatrix( 0, 0 );
  117. meshBuilder.Color4ub( 255, 255, 255, 255 );
  118. meshBuilder.TexCoord2f( 0, u1, v0 );
  119. meshBuilder.TexCoord2f( 1, 1.0f, 0.0f );
  120. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  121. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 3>();
  122. meshBuilder.Position3f( x+w, y+h, 0.0f );
  123. meshBuilder.BoneWeight( 0, 1.0f );
  124. meshBuilder.BoneMatrix( 0, 0 );
  125. meshBuilder.Color4ub( 255, 255, 255, 255 );
  126. meshBuilder.TexCoord2f( 0, u1, v1 );
  127. meshBuilder.TexCoord2f( 1, 1.0f, 1.0f );
  128. meshBuilder.TexCoord2f( 2, 0.0f, 0.0f );
  129. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 3>();
  130. meshBuilder.End();
  131. pMesh->Draw();
  132. }
  133. void CDmeMaterialOverlayFXClip::DrawOneToOneQuad( int nWidth, int nHeight )
  134. {
  135. CMatRenderContextPtr pRenderContext( materials );
  136. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  137. CMeshBuilder meshBuilder;
  138. // Epsilons for 1:1 texel to pixel mapping
  139. float fWidthEpsilon = 0.5f / ((float) nWidth);
  140. float fHeightEpsilon = 0.5f / ((float) nHeight);
  141. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  142. meshBuilder.Position3f( -1.0f, 1.0f, 0.5f ); // Upper left
  143. meshBuilder.TexCoord2f( 0, 0.0f + fWidthEpsilon, 0.0f + fHeightEpsilon);
  144. meshBuilder.AdvanceVertexF<VTX_HAVEPOS, 1>();
  145. meshBuilder.Position3f( -1.0f, -1.0f, 0.5f ); // Lower left
  146. meshBuilder.TexCoord2f( 0, 0.0f + fWidthEpsilon, 1.0f + fHeightEpsilon);
  147. meshBuilder.AdvanceVertexF<VTX_HAVEPOS, 1>();
  148. meshBuilder.Position3f( 1.0f, -1.0f, 0.5 ); // Lower right
  149. meshBuilder.TexCoord2f( 0, 1.0f + fWidthEpsilon, 1.0f + fHeightEpsilon);
  150. meshBuilder.AdvanceVertexF<VTX_HAVEPOS, 1>();
  151. meshBuilder.Position3f( 1.0f, 1.0f, 0.5 ); // Upper right
  152. meshBuilder.TexCoord2f( 0, 1.0f + fWidthEpsilon, 0.0f + fHeightEpsilon);
  153. meshBuilder.AdvanceVertexF<VTX_HAVEPOS, 1>();
  154. meshBuilder.End();
  155. pMesh->Draw();
  156. }
  157. //-----------------------------------------------------------------------------
  158. // All effects must be able to apply their effect
  159. //-----------------------------------------------------------------------------
  160. void CDmeMaterialOverlayFXClip::ApplyEffect( DmeTime_t time, Rect_t &currentRect, Rect_t &totalRect, ITexture *pTextures[MAX_FX_INPUT_TEXTURES] )
  161. {
  162. if ( !m_OverlayMaterial || !m_BltMaterial || m_Color.a() == 0 )
  163. return;
  164. time = ToChildMediaTime( time, false );
  165. // Clip the overlay rectangle to the currently drawn one
  166. int x, y, w, h;
  167. int tx, ty, tw, th;
  168. if ( m_bFullScreen )
  169. {
  170. x = currentRect.x;
  171. y = currentRect.y;
  172. w = currentRect.width;
  173. h = currentRect.height;
  174. tx = ty = 0;
  175. tw = totalRect.width;
  176. th = totalRect.height;
  177. }
  178. else
  179. {
  180. x = clamp( m_nLeft.Get(), currentRect.x, currentRect.x + currentRect.width );
  181. y = clamp( m_nTop.Get(), currentRect.y, currentRect.y + currentRect.height );
  182. int x1 = clamp( m_nLeft + m_nWidth, currentRect.x, currentRect.x + currentRect.width );
  183. int y1 = clamp( m_nTop + m_nHeight, currentRect.y, currentRect.y + currentRect.height );
  184. w = x1 - x;
  185. h = y1 - y;
  186. tx = m_nLeft;
  187. ty = m_nTop;
  188. tw = m_nWidth;
  189. th = m_nHeight;
  190. // Clipped...
  191. if ( w <= 0 || h <= 0 )
  192. return;
  193. }
  194. if ( tw == 0 || th == 0 )
  195. return;
  196. // Compute texture coordinate range of the entire texture
  197. int mw = m_OverlayMaterial->GetMappingWidth();
  198. int mh = m_OverlayMaterial->GetMappingHeight();
  199. // Compute the texture coords in texels we want over the entire image
  200. float uMin = 0;
  201. float uMax = mw;
  202. float vMin = 0;
  203. float vMax = mh;
  204. if ( m_bUseSubRect )
  205. {
  206. uMin = m_nSubRectLeft;
  207. vMin = m_nSubRectTop;
  208. uMax = uMin + m_nSubRectWidth;
  209. vMax = vMin + m_nSubRectHeight;
  210. }
  211. if ( m_flMovementSpeed )
  212. {
  213. float flRadians = M_PI * m_flMovementAngle / 180.0f;
  214. float dUdT = -m_flMovementSpeed * cos( flRadians );
  215. float dVdT = m_flMovementSpeed * sin( flRadians );
  216. float dU = time.GetSeconds() * dUdT;
  217. float dV = time.GetSeconds() * dVdT;
  218. uMin += dU; uMax += dU;
  219. vMin += dV; vMax += dV;
  220. }
  221. // This is the range of normalizes (u,v) coordinates over the *total* image
  222. uMin = ( uMin + 0.5f ) / mw;
  223. vMin = ( vMin + 0.5f ) / mh;
  224. uMax = ( uMax - 0.5f ) / mw;
  225. vMax = ( vMax - 0.5f ) / mh;
  226. // Now determine the subrange we should use given we're rendering a portion of the image
  227. float u0, v0, u1, v1, f;
  228. f = ( x - tx ) / tw;
  229. u0 = Lerp( f, uMin, uMax );
  230. f = ( x + w - tx ) / tw;
  231. u1 = Lerp( f, uMin, uMax );
  232. f = ( y - ty ) / th;
  233. v0 = Lerp( f, vMin, vMax );
  234. f = ( y + h - ty ) / th;
  235. v1 = Lerp( f, vMin, vMax );
  236. x -= currentRect.x;
  237. y -= currentRect.y;
  238. CMatRenderContextPtr pRenderContext( materials );
  239. if ( m_OverlayMaterial->NeedsPowerOfTwoFrameBufferTexture() )
  240. {
  241. pRenderContext->Bind( m_BltMaterial, pTextures[0] );
  242. pRenderContext->PushRenderTargetAndViewport( pTextures[1], 0, 0, w, h ); // Blt current input to temp surface
  243. DrawOneToOneQuad( w, h );
  244. pRenderContext->PopRenderTargetAndViewport();
  245. pRenderContext->SetFrameBufferCopyTexture( pTextures[1] );
  246. pRenderContext->PushRenderTargetAndViewport( pTextures[0], 0, 0, w, h ); // Render to result surface
  247. }
  248. float r, g, b, a;
  249. m_OverlayMaterial->GetColorModulation( &r, &g, &b );
  250. a = m_OverlayMaterial->GetAlphaModulation();
  251. m_OverlayMaterial->ColorModulate( m_Color.r() / 255.0f, m_Color.g() / 255.0f, m_Color.b() / 255.0f );
  252. m_OverlayMaterial->AlphaModulate( m_Color.a() / 255.0f );
  253. pRenderContext->Bind( m_OverlayMaterial );
  254. DrawQuad( x, y, w, h, u0, v0, u1, v1 );
  255. if ( m_OverlayMaterial->NeedsPowerOfTwoFrameBufferTexture() )
  256. {
  257. pRenderContext->PopRenderTargetAndViewport();
  258. }
  259. m_OverlayMaterial->ColorModulate( r, g, b );
  260. m_OverlayMaterial->AlphaModulate( a );
  261. }