337 lines
20 KiB
C++
337 lines
20 KiB
C++
|
||
#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 );
|
||
}
|