diff options
Diffstat (limited to 'movieobjects/dmematerialoverlayfxclip.cpp')
| -rw-r--r-- | movieobjects/dmematerialoverlayfxclip.cpp | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/movieobjects/dmematerialoverlayfxclip.cpp b/movieobjects/dmematerialoverlayfxclip.cpp new file mode 100644 index 0000000..3fb62b1 --- /dev/null +++ b/movieobjects/dmematerialoverlayfxclip.cpp @@ -0,0 +1,270 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "movieobjects/dmematerialoverlayfxclip.h" +#include "datamodel/dmelementfactoryhelper.h" +#include "materialsystem/imesh.h" +#include "materialsystem/imaterial.h" +#include "tier1/KeyValues.h" +#include "tier1/convar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// CDmeClip - common base class for filmclips, soundclips, and channelclips +//----------------------------------------------------------------------------- +IMPLEMENT_FX_CLIP_ELEMENT_FACTORY( DmeMaterialOverlayFXClip, CDmeMaterialOverlayFXClip, "Material Overlay Effect" ); + +void CDmeMaterialOverlayFXClip::OnConstruction() +{ + m_Material.Init( this, "material" ); + m_Color.Init( this, "overlaycolor" ); + m_nLeft.Init( this, "left" ); + m_nTop.Init( this, "top" ); + m_nWidth.Init( this, "width" ); + m_nHeight.Init( this, "height" ); + m_bFullScreen.Init( this, "fullscreen" ); + m_bUseSubRect.Init( this, "useSubRect" ); + m_flMovementAngle.Init( this, "movementAngle" ); + m_flMovementSpeed.Init( this, "movementSpeed" ); + m_nSubRectLeft.Init( this, "subRectLeft" ); + m_nSubRectTop.Init( this, "subRectTop" ); + m_nSubRectWidth.Init( this, "subRectWidth" ); + m_nSubRectHeight.Init( this, "subRectHeight" ); + + m_Color.SetColor( 255, 255, 255, 255 ); + m_bFullScreen = true; + m_nLeft = m_nTop = 0; + m_nWidth = m_nHeight = 1; +} + +void CDmeMaterialOverlayFXClip::OnDestruction() +{ +} + + +//----------------------------------------------------------------------------- +// Resolve +//----------------------------------------------------------------------------- +void CDmeMaterialOverlayFXClip::Resolve() +{ + if ( m_Material.IsDirty() ) + { + m_OverlayMaterial.Shutdown(); + const char *pName = m_Material.Get(); + if ( pName && pName[0] ) + { + m_OverlayMaterial.Init( pName, NULL, false ); + } + m_Material.GetAttribute()->RemoveFlag( FATTRIB_DIRTY ); + } +} + + +//----------------------------------------------------------------------------- +// Helper for overlays +//----------------------------------------------------------------------------- +void CDmeMaterialOverlayFXClip::SetOverlayEffect( const char *pMaterialName ) +{ + m_Material = pMaterialName; +} + +void CDmeMaterialOverlayFXClip::SetAlpha( float flAlpha ) +{ + m_Color.SetAlpha( flAlpha * 255 ); +} + +float CDmeMaterialOverlayFXClip::GetAlpha( void ) +{ + return ( (float)m_Color.a() ) / 255.0f; +} + +bool CDmeMaterialOverlayFXClip::HasOpaqueOverlay( void ) +{ + if ( m_OverlayMaterial ) + return ( !m_OverlayMaterial->IsTranslucent() && ( m_Color.a() == 255 ) && m_bFullScreen ); + + // no material overlay set + return false; +} + +IMaterial *CDmeMaterialOverlayFXClip::GetMaterial() +{ + return m_OverlayMaterial; +} + + +//----------------------------------------------------------------------------- +// All effects must be able to apply their effect +//----------------------------------------------------------------------------- +void CDmeMaterialOverlayFXClip::ApplyEffect( DmeTime_t time, Rect_t ¤tRect, Rect_t &totalRect, ITexture *pTextures[MAX_FX_INPUT_TEXTURES] ) +{ + if ( !m_OverlayMaterial || m_Color.a() == 0 ) + return; + + time = ToChildMediaTime( time, false ); + + // Clip the overlay rectangle to the currently drawn one + int x, y, w, h; + int tx, ty, tw, th; + if ( m_bFullScreen ) + { + x = currentRect.x; + y = currentRect.y; + w = currentRect.width; + h = currentRect.height; + tx = ty = 0; + tw = totalRect.width; + th = totalRect.height; + } + else + { + x = clamp( m_nLeft, currentRect.x, currentRect.x + currentRect.width ); + y = clamp( m_nTop, currentRect.y, currentRect.y + currentRect.height ); + int x1 = clamp( m_nLeft + m_nWidth, currentRect.x, currentRect.x + currentRect.width ); + int y1 = clamp( m_nTop + m_nHeight, currentRect.y, currentRect.y + currentRect.height ); + w = x1 - x; + h = y1 - y; + + tx = m_nLeft; + ty = m_nTop; + tw = m_nWidth; + th = m_nHeight; + + // Clipped... + if ( w <= 0 || h <= 0 ) + return; + } + + if ( tw == 0 || th == 0 ) + return; + + // Compute texture coordinate range of the entire texture + int mw = m_OverlayMaterial->GetMappingWidth(); + int mh = m_OverlayMaterial->GetMappingHeight(); + + // Compute the texture coords in texels we want over the entire image + float uMin = 0; + float uMax = mw; + float vMin = 0; + float vMax = mh; + + if ( m_bUseSubRect ) + { + uMin = m_nSubRectLeft; + vMin = m_nSubRectTop; + uMax = uMin + m_nSubRectWidth; + vMax = vMin + m_nSubRectHeight; + } + + if ( m_flMovementSpeed ) + { + float flRadians = M_PI * m_flMovementAngle / 180.0f; + float dUdT = -m_flMovementSpeed * cos( flRadians ); + float dVdT = m_flMovementSpeed * sin( flRadians ); + float dU = time.GetSeconds() * dUdT; + float dV = time.GetSeconds() * dVdT; + uMin += dU; uMax += dU; + vMin += dV; vMax += dV; + } + + // This is the range of normalizes (u,v) coordinates over the *total* image + uMin = ( uMin + 0.5f ) / mw; + vMin = ( vMin + 0.5f ) / mh; + uMax = ( uMax - 0.5f ) / mw; + vMax = ( vMax - 0.5f ) / mh; + + // Now determine the subrange we should use given we're rendering a portion of the image + float u0, v0, u1, v1, f; + + f = ( x - tx ) / tw; + u0 = Lerp( f, uMin, uMax ); + + f = ( x + w - tx ) / tw; + u1 = Lerp( f, uMin, uMax ); + + f = ( y - ty ) / th; + v0 = Lerp( f, vMin, vMax ); + + f = ( y + h - ty ) / th; + v1 = Lerp( f, vMin, vMax ); + + x -= currentRect.x; + y -= currentRect.y; + + if ( m_OverlayMaterial->NeedsPowerOfTwoFrameBufferTexture() ) + { + CMatRenderContextPtr pRenderContext( materials ); + ITexture *pTexture = materials->FindTexture( "_rt_PowerOfTwoFB", TEXTURE_GROUP_RENDER_TARGET ); + + // forced or only once per frame + Rect_t rect; + rect.x = 0; + rect.y = 0; + rect.width = currentRect.width; + rect.height = currentRect.height; + pRenderContext->CopyRenderTargetToTextureEx( pTexture, 0, &rect, NULL ); + pRenderContext->SetFrameBufferCopyTexture( pTexture ); + } + + float r, g, b, a; + m_OverlayMaterial->GetColorModulation( &r, &g, &b ); + a = m_OverlayMaterial->GetAlphaModulation(); + + m_OverlayMaterial->ColorModulate( m_Color.r() / 255.0f, m_Color.g() / 255.0f, m_Color.b() / 255.0f ); + m_OverlayMaterial->AlphaModulate( m_Color.a() / 255.0f ); + + CMatRenderContextPtr pRenderContext( materials ); + pRenderContext->Bind( m_OverlayMaterial ); + + IMesh *pMesh = pRenderContext->GetDynamicMesh(); + CMeshBuilder meshBuilder; + meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 ); + + meshBuilder.Position3f( x, y, 0.0f ); + meshBuilder.BoneWeight( 0, 1.0f ); + meshBuilder.BoneMatrix( 0, 0 ); + meshBuilder.Color4ub( 255, 255, 255, 255 ); + meshBuilder.TexCoord2f( 0, u0, v0 ); + meshBuilder.TexCoord2f( 1, 0.0f, 0.0f ); + meshBuilder.TexCoord2f( 2, 0.0f, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3f( x, y+h, 0.0f ); + meshBuilder.BoneWeight( 0, 1.0f ); + meshBuilder.BoneMatrix( 0, 0 ); + meshBuilder.Color4ub( 255, 255, 255, 255 ); + meshBuilder.TexCoord2f( 0, u0, v1 ); + meshBuilder.TexCoord2f( 1, 0.0f, 1.0f ); + meshBuilder.TexCoord2f( 2, 0.0f, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3f( x+w, y, 0.0f ); + meshBuilder.BoneWeight( 0, 1.0f ); + meshBuilder.BoneMatrix( 0, 0 ); + meshBuilder.Color4ub( 255, 255, 255, 255 ); + meshBuilder.TexCoord2f( 0, u1, v0 ); + meshBuilder.TexCoord2f( 1, 1.0f, 0.0f ); + meshBuilder.TexCoord2f( 2, 0.0f, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3f( x+w, y+h, 0.0f ); + meshBuilder.BoneWeight( 0, 1.0f ); + meshBuilder.BoneMatrix( 0, 0 ); + meshBuilder.Color4ub( 255, 255, 255, 255 ); + meshBuilder.TexCoord2f( 0, u1, v1 ); + meshBuilder.TexCoord2f( 1, 1.0f, 1.0f ); + meshBuilder.TexCoord2f( 2, 0.0f, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.End(); + pMesh->Draw(); + + m_OverlayMaterial->ColorModulate( r, g, b ); + m_OverlayMaterial->AlphaModulate( a ); +} + |