mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-26 08:06:58 +00:00
631 lines
22 KiB
C++
631 lines
22 KiB
C++
//========= 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 );
|
|
}
|
|
}
|
|
|
|
|