Optimise func_fake_worldportal render code

Consistent and descriptive variable names, simplified calculations.
This commit is contained in:
samisalreadytaken 2022-11-17 08:48:10 +03:00
parent 713c8e8cf3
commit cc0c90693d
4 changed files with 70 additions and 169 deletions

View File

@ -58,70 +58,11 @@ bool C_FuncFakeWorldPortal::ShouldDraw()
} }
//-----------------------------------------------------------------------------
// Do we have a fake world portal in view?
//-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane )
{
// Early out if no cameras
C_FuncFakeWorldPortal *pReflectiveGlass = GetFakeWorldPortalList();
if ( !pReflectiveGlass )
return NULL;
Frustum_t frustum;
GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum );
cplane_t localPlane;
Vector vecOrigin, vecWorld, vecDelta, vecForward;
AngleVectors( view.angles, &vecForward, NULL, NULL );
for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext )
{
if ( pReflectiveGlass->IsDormant() )
continue;
if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) )
continue;
Vector vecMins, vecMaxs;
pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs );
if ( R_CullBox( vecMins, vecMaxs, frustum ) )
continue;
const model_t *pModel = pReflectiveGlass->GetModel();
const matrix3x4_t& mat = pReflectiveGlass->EntityToWorldTransform();
int nCount = modelinfo->GetBrushModelPlaneCount( pModel );
for ( int i = 0; i < nCount; ++i )
{
modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin );
MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space
VectorTransform( vecOrigin, mat, vecWorld );
if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane
continue;
VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull
if ( vecDelta.Dot( plane.normal ) >= 0 )
continue;
// Must have valid plane
if ( !pReflectiveGlass->m_hTargetPlane )
continue;
return pReflectiveGlass;
}
}
return NULL;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Iterates through fake world portals instead of just picking one // Iterates through fake world portals instead of just picking one
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum ) Vector &vecAbsPlaneNormal, Vector &vecPlaneLocalOrigin, const Frustum_t &frustum )
{ {
// Early out if no cameras // Early out if no cameras
C_FuncFakeWorldPortal *pReflectiveGlass = NULL; C_FuncFakeWorldPortal *pReflectiveGlass = NULL;
@ -130,8 +71,9 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
else else
pReflectiveGlass = pStart->m_pNext; pReflectiveGlass = pStart->m_pNext;
cplane_t localPlane; cplane_t localPlane, worldPlane;
Vector vecOrigin, vecWorld, vecDelta; Vector vecMins, vecMaxs, vecLocalOrigin, vecAbsOrigin, vecDelta;
for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext ) for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext )
{ {
if ( pReflectiveGlass->IsDormant() ) if ( pReflectiveGlass->IsDormant() )
@ -140,7 +82,10 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) ) if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) )
continue; continue;
Vector vecMins, vecMaxs; // Must have valid plane
if ( !pReflectiveGlass->m_hTargetPlane )
continue;
pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs ); pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs );
if ( R_CullBox( vecMins, vecMaxs, frustum ) ) if ( R_CullBox( vecMins, vecMaxs, frustum ) )
continue; continue;
@ -151,23 +96,22 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
int nCount = modelinfo->GetBrushModelPlaneCount( pModel ); int nCount = modelinfo->GetBrushModelPlaneCount( pModel );
for ( int i = 0; i < nCount; ++i ) for ( int i = 0; i < nCount; ++i )
{ {
modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin ); modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecLocalOrigin );
MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space MatrixTransformPlane( mat, localPlane, worldPlane ); // Transform to world space
VectorTransform( vecOrigin, mat, vecWorld );
if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane if ( view.origin.Dot( worldPlane.normal ) <= worldPlane.dist ) // Check for view behind plane
continue; continue;
VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull VectorTransform( vecLocalOrigin, mat, vecAbsOrigin );
if ( vecDelta.Dot( plane.normal ) >= 0 ) VectorSubtract( vecAbsOrigin, view.origin, vecDelta );
if ( vecDelta.Dot( worldPlane.normal ) >= 0 ) // Backface cull
continue; continue;
// Must have valid plane vecPlaneLocalOrigin = vecLocalOrigin;
if ( !pReflectiveGlass->m_hTargetPlane ) vecAbsPlaneNormal = worldPlane.normal;
continue;
vecPlaneOrigin = vecOrigin;
return pReflectiveGlass; return pReflectiveGlass;
} }
} }

View File

@ -53,10 +53,8 @@ public:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Do we have reflective glass in view? If so, what's the reflection plane? // Do we have reflective glass in view? If so, what's the reflection plane?
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane );
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum ); Vector &vecAbsPlaneNormal, Vector &vecPlaneOrigin, const Frustum_t &frustum );
#endif // C_FUNC_FAKE_WORLDPORTAL #endif // C_FUNC_FAKE_WORLDPORTAL

View File

@ -2106,20 +2106,18 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
Frustum_t frustum; Frustum_t frustum;
GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum ); GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum );
cplane_t portalPlane; Vector vecAbsPlaneNormal;
Vector vecPlaneOrigin; Vector vecPlaneLocalOrigin;
//C_FuncFakeWorldPortal *pPortalEnt = IsFakeWorldPortalInView( view, portalPlane ); C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, vecAbsPlaneNormal, vecPlaneLocalOrigin, frustum );
//if ( pPortalEnt )
C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, portalPlane, vecPlaneOrigin, frustum );
while ( pPortalEnt != NULL ) while ( pPortalEnt != NULL )
{ {
ITexture *pCameraTarget = pPortalEnt->RenderTarget(); ITexture *pCameraTarget = pPortalEnt->RenderTarget();
int width = pCameraTarget->GetActualWidth(); int width = pCameraTarget->GetActualWidth();
int height = pCameraTarget->GetActualHeight(); int height = pCameraTarget->GetActualHeight();
DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, portalPlane, vecPlaneOrigin ); DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, vecAbsPlaneNormal, vecPlaneLocalOrigin );
pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, portalPlane, vecPlaneOrigin, frustum ); pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, vecAbsPlaneNormal, vecPlaneLocalOrigin, frustum );
} }
#endif #endif
} }
@ -3537,8 +3535,6 @@ bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_Poin
} }
#ifdef MAPBASE #ifdef MAPBASE
ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Sets up scene and renders WIP fake world portal view. // Purpose: Sets up scene and renders WIP fake world portal view.
// Based on code from monitors, mirrors, and logic_measure_movement. // Based on code from monitors, mirrors, and logic_measure_movement.
@ -3555,7 +3551,7 @@ ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer, bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer,
int x, int y, int width, int height, int x, int y, int width, int height,
const CViewSetup &mainView, cplane_t &ourPlane, const Vector &vecPlaneOrigin ) const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, const Vector &vecPlaneLocalOrigin )
{ {
#ifdef USE_MONITORS #ifdef USE_MONITORS
VPROF_INCREMENT_COUNTER( "cameras rendered", 1 ); VPROF_INCREMENT_COUNTER( "cameras rendered", 1 );
@ -3586,85 +3582,52 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
} }
} }
monitorView.width = width;
monitorView.height = height;
monitorView.x = x; monitorView.x = x;
monitorView.y = y; monitorView.y = y;
monitorView.width = width;
monitorView.origin = mainView.origin; monitorView.height = height;
monitorView.angles = mainView.angles;
// Debug stuff
static float flLastDebugTime = 0.0f;
bool bDebug = r_fakeworldportal_debug.GetBool() && gpGlobals->curtime > flLastDebugTime;
//
// Calculate the angles for the fake portal plane
//
QAngle angTargetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() - pCameraEnt->m_PlaneAngles;
QAngle angFakePortalAngles;
// Get vectors from our original angles.
Vector vOurForward, vOurRight, vOurUp;
AngleVectors( pCameraEnt->GetAbsAngles(), &vOurForward, &vOurRight, &vOurUp );
Quaternion quat;
BasisToQuaternion( ourPlane.normal, vOurRight, vOurUp, quat );
QuaternionAngles( quat, angFakePortalAngles );
if (bDebug)
{
// RED - Initial player origin
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 0, 0, 128, 10.0f );
// YELLOW - Portal origin
debugoverlay->AddBoxOverlay( pCameraEnt->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angFakePortalAngles, 255, 224, 0, 128, 10.0f );
}
//
// Translate the actual portal view position to be relative to the target
//
matrix3x4_t matPlayer, matPortal, matPlayerToPortal;
AngleIMatrix( monitorView.angles, monitorView.origin, matPlayer );
AngleMatrix( angFakePortalAngles, pCameraEnt->GetAbsOrigin(), matPortal );
ConcatTransforms( matPlayer, matPortal, matPlayerToPortal );
// Apply the scale factor
if ( pCameraEnt->m_flScale > 0 )
{
Vector vecTranslation;
MatrixGetColumn( matPlayerToPortal, 3, vecTranslation );
vecTranslation /= pCameraEnt->m_flScale;
MatrixSetColumn( vecTranslation, 3, matPlayerToPortal );
}
matrix3x4_t matTarget;
AngleMatrix( angTargetAngles, pCameraEnt->m_hTargetPlane->GetAbsOrigin(), matTarget );
// Now apply the new matrix to the new reference point
matrix3x4_t matPortalToPlayer, matNewPlayerPosition;
MatrixInvert( matPlayerToPortal, matPortalToPlayer );
ConcatTransforms( matTarget, matPortalToPlayer, matNewPlayerPosition );
MatrixAngles( matNewPlayerPosition, monitorView.angles, monitorView.origin );
if (bDebug)
{
// BLUE - Target origin
debugoverlay->AddBoxOverlay( pCameraEnt->m_hTargetPlane->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angTargetAngles, 0, 0, 255, 128, 10.0f );
// GREEN - Final origin
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 255, 0, 128, 10.0f );
flLastDebugTime = gpGlobals->curtime + 5.0f;
}
monitorView.fov = mainView.fov;
monitorView.m_bOrtho = mainView.m_bOrtho; monitorView.m_bOrtho = mainView.m_bOrtho;
monitorView.fov = mainView.fov;
monitorView.m_flAspectRatio = mainView.m_flAspectRatio; monitorView.m_flAspectRatio = mainView.m_flAspectRatio;
monitorView.m_bViewToProjectionOverride = false; monitorView.m_bViewToProjectionOverride = false;
matrix3x4_t worldToView;
AngleIMatrix( mainView.angles, mainView.origin, worldToView );
matrix3x4_t targetToWorld;
{
// NOTE: m_PlaneAngles is angle offset
QAngle targetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() - pCameraEnt->m_PlaneAngles;
AngleMatrix( targetAngles, pCameraEnt->m_hTargetPlane->GetAbsOrigin(), targetToWorld );
}
matrix3x4_t portalToWorld;
{
Vector left, up;
VectorVectors( vecAbsPlaneNormal, left, up );
VectorNegate( left );
portalToWorld.Init( vecAbsPlaneNormal, left, up, pCameraEnt->GetAbsOrigin() );
}
matrix3x4_t portalToView;
ConcatTransforms( worldToView, portalToWorld, portalToView );
if ( pCameraEnt->m_flScale > 0.0f )
{
portalToView[0][3] /= pCameraEnt->m_flScale;
portalToView[1][3] /= pCameraEnt->m_flScale;
portalToView[2][3] /= pCameraEnt->m_flScale;
}
matrix3x4_t viewToPortal;
MatrixInvert( portalToView, viewToPortal );
matrix3x4_t newViewToWorld;
ConcatTransforms( targetToWorld, viewToPortal, newViewToWorld );
MatrixAngles( newViewToWorld, monitorView.angles, monitorView.origin );
// @MULTICORE (toml 8/11/2006): this should be a renderer.... // @MULTICORE (toml 8/11/2006): this should be a renderer....
int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL); int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL);
bool bDrew3dSkybox = false; bool bDrew3dSkybox = false;
@ -3687,21 +3650,17 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
SafeRelease( pSkyView ); SafeRelease( pSkyView );
} }
//
// Make a clipping plane for the target view
//
Vector4D plane; Vector4D plane;
Vector vecAnglesNormal; MatrixGetColumn( targetToWorld, 0, plane.AsVector3D() );
AngleVectors( angTargetAngles, &vecAnglesNormal ); VectorNormalize( plane.AsVector3D() );
VectorNormalize( vecAnglesNormal ); VectorNegate( plane.AsVector3D() );
VectorCopy( -vecAnglesNormal, plane.AsVector3D() );
// The portal plane's distance from the actual brush's origin // The portal plane's distance from the actual brush's origin
float flPlaneDist = vecPlaneOrigin.Length(); float flPlaneDist = vecPlaneLocalOrigin.Length();
// The target's distance from world origin // The target's distance from world origin
plane.w = -((pCameraEnt->m_hTargetPlane->GetAbsOrigin() * vecAnglesNormal).Length() + flPlaneDist) + 0.1f; plane.w = -((pCameraEnt->m_hTargetPlane->GetAbsOrigin() * plane.AsVector3D()).Length() + flPlaneDist) + 0.1f;
CMatRenderContextPtr pRenderContext( materials ); CMatRenderContextPtr pRenderContext( materials );
pRenderContext->PushCustomClipPlane( plane.Base() ); pRenderContext->PushCustomClipPlane( plane.Base() );

View File

@ -454,7 +454,7 @@ private:
#ifdef MAPBASE #ifdef MAPBASE
bool DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer, bool DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer,
int x, int y, int width, int height, int x, int y, int width, int height,
const CViewSetup &mainView, cplane_t &ourPlane, const Vector &vecPlaneOrigin ); const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, const Vector &vecPlaneOrigin );
#endif #endif
// Drawing primitives // Drawing primitives