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.
630 lines
22 KiB
630 lines
22 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Rising liquid that acts as a one-way portal |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "c_func_liquidportal.h" |
|
#include "debugoverlay_shared.h" |
|
#include "view_scene.h" |
|
#include "view.h" |
|
#include "ScreenSpaceEffects.h" |
|
#include "materialsystem/imaterialvar.h" |
|
|
|
|
|
LINK_ENTITY_TO_CLASS( func_liquidportal, C_Func_LiquidPortal ); |
|
|
|
IMPLEMENT_CLIENTCLASS_DT( C_Func_LiquidPortal, DT_Func_LiquidPortal, CFunc_LiquidPortal ) |
|
RecvPropEHandle( RECVINFO(m_hLinkedPortal) ), |
|
RecvPropFloat( RECVINFO(m_fFillStartTime) ), |
|
RecvPropFloat( RECVINFO(m_fFillEndTime) ), |
|
END_RECV_TABLE() |
|
|
|
|
|
#define LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( vertnum, xtexbase, xtexscale, ytexbase, ytexscale )\ |
|
meshBuilder.Position3fv( &vVertices[vertnum].x );\ |
|
meshBuilder.TexCoord2f( 0, vVertices[vertnum].xtexbase * xtexscale, vVertices[vertnum].ytexbase * ytexscale );\ |
|
meshBuilder.AdvanceVertex(); |
|
|
|
|
|
C_Func_LiquidPortal::C_Func_LiquidPortal( void ) |
|
{ |
|
g_pPortalRender->AddPortal( this ); |
|
} |
|
|
|
C_Func_LiquidPortal::~C_Func_LiquidPortal( void ) |
|
{ |
|
g_pPortalRender->RemovePortal( this ); |
|
} |
|
|
|
|
|
int C_Func_LiquidPortal::DrawModel( int flags ) |
|
{ |
|
if( IsFillingNow() ) |
|
{ |
|
DrawPortal(); |
|
return 1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
void C_Func_LiquidPortal::OnDataChanged( DataUpdateType_t updateType ) |
|
{ |
|
GetRenderBoundsWorldspace( m_vAABBMins, m_vAABBMaxs ); |
|
m_pLinkedPortal = m_hLinkedPortal.Get(); |
|
ComputeLinkMatrix(); |
|
UpdateBoundingPlanes(); |
|
} |
|
|
|
void C_Func_LiquidPortal::ComputeLinkMatrix( void ) |
|
{ |
|
C_Func_LiquidPortal *pLinkedPortal = m_hLinkedPortal.Get(); |
|
if( pLinkedPortal ) |
|
{ |
|
VMatrix matLocalToWorld, matLocalToWorldInv, matRemoteToWorld; |
|
|
|
//matLocalToWorld.Identity(); |
|
//matLocalToWorld.SetTranslation( CollisionProp()->WorldSpaceCenter() ); |
|
matLocalToWorld = EntityToWorldTransform(); |
|
|
|
//matRemoteToWorld.Identity(); |
|
//matRemoteToWorld.SetTranslation( pLinkedPortal->CollisionProp()->WorldSpaceCenter() ); |
|
matRemoteToWorld = pLinkedPortal->EntityToWorldTransform(); |
|
|
|
MatrixInverseTR( matLocalToWorld, matLocalToWorldInv ); |
|
m_matrixThisToLinked = matRemoteToWorld * matLocalToWorldInv; |
|
|
|
MatrixInverseTR( m_matrixThisToLinked, pLinkedPortal->m_matrixThisToLinked ); |
|
} |
|
else |
|
{ |
|
m_matrixThisToLinked.Identity(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
void CPortalRenderable_Func_LiquidPortal::UpdateBoundingPlanes( void ) |
|
{ |
|
//x min |
|
m_fBoundingPlanes[0][0] = 1.0f; |
|
m_fBoundingPlanes[0][1] = 0.0f; |
|
m_fBoundingPlanes[0][2] = 0.0f; |
|
m_fBoundingPlanes[0][3] = m_vAABBMins.x; |
|
|
|
//x max |
|
m_fBoundingPlanes[1][0] = -1.0f; |
|
m_fBoundingPlanes[1][1] = 0.0f; |
|
m_fBoundingPlanes[1][2] = 0.0f; |
|
m_fBoundingPlanes[1][3] = -m_vAABBMaxs.x; |
|
|
|
|
|
//y min |
|
m_fBoundingPlanes[2][0] = 0.0f; |
|
m_fBoundingPlanes[2][1] = 1.0f; |
|
m_fBoundingPlanes[2][2] = 0.0f; |
|
m_fBoundingPlanes[2][3] = m_vAABBMins.y; |
|
|
|
//y max |
|
m_fBoundingPlanes[3][0] = 0.0f; |
|
m_fBoundingPlanes[3][1] = -1.0f; |
|
m_fBoundingPlanes[3][2] = 0.0f; |
|
m_fBoundingPlanes[3][3] = -m_vAABBMaxs.y; |
|
|
|
|
|
//z min |
|
m_fBoundingPlanes[4][0] = 0.0f; |
|
m_fBoundingPlanes[4][1] = 0.0f; |
|
m_fBoundingPlanes[4][2] = 1.0f; |
|
m_fBoundingPlanes[4][3] = m_vAABBMins.z; |
|
|
|
//z max is too variable to store |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::DrawPreStencilMask( void ) |
|
{ |
|
// Should we do something here like flatbasic? |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::DrawStencilMask( void ) |
|
{ |
|
DrawOutwardBox( g_pPortalRender->m_MaterialsAccess.m_WriteZ_Model ); |
|
DrawInnerLiquid( true, 1.0f, g_pPortalRender->m_MaterialsAccess.m_WriteZ_Model ); |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::DrawPostStencilFixes( void ) |
|
{ |
|
DrawOutwardBox( g_pPortalRender->m_MaterialsAccess.m_WriteZ_Model ); |
|
DrawInnerLiquid( true, 1.0f, g_pPortalRender->m_MaterialsAccess.m_WriteZ_Model ); |
|
} |
|
|
|
|
|
void CPortalRenderable_Func_LiquidPortal::RenderPortalViewToBackBuffer( CViewRender *pViewRender, const CViewSetup &cameraView ) |
|
{ |
|
if( m_pLinkedPortal == NULL ) //not linked to any portal |
|
return; |
|
|
|
Frustum FrustumBackup; |
|
memcpy( FrustumBackup, pViewRender->GetFrustum(), sizeof( Frustum ) ); |
|
|
|
Frustum seeThroughFrustum; |
|
bool bUseSeeThroughFrustum; |
|
|
|
if ( g_pPortalRender->GetViewRecursionLevel() == 0 ) |
|
{ |
|
bUseSeeThroughFrustum = CalcFrustumThroughPortal( cameraView.origin, seeThroughFrustum, pViewRender->GetFrustum(), FRUSTUM_NUMPLANES ); |
|
} |
|
else |
|
{ |
|
bUseSeeThroughFrustum = CalcFrustumThroughPortal( cameraView.origin, seeThroughFrustum ); |
|
} |
|
|
|
Vector vCameraForward; |
|
AngleVectors( cameraView.angles, &vCameraForward, NULL, NULL ); |
|
|
|
// Setup fog state for the camera. |
|
Vector ptPOVOrigin = m_matrixThisToLinked * cameraView.origin; |
|
Vector vPOVForward = m_matrixThisToLinked.ApplyRotation( vCameraForward ); |
|
|
|
CViewSetup portalView = cameraView; |
|
|
|
QAngle qPOVAngles = TransformAnglesToWorldSpace( cameraView.angles, m_matrixThisToLinked.As3x4() ); |
|
|
|
portalView.width = cameraView.width; |
|
portalView.height = cameraView.height; |
|
portalView.x = 0; |
|
portalView.y = 0; |
|
portalView.origin = ptPOVOrigin; |
|
portalView.angles = qPOVAngles; |
|
portalView.fov = cameraView.fov; |
|
portalView.m_bOrtho = false; |
|
portalView.m_flAspectRatio = cameraView.m_flAspectRatio; //use the screen aspect ratio, 0.0f doesn't work as advertised |
|
|
|
CopyToCurrentView( pViewRender, portalView ); |
|
|
|
CMatRenderContextPtr pRenderContext( materials ); |
|
|
|
{ |
|
ViewCustomVisibility_t customVisibility; |
|
m_pLinkedPortal->AddToVisAsExitPortal( &customVisibility ); |
|
render->Push3DView( portalView, 0, NULL, pViewRender->GetFrustum() ); |
|
{ |
|
if( bUseSeeThroughFrustum) |
|
memcpy( pViewRender->GetFrustum(), seeThroughFrustum, sizeof( Frustum ) ); |
|
|
|
render->OverrideViewFrustum( pViewRender->GetFrustum() ); |
|
SetViewRecursionLevel( g_pPortalRender->GetViewRecursionLevel() + 1 ); |
|
|
|
CPortalRenderable *pRenderingViewForPortalBackup = g_pPortalRender->GetCurrentViewEntryPortal(); |
|
CPortalRenderable *pRenderingViewExitPortalBackup = g_pPortalRender->GetCurrentViewExitPortal(); |
|
SetViewEntranceAndExitPortals( this, m_pLinkedPortal ); |
|
|
|
//DRAW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
ViewDrawScene_PortalStencil( pViewRender, portalView, &customVisibility ); |
|
|
|
SetViewEntranceAndExitPortals( pRenderingViewForPortalBackup, pRenderingViewExitPortalBackup ); |
|
|
|
SetViewRecursionLevel( g_pPortalRender->GetViewRecursionLevel() - 1 ); |
|
} |
|
render->PopView( pViewRender->GetFrustum() ); |
|
|
|
//restore old frustum |
|
memcpy( pViewRender->GetFrustum(), FrustumBackup, sizeof( Frustum ) ); |
|
render->OverrideViewFrustum( FrustumBackup ); |
|
} |
|
|
|
//restore old vis data |
|
CopyToCurrentView( pViewRender, cameraView ); |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::RenderPortalViewToTexture( CViewRender *pViewRender, const CViewSetup &cameraView ) |
|
{ |
|
|
|
} |
|
|
|
|
|
void CPortalRenderable_Func_LiquidPortal::AddToVisAsExitPortal( ViewCustomVisibility_t *pCustomVisibility ) |
|
{ |
|
if ( !pCustomVisibility ) |
|
return; |
|
|
|
VisOverrideData_t visOverride; |
|
Vector vOrigin = (m_vAABBMins + m_vAABBMaxs) * 0.5f; |
|
|
|
visOverride.m_vecVisOrigin = vOrigin; |
|
visOverride.m_fDistToAreaPortalTolerance = 64.0f; |
|
|
|
// Specify which leaf to use for area portal culling |
|
pCustomVisibility->ForceVisOverride( visOverride ); |
|
pCustomVisibility->ForceViewLeaf( enginetrace->GetLeafContainingPoint( vOrigin ) ); |
|
|
|
pCustomVisibility->AddVisOrigin( vOrigin ); |
|
} |
|
|
|
bool CPortalRenderable_Func_LiquidPortal::DoesExitViewIntersectWaterPlane( float waterZ, int leafWaterDataID ) const |
|
{ |
|
return ((m_vAABBMins.z < waterZ) && (m_vAABBMaxs.z > waterZ)); |
|
} |
|
|
|
SkyboxVisibility_t CPortalRenderable_Func_LiquidPortal::SkyBoxVisibleFromPortal( void ) |
|
{ |
|
return SKYBOX_NOT_VISIBLE; |
|
} |
|
|
|
|
|
bool CPortalRenderable_Func_LiquidPortal::CalcFrustumThroughPortal( const Vector &ptCurrentViewOrigin, Frustum OutputFrustum, const VPlane *pInputFrustum, int iInputFrustumPlaneCount ) |
|
{ |
|
return false; |
|
} |
|
|
|
|
|
const Vector& CPortalRenderable_Func_LiquidPortal::GetFogOrigin( void ) const |
|
{ |
|
return vec3_origin; |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::ShiftFogForExitPortalView() const |
|
{ |
|
|
|
} |
|
|
|
|
|
bool CPortalRenderable_Func_LiquidPortal::ShouldUpdatePortalView_BasedOnView( const CViewSetup ¤tView, Frustum currentFrustum ) |
|
{ |
|
//return false; |
|
return IsFillingNow(); |
|
} |
|
|
|
CPortalRenderable* CPortalRenderable_Func_LiquidPortal::GetLinkedPortal() const |
|
{ |
|
return m_pLinkedPortal; |
|
} |
|
|
|
bool CPortalRenderable_Func_LiquidPortal::ShouldUpdateDepthDoublerTexture( const CViewSetup &viewSetup ) |
|
{ |
|
return false; |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::DrawPortal( void ) |
|
{ |
|
if( IsFillingNow() ) |
|
{ |
|
//"shadertest/gooinglass" |
|
//"glass/glasswindow_refract01" |
|
//IMaterial *pMaterial = materials->FindMaterial( "glass/glasswindow_refract01", TEXTURE_GROUP_OTHER ); |
|
//UpdateFrontBufferTexturesForMaterial( (IMaterial *)pMaterial ); |
|
|
|
DrawOutwardBox(); |
|
//DrawInnerLiquid( pMaterial ); |
|
//DrawInwardBox( pMaterial ); |
|
} |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::GetToolRecordingState( bool bActive, KeyValues *msg ) |
|
{ |
|
|
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::HandlePortalPlaybackMessage( KeyValues *pKeyValues ) |
|
{ |
|
|
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::DrawOutwardBox( const IMaterial *pMaterial ) |
|
{ |
|
if( pMaterial == NULL ) |
|
pMaterial = materials->FindMaterial( "glass/glasswindow_refract01", TEXTURE_GROUP_OTHER ); |
|
|
|
const float fVerticalTextureScale = 1.0f / 100.0f; |
|
const float fHorizontalTextureScale = 1.0f / 100.0f; |
|
|
|
float fMaxZ = m_vAABBMins.z + ((m_vAABBMaxs.z - m_vAABBMins.z) * GetFillInterpolationAmount()); |
|
|
|
Vector vVertices[8]; |
|
for( int i = 0; i != 8; ++i ) |
|
{ |
|
vVertices[i].x = (i&(1<<0)) ? m_vAABBMaxs.x : m_vAABBMins.x; |
|
vVertices[i].y = (i&(1<<1)) ? m_vAABBMaxs.y : m_vAABBMins.y; |
|
vVertices[i].z = (i&(1<<2)) ? fMaxZ : m_vAABBMins.z; |
|
} |
|
|
|
CMatRenderContextPtr pRenderContext( materials ); |
|
pRenderContext->Bind( (IMaterial *)pMaterial, (CPortalRenderable_Func_LiquidPortal*)this ); |
|
|
|
CMeshBuilder meshBuilder; |
|
IMesh* pMesh = pRenderContext->GetDynamicMesh( false ); |
|
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 6 ); |
|
|
|
//x min |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 2, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 6, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 4, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 0, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
//x max |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 1, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 5, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 7, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 3, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
//y min |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 0, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 4, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 5, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 1, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
//y max |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 3, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 7, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 6, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 2, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
|
|
//z min |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 1, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 3, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 2, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 0, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
|
|
//z max |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 4, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 6, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 7, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 5, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
|
|
meshBuilder.End(); |
|
pMesh->Draw(); |
|
pRenderContext->Flush( false ); |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::DrawInwardBox( const IMaterial *pMaterial ) |
|
{ |
|
if( pMaterial == NULL ) |
|
pMaterial = materials->FindMaterial( "glass/glasswindow_refract01", TEXTURE_GROUP_OTHER ); |
|
|
|
const float fVerticalTextureScale = 1.0f / 100.0f; |
|
const float fHorizontalTextureScale = 1.0f / 100.0f; |
|
|
|
float fMaxZ = m_vAABBMins.z + ((m_vAABBMaxs.z - m_vAABBMins.z) * GetFillInterpolationAmount()); |
|
|
|
Vector vVertices[8]; |
|
for( int i = 0; i != 8; ++i ) |
|
{ |
|
vVertices[i].x = (i&(1<<0)) ? m_vAABBMaxs.x : m_vAABBMins.x; |
|
vVertices[i].y = (i&(1<<1)) ? m_vAABBMaxs.y : m_vAABBMins.y; |
|
vVertices[i].z = (i&(1<<2)) ? fMaxZ : m_vAABBMins.z; |
|
} |
|
|
|
CMatRenderContextPtr pRenderContext( materials ); |
|
pRenderContext->Bind( (IMaterial *)pMaterial, (CPortalRenderable_Func_LiquidPortal*)this ); |
|
|
|
CMeshBuilder meshBuilder; |
|
IMesh* pMesh = pRenderContext->GetDynamicMesh( false ); |
|
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 6 ); |
|
|
|
//x min |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 0, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 4, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 6, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 2, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
//x max |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 3, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 7, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 5, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 1, y, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
//y min |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 1, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 5, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 4, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 0, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
//y max |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 2, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 6, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 7, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 3, x, fHorizontalTextureScale, z, -fVerticalTextureScale ); |
|
|
|
|
|
//z min |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 0, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 2, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 3, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 1, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
|
|
//z max |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 5, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 7, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 6, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
LIQUIDPORTAL_DYNAMICMESH_BOX_ADDVERTEX( 4, x, fHorizontalTextureScale, y, fVerticalTextureScale ); |
|
|
|
meshBuilder.End(); |
|
pMesh->Draw(); |
|
pRenderContext->Flush( false ); |
|
} |
|
|
|
void CPortalRenderable_Func_LiquidPortal::DrawInnerLiquid( bool bClipToBounds, float fOpacity, const IMaterial *pMaterial ) //quads in front of camera clipped to box dimensions |
|
{ |
|
if( !IsFillingNow() && bClipToBounds ) |
|
return; |
|
|
|
PortalMeshPoint_t WorkVertices[4]; |
|
|
|
//view->GetViewSetup()->zNear; |
|
Vector vForward, vUp, vRight, vOrigin; |
|
vForward = CurrentViewForward(); |
|
vUp = CurrentViewUp(); |
|
vRight = CurrentViewRight(); |
|
|
|
//vOrigin = CurrentViewOrigin() + vForward * (view->GetViewSetup()->zNear + 0.011f); //experimentation has shown this to be the optimal distance on the Nvidia 6800 cards we develop on |
|
vOrigin = CurrentViewOrigin() + vForward * (view->GetViewSetup()->zNear + 1.0f ); |
|
|
|
const float fScalingAmount = 5.0f; |
|
|
|
WorkVertices[0].texCoord.x = fScalingAmount; |
|
WorkVertices[0].texCoord.y = fScalingAmount; |
|
|
|
WorkVertices[1].texCoord.x = fScalingAmount; |
|
WorkVertices[1].texCoord.y = 0.0f; |
|
|
|
WorkVertices[2].texCoord.x = 0.0f; |
|
WorkVertices[2].texCoord.y = 0.0f; |
|
|
|
WorkVertices[3].texCoord.x = 0.0f; |
|
WorkVertices[3].texCoord.y = fScalingAmount; |
|
|
|
|
|
WorkVertices[0].vWorldSpacePosition = vOrigin + (vRight * 40.0f) + (vUp * -40.0f); |
|
WorkVertices[1].vWorldSpacePosition = vOrigin + (vRight * 40.0f) + (vUp * 40.0f); |
|
WorkVertices[2].vWorldSpacePosition = vOrigin + (vRight * -40.0f) + (vUp * 40.0f); |
|
WorkVertices[3].vWorldSpacePosition = vOrigin + (vRight * -40.0f) + (vUp * -40.0f); |
|
|
|
PortalMeshPoint_t *pInVerts = (PortalMeshPoint_t *)stackalloc( 4 * (6) * 2 * sizeof( PortalMeshPoint_t ) ); //really only should need 2x points, but I'm paranoid |
|
PortalMeshPoint_t *pOutVerts = (PortalMeshPoint_t *)stackalloc( 4 * (6) * 2 * sizeof( PortalMeshPoint_t ) ); |
|
|
|
PortalMeshPoint_t *pFinalVerts; |
|
int iVertCount; |
|
if( bClipToBounds ) |
|
{ |
|
PortalMeshPoint_t *pTempVerts; |
|
|
|
//clip by first plane and put output into pInVerts |
|
iVertCount = ClipPolyToPlane_LerpTexCoords( WorkVertices, 4, pInVerts, Vector( 0.0f, 0.0f, -1.0f ), -(m_vAABBMins.z + ((m_vAABBMaxs.z - m_vAABBMins.z) * GetFillInterpolationAmount())), 0.01f ); |
|
|
|
//clip by other planes and flipflop in and out pointers |
|
for( int i = 0; i != 5; ++i ) |
|
{ |
|
if( iVertCount < 3 ) |
|
return; //nothing to draw |
|
|
|
iVertCount = ClipPolyToPlane_LerpTexCoords( pInVerts, iVertCount, pOutVerts, *(Vector *)m_fBoundingPlanes[i], m_fBoundingPlanes[i][3], 0.01f ); |
|
pTempVerts = pInVerts; pInVerts = pOutVerts; pOutVerts = pTempVerts; //swap vertex pointers |
|
} |
|
|
|
if( iVertCount < 3 ) |
|
return; //nothing to draw |
|
|
|
pFinalVerts = pInVerts; |
|
} |
|
else |
|
{ |
|
pFinalVerts = WorkVertices; |
|
iVertCount = 4; |
|
} |
|
|
|
bool bInterpOpacity = false; |
|
if( pMaterial == NULL ) |
|
{ |
|
pMaterial = materials->FindMaterial( "glass/glasswindow_refract01", TEXTURE_GROUP_OTHER ); |
|
bInterpOpacity = ( fOpacity != 1.0f ); |
|
} |
|
|
|
if( bInterpOpacity ) |
|
{ |
|
IMaterial *pEditMaterial = (IMaterial *)pMaterial; //we'll be making changes, then changing it back |
|
|
|
IMaterialVar *pRefractAmount = pEditMaterial->FindVar( "$refractamount", NULL ); |
|
IMaterialVar *pBlurAmount = pEditMaterial->FindVar( "$bluramount", NULL ); |
|
IMaterialVar *pTint = pEditMaterial->FindVar( "$refracttint", NULL ); |
|
|
|
float fOriginalRefractAmount = pRefractAmount->GetFloatValue(); |
|
float fOriginalBlurAmount = pBlurAmount->GetFloatValue(); |
|
Vector4D vOriginalTint; |
|
pTint->GetVecValue( &vOriginalTint.x, 4 ); |
|
|
|
Vector4D vModdedTint = vOriginalTint; |
|
|
|
pRefractAmount->SetFloatValue( fOriginalRefractAmount * fOpacity ); |
|
pBlurAmount->SetFloatValue( fOriginalBlurAmount * fOpacity ); |
|
vModdedTint.x = 1.0f - ((1.0f - vOriginalTint.x) * fOpacity); |
|
vModdedTint.y = 1.0f - ((1.0f - vOriginalTint.y) * fOpacity); |
|
vModdedTint.z = 1.0f - ((1.0f - vOriginalTint.z) * fOpacity); |
|
pTint->SetVecValue( &vModdedTint.x, 4 ); |
|
|
|
Clip_And_Render_Convex_Polygon( pFinalVerts, iVertCount, pEditMaterial, this ); |
|
materials->Flush(); |
|
|
|
pRefractAmount->SetFloatValue( fOriginalRefractAmount ); |
|
pBlurAmount->SetFloatValue( fOriginalBlurAmount ); |
|
pTint->SetVecValue( &vOriginalTint.x, 4 ); |
|
} |
|
else |
|
{ |
|
Clip_And_Render_Convex_Polygon( pFinalVerts, iVertCount, pMaterial, this ); |
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
ADD_SCREENSPACE_EFFECT( CLiquidPortal_InnerLiquidEffect, LiquidPortal_InnerLiquid ); |
|
const float CLiquidPortal_InnerLiquidEffect::s_fFadeBackEffectTime = 5.0f; |
|
|
|
|
|
CLiquidPortal_InnerLiquidEffect::CLiquidPortal_InnerLiquidEffect( void ) |
|
: m_bEnable(true), |
|
m_pImmersionPortal(NULL), |
|
m_bFadeBackToReality(false), |
|
m_fFadeBackTimeLeft(0.0f) |
|
{ |
|
} |
|
|
|
|
|
void CLiquidPortal_InnerLiquidEffect::SetParameters( KeyValues *params ) |
|
{ |
|
/*KeyValues *pImmersionPortal = params->FindKey( "immersion_portal" ); |
|
if( pImmersionPortal ) |
|
m_pImmersionPortal = (C_Func_LiquidPortal *)pImmersionPortal->GetPtr();*/ |
|
} |
|
|
|
|
|
void CLiquidPortal_InnerLiquidEffect::Render( int x, int y, int w, int h ) |
|
{ |
|
if( !m_pImmersionPortal || !m_bEnable ) |
|
return; |
|
|
|
if( m_bFadeBackToReality ) |
|
{ |
|
//effect should cover whole screen and have a alpha-like fade back to normal view |
|
m_fFadeBackTimeLeft -= gpGlobals->absoluteframetime; |
|
if( m_fFadeBackTimeLeft > 0.0f ) |
|
{ |
|
float fInterp = m_fFadeBackTimeLeft/s_fFadeBackEffectTime; |
|
|
|
//clear depth buffer so we can be all warpy on the view model too |
|
CMatRenderContextPtr pRenderContext( materials ); |
|
pRenderContext->ClearBuffers( false, true, false ); |
|
pRenderContext->OverrideDepthEnable( true, false ); |
|
|
|
m_pImmersionPortal->DrawInnerLiquid( false, fInterp ); |
|
|
|
pRenderContext->OverrideDepthEnable( false, true ); |
|
} |
|
else |
|
{ |
|
m_bFadeBackToReality = false; |
|
m_pImmersionPortal = NULL; |
|
} |
|
} |
|
else |
|
{ |
|
//effect should only cover a portion of the screen and be in full warpiness |
|
|
|
//clear depth buffer so we can be all warpy on the view model too |
|
CMatRenderContextPtr pRenderContext( materials ); |
|
pRenderContext->ClearBuffers( false, true, false ); |
|
pRenderContext->OverrideDepthEnable( true, false ); |
|
|
|
m_pImmersionPortal->DrawInnerLiquid(); |
|
|
|
pRenderContext->OverrideDepthEnable( false, true ); |
|
} |
|
} |
|
|
|
|
|
|