#include "StdAfx.h" #include "EtShadowMap.h" #include "EtLiSPShadowMap.h" #include "EtTrapezoidShadowMap.h" #include "EtSprite.h" #include "EtDrawQuad.h" #include "EtOptionController.h" #ifdef _DEBUG #define new new(_NORMAL_BLOCK,__FILE__,__LINE__) #endif CEtShadowMap *g_pEtShadowMap = NULL; CEtShadowMap::CEtShadowMap(void) { m_fShadowRange = 500.0f; m_fDistanceLightAt = 500.0f; m_ShadowColor = EtColor( 0.0f, 0.0f, 0.0f, 1.0f ); m_ShadowMapFormat = FMT_UNKNOWN; EtMatrixIdentity(&m_LightViewMat); D3DXMatrixTranslation(&m_LightProjMat, 0.0f, 0.0f, -10000.0f ); m_LightProjMat._11 = m_LightProjMat._22 = m_LightProjMat._33 = 0.f; m_LightProjDepthMat = m_LightProjMat; m_bEnable = true; SGraphicOption Option; GetEtOptionController()->GetGraphicOption( Option ); m_bUseSoftShadow = Option.bSoftShadow; m_nVertexDecl = -1; m_pBackupDepthTarget = NULL; m_pBackupRenderTarget = NULL; } CEtShadowMap::~CEtShadowMap(void) { Clear(); } void CEtShadowMap::Clear() { SAFE_RELEASE_SPTR( m_hShadowMap ); SAFE_RELEASE_SPTR( m_hShadowMapDepth ); SAFE_RELEASE_SPTR( m_hShadowMaterial ); SAFE_RELEASE_SPTR( m_hBlurShadowMap ); } void CEtShadowMap::Initialize( ShadowQuality Quality, ShadowType Type ) { switch( Quality ) { case SQ_HIGH: m_nShadowMapSize = m_bUseSoftShadow ? 1024 : 2048; break; case SQ_NORMAL: m_nShadowMapSize = 1024; break; case SQ_NONE: m_nShadowMapSize = 512; m_bEnable = false; break; default: m_nShadowMapSize = 1024; m_bEnable = false; break; } EtFormat ShadowFormat; m_ShadowType = Type; if( m_ShadowType == ST_SHADOWMAP ) { ShadowFormat = FMT_R5G6B5; } else if( m_ShadowType == ST_DEPTHSHADOWMAP ) { ShadowFormat = FMT_R32F; } else { ShadowFormat = FMT_UNKNOWN; } if( ( !m_hShadowMap ) || ( m_hShadowMap->Width() != m_nShadowMapSize ) || ( ShadowFormat != m_ShadowMapFormat ) ) { SAFE_RELEASE_SPTR( m_hShadowMap ); SAFE_RELEASE_SPTR( m_hBlurShadowMap ); SAFE_RELEASE_SPTR( m_hShadowMapDepth ); m_ShadowMapFormat = ShadowFormat; m_hShadowMap = CEtTexture::CreateRenderTargetTexture( m_nShadowMapSize, m_nShadowMapSize, ShadowFormat ); m_hShadowMap->SetFileName( "EtShadowMap" ); if( m_bUseSoftShadow ) { m_hBlurShadowMap = CEtTexture::CreateRenderTargetTexture( 3 * m_nShadowMapSize / 4, 3 * m_nShadowMapSize / 4, ShadowFormat ); m_hBlurShadowMap->SetFileName( "EtBlurShadowMap" ); } if( m_ShadowType == ST_DEPTHSHADOWMAP ) { m_hShadowMapDepth = CEtDepth::CreateDepthStencil( m_nShadowMapSize, m_nShadowMapSize ); m_hShadowMapDepth->SetFileName( "EtShadowMapDepth" ); } } if( m_bUseSoftShadow ) { D3DVERTEXELEMENT9 VertexElement[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; m_nVertexDecl = GetEtDevice()->CreateVertexDeclaration( VertexElement ); } ResetRenderTarget(); } void CEtShadowMap::LoadMaterial() { if( m_bUseSoftShadow && !m_hShadowMaterial && CEtResourceMng::IsActive() ) { m_hShadowMaterial = ::LoadResource( "Shadow.fx", RT_SHADER, true ); int nTexIndex = m_hShadowMap->GetMyIndex(); ::AddCustomParam( m_vecCustomParam, EPT_TEX, m_hShadowMaterial, "g_ShadowMapTex", &nTexIndex ); } } void CEtShadowMap::CalcShadowMat() { EtMatrix *pInvViewMat; SLightInfo *pLightInfo; EtVector3 Eye, At, CamDir; pLightInfo = CEtLight::GetShadowCastDirLightInfo(); pInvViewMat = CEtCamera::GetActiveCamera()->GetInvViewMat(); CamDir = *( EtVector3 * )&pInvViewMat->_31; CamDir.y = 0.0f; EtVec3Normalize( &CamDir, &CamDir ); At = *( EtVector3 * )&pInvViewMat->_41 + CamDir * m_fDistanceLightAt; Eye = At - pLightInfo->Direction * 10000.0f; EtMatrixLookAtLH( &m_LightViewMat, &Eye, &At, &EtVector3( 0.0f, 1.0f, 0.0f ) ); EtMatrixOrthoLH( &m_LightProjMat, m_fShadowRange * 2.0f, m_fShadowRange * 2.0f, 10.0f, 100000.0f ); m_LightProjDepthMat = m_LightProjMat; } void CEtShadowMap::BeginShadow() { m_pBackupRenderTarget = GetEtDevice()->GetRenderTarget(); m_pBackupDepthTarget = GetEtDevice()->GetDepthStencilSurface(); GetEtDevice()->SetRenderTarget( m_hShadowMap->GetSurfaceLevel() ); if( m_ShadowType == ST_DEPTHSHADOWMAP ) { //GetEtDevice()->SetCullMode( CULL_CW ); GetEtDevice()->SetDepthStencilSurface( m_hShadowMapDepth->GetDepthBuffer() ); } else if( m_ShadowType == ST_SHADOWMAP ) { GetEtDevice()->EnableZ( false ); GetEtDevice()->SetDepthStencilSurface( NULL ); } GetEtDevice()->ClearBuffer( 0xFFFFFFFF, 1.0f, 0, true, true, false); } void CEtShadowMap::EndShadow() { if( m_ShadowType == ST_DEPTHSHADOWMAP ) { //GetEtDevice()->SetCullMode( CULL_CCW ); } else if( m_ShadowType == ST_SHADOWMAP ) { GetEtDevice()->EnableZ( true ); } if( m_bUseSoftShadow ) { DownSampling(); } GetEtDevice()->SetRenderTarget( m_pBackupRenderTarget ); GetEtDevice()->SetDepthStencilSurface( m_pBackupDepthTarget ); } void CEtShadowMap::ClearBuffer() { LoadMaterial(); if( !m_hShadowMaterial ) return; GetEtDevice()->EnableZ( false ); int nPasses = 0; m_hShadowMaterial->SetTechnique( 3 ); m_hShadowMaterial->BeginEffect( nPasses ); m_hShadowMaterial->BeginPass( 0 ); m_hShadowMaterial->CommitChanges(); float fDepth = 0.999f; STextureVertex Vertices[4]; Vertices[ 0 ].Position = EtVector3( -1, 1, fDepth ); Vertices[ 0 ].TexCoordinate = EtVector2( 0, 0 ); Vertices[ 1 ].Position = EtVector3( 1, 1, fDepth ); Vertices[ 1 ].TexCoordinate = EtVector2( 1, 0 ); Vertices[ 2 ].Position = EtVector3( -1, -1, fDepth); Vertices[ 2 ].TexCoordinate = EtVector2( 0, 1 ); Vertices[ 3 ].Position = EtVector3( 1, -1, fDepth ); Vertices[ 3 ].TexCoordinate = EtVector2( 1, 1); GetEtDevice()->SetVertexDeclaration( m_nVertexDecl ); GetEtDevice()->DrawPrimitiveUP( PT_TRIANGLESTRIP, 2, Vertices, sizeof( STextureVertex ) ); m_hShadowMaterial->EndPass(); m_hShadowMaterial->EndEffect(); GetEtDevice()->EnableZ( true ); } void CEtShadowMap::DownSampling() { LoadMaterial(); if( !m_hShadowMaterial ) return; int nPasses = 0; GetEtDevice()->EnableZ( false ); GetEtDevice()->SetRenderTarget( m_hBlurShadowMap->GetSurfaceLevel() ); GetEtDevice()->SetDepthStencilSurface( NULL ); m_hShadowMaterial->SetTechnique( 2 ); m_hShadowMaterial->BeginEffect( nPasses ); m_hShadowMaterial->BeginPass( 0 ); m_hShadowMaterial->SetCustomParamList( m_vecCustomParam ); m_hShadowMaterial->CommitChanges(); STextureVertex Vertices[4]; Vertices[ 0 ].Position = EtVector3( -1, 1, 0 ); Vertices[ 0 ].TexCoordinate = EtVector2( 0, 0 ); Vertices[ 1 ].Position = EtVector3( 1, 1, 0 ); Vertices[ 1 ].TexCoordinate = EtVector2( 1, 0 ); Vertices[ 2 ].Position = EtVector3( -1, -1, 0); Vertices[ 2 ].TexCoordinate = EtVector2( 0, 1 ); Vertices[ 3 ].Position = EtVector3( 1, -1, 0 ); Vertices[ 3 ].TexCoordinate = EtVector2( 1, 1); GetEtDevice()->SetVertexDeclaration( m_nVertexDecl ); GetEtDevice()->DrawPrimitiveUP( PT_TRIANGLESTRIP, 2, Vertices, sizeof( STextureVertex ) ); m_hShadowMaterial->EndPass(); m_hShadowMaterial->EndEffect(); GetEtDevice()->EnableZ( true ); } void CEtShadowMap::ResetShadowMap() { m_pBackupRenderTarget = GetEtDevice()->GetRenderTarget(); m_pBackupDepthTarget = GetEtDevice()->GetDepthStencilSurface(); GetEtDevice()->SetRenderTarget( m_hShadowMap->GetSurfaceLevel() ); if( m_hShadowMapDepth ) { GetEtDevice()->SetDepthStencilSurface( m_hShadowMapDepth->GetDepthBuffer() ); } GetEtDevice()->ClearBuffer( 0xffffffff, 1.0f, 0 ); GetEtDevice()->SetRenderTarget( m_pBackupRenderTarget ); GetEtDevice()->SetDepthStencilSurface( m_pBackupDepthTarget ); EtMatrixIdentity(&m_LightViewMat); D3DXMatrixTranslation(&m_LightProjMat, 0.0f, 0.0f, -10000.0f ); m_LightProjMat._11 = m_LightProjMat._22 = m_LightProjMat._33 = 0.f; m_LightProjDepthMat = m_LightProjMat; } void CEtShadowMap::DebugRender() { SUICoord UVCoord, ScreenCoord; CEtSprite::GetInstance().Begin( 0 ); UVCoord.SetCoord( 0.0f, 0.0f, 1.0f, 1.0f ); ScreenCoord.SetCoord( 0.55f, 0.65f, 0.2f, 0.3f ); CEtSprite::GetInstance().DrawSprite( (EtTexture*)m_hBlurShadowMap->GetTexturePtr(), m_hBlurShadowMap->Width(), m_hBlurShadowMap->Height(), UVCoord, 0xffffffff, ScreenCoord, 0.0f ); CEtSprite::GetInstance().End(); } EtBaseTexture * CEtShadowMap::GetShadowMapTexture() { if( m_bUseSoftShadow ) { if( m_hBlurShadowMap ) { return m_hBlurShadowMap->GetTexturePtr(); } else { return NULL; } } else { if( m_hShadowMap ) { return m_hShadowMap->GetTexturePtr(); } else { return NULL; } } } void CEtShadowMap::Bake( CEtRenderStack *pStack ) { if( m_bEnable ) { BeginShadow(); CalcShadowMat(); pStack->RenderBlock( CEtRenderStack::PASS_SHADOW ); EndShadow(); } else { pStack->ClearElement( CEtRenderStack::PASS_SHADOW ); } } void CEtShadowMap::ResetRenderTarget() { m_pBackupRenderTarget = GetEtDevice()->GetRenderTarget(); m_pBackupDepthTarget = GetEtDevice()->GetDepthStencilSurface(); GetEtDevice()->SetRenderTarget( m_hShadowMap->GetSurfaceLevel() ); if( m_hShadowMapDepth ) GetEtDevice()->SetDepthStencilSurface( m_hShadowMapDepth->GetDepthBuffer() ); GetEtDevice()->ClearBuffer( 0xFFFFFFFF, 1.0f, 0, true, true, false); GetEtDevice()->SetRenderTarget( m_pBackupRenderTarget ); GetEtDevice()->SetDepthStencilSurface( m_pBackupDepthTarget ); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////// CEtShadowMap *GetEtShadowMap() { return g_pEtShadowMap; } void DeleteShadowMap() { SAFE_DELETE( g_pEtShadowMap ); } void CreateSimpleSahdowMap( ShadowQuality Quality, ShadowType Type ) { SAFE_DELETE( g_pEtShadowMap ); g_pEtShadowMap = new CEtTrapezoidShadowMap; g_pEtShadowMap->Initialize( Quality, Type ); }