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.
132 lines
4.2 KiB
132 lines
4.2 KiB
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//===========================================================================//
|
|
|
|
#ifndef FRUSTUM_H
|
|
#define FRUSTUM_H
|
|
|
|
#include "mathlib/camera.h"
|
|
#include "mathlib/ssemath.h"
|
|
#include "worldrenderer/bvhsupport.h"
|
|
|
|
|
|
class CWorldRenderFrustum : public CFrustum
|
|
{
|
|
|
|
public:
|
|
//
|
|
// Slight modification of
|
|
// http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_vrcia/shadow_vrcia.pdf
|
|
//
|
|
float CalculateSplitPlaneDistance( int nSplit, int nShadowSplits, float flMaxShadowDistance )
|
|
{
|
|
float fIM = (float)nSplit / (float)nShadowSplits;
|
|
float f = MIN( flMaxShadowDistance, m_camera.m_flZFar );
|
|
float n = m_camera.m_flZNear;
|
|
float fBias = 0.1f;
|
|
float flLog = n + ( n * powf( f / n, fIM ) );
|
|
float flLinear = ( n + ( f - n ) * fIM );
|
|
return ( flLog * 0.9f + flLinear * 0.10f ) + fBias;
|
|
}
|
|
|
|
void UpdateLightFrustumFromClippedVolume( float flNear, float flFar )
|
|
{
|
|
//VMatrix mLightProj = OrthoMatrixRH( m_fSplitXSize, m_fSplitZSize, MAX( m_camera.m_flZNear, flNear ), MIN( m_camera.m_flZFar, flFar ) );
|
|
VMatrix mLightProj = OrthoMatrixRH( m_fSplitXSize, m_fSplitZSize, flNear, flFar );
|
|
SetProj( mLightProj );
|
|
CalcViewProj();
|
|
}
|
|
|
|
void SetSplitSizes( float flXSize, float flZSize ) { m_fSplitXSize = flXSize; m_fSplitZSize = flZSize; }
|
|
|
|
void CalculateLightFrusta( CWorldRenderFrustum **ppOutFrustums, int nShadowSplits, Vector vLightDir, float flLightDistance, float flLightFarPlane, float flMaxShadowDistance )
|
|
{
|
|
float fPreviousSplit = m_camera.m_flZNear;
|
|
Vector vEye = m_camera.m_origin;
|
|
Vector vEyeDir = m_forward;
|
|
vEyeDir.NormalizeInPlace();
|
|
vLightDir.NormalizeInPlace();
|
|
|
|
for( int i=0; i<nShadowSplits; i++ )
|
|
{
|
|
float fSplitPlane = CalculateSplitPlaneDistance( i + 1, nShadowSplits, flMaxShadowDistance );
|
|
|
|
float fZDist = fSplitPlane - fPreviousSplit;
|
|
float fCenterZ = ( fPreviousSplit + fSplitPlane ) * 0.5f;
|
|
|
|
float fXSize = tanf( DEG2RAD(m_camera.m_flFOVX) * 0.5f ) * fSplitPlane * 2.0f;
|
|
fXSize += ( nShadowSplits - i ) * 12.0f;
|
|
fZDist *= 1.10f;
|
|
|
|
#if ( SNAP_SHADOW_MAP == 1 )
|
|
fXSize = max( fXSize, fZDist );
|
|
fZDist = fXSize;
|
|
#endif
|
|
|
|
Vector vLightLookAt = vEye + vEyeDir * fCenterZ;
|
|
Vector vLightPosition = vLightLookAt + vLightDir * flLightDistance;
|
|
|
|
// Create the light frustum
|
|
VMatrix mLightView;
|
|
VMatrix mLightProj;
|
|
#if ( SNAP_SHADOW_MAP == 1 )
|
|
Vector vFrustumUp( 0,1,0 );
|
|
#else
|
|
Vector vFrustumUp = vEyeDir;
|
|
#endif
|
|
mLightView = ViewMatrixRH( vLightPosition, vLightLookAt, vFrustumUp );
|
|
|
|
#if ( SNAP_SHADOW_MAP == 1 )
|
|
// Clamp camera movement to full-pixels only
|
|
float fUnitsPerTexel = fXSize / (float)g_ShadowDepthTextureSize;
|
|
mLightView._41 = floorf( mLightView._41 / fUnitsPerTexel ) * fUnitsPerTexel;
|
|
mLightView._42 = floorf( mLightView._42 / fUnitsPerTexel ) * fUnitsPerTexel;
|
|
#endif
|
|
|
|
CWorldRenderFrustum *pOutFrustum = (ppOutFrustums)[i];
|
|
|
|
mLightProj = OrthoMatrixRH( fXSize, fZDist, m_camera.m_flZNear, flLightFarPlane );
|
|
pOutFrustum->SetSplitSizes( fXSize, fZDist );
|
|
|
|
pOutFrustum->SetView( mLightView );
|
|
pOutFrustum->SetProj( mLightProj );
|
|
pOutFrustum->CalcViewProj();
|
|
pOutFrustum->SetCameraPosition( vLightPosition );
|
|
Vector vLightForward;
|
|
Vector vLightLeft;
|
|
Vector vLightUp;
|
|
VMatrix mView( pOutFrustum->GetView() );
|
|
MatrixGetRow( mView, 0, &vLightLeft );
|
|
MatrixGetRow( mView, 1, &vLightUp );
|
|
MatrixGetRow( mView, 2, &vLightForward );
|
|
Vector vLightRight = -vLightLeft;
|
|
vLightForward = -vLightForward;
|
|
|
|
pOutFrustum->SetNearFarPlanes( m_camera.m_flZNear, flLightFarPlane );
|
|
pOutFrustum->SetForward( -vLightDir );
|
|
|
|
Frustum_t lightFrustum;
|
|
VPlane pSixPlanes[6];
|
|
GenerateOrthoFrustum( vec3_origin, vLightForward, vLightRight, vLightUp,
|
|
-fXSize/2.0f, fXSize/2.0f, -fZDist/2.0f, fZDist/2.0f,
|
|
m_camera.m_flZNear, flLightFarPlane,
|
|
pSixPlanes );
|
|
lightFrustum.SetPlanes( pSixPlanes );
|
|
pOutFrustum->SetFrustum( lightFrustum );
|
|
|
|
fPreviousSplit = fSplitPlane;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
float m_fSplitXSize;
|
|
float m_fSplitZSize;
|
|
};
|
|
|
|
|
|
|
|
#endif
|