summaryrefslogtreecommitdiff
path: root/game/client/portal/c_func_liquidportal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/portal/c_func_liquidportal.cpp')
-rw-r--r--game/client/portal/c_func_liquidportal.cpp630
1 files changed, 630 insertions, 0 deletions
diff --git a/game/client/portal/c_func_liquidportal.cpp b/game/client/portal/c_func_liquidportal.cpp
new file mode 100644
index 0000000..9365102
--- /dev/null
+++ b/game/client/portal/c_func_liquidportal.cpp
@@ -0,0 +1,630 @@
+//========= 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 &currentView, 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 );
+ }
+}
+
+