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
270 lines
7.7 KiB
//========= 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 ); |
|
} |
|
|
|
|