#include "StdAfx.h" #include "ShadowMapProcess.h" #include "Terrain.h" #include "WaterRenderView.h" #include #include #define CAMERA_DIST 500 using namespace SceneCore; bool CShadowMapProcess::Init( CTerrain * pTerrain, NiRenderer *pRenderer, NiCamera *pCamera, NiRenderView *pMainRenderView, NiPoint3 vLitDir ) { int iChunkX = pTerrain->GetChunkNumX(); int iChunkY = pTerrain->GetChunkNumY(); if ( iChunkX <= 0 || iChunkY <= 0 ) return false; if ( !pRenderer || ! pCamera || !pMainRenderView ) return false; //NiPoint3 kTerrainCenter(iChunkX*GRIDINCHUNK*0.5f, iChunkY*GRIDINCHUNK*0.5f, 0.0f); //bool bDirectionLight = pTerrain->GetDirectionLightDir( m_vLightDir ); //if ( !bDirectionLight ) return false; m_pTerrain = pTerrain; m_spMainRenderView = pMainRenderView; m_spHelpCamera = NiNew NiCamera; //m_spHelpCamera->SetWorldTranslate(kTerrainCenter-vLitDir); //m_spHelpCamera->LookAtWorldPoint(kTerrainCenter); //m_spHelpCamera-> //m_spHelpCamera->SetViewFrustum( pCamera->GetViewFrustum() ); //m_spHelpCamera->SetTranslate( pCamera->GetWorldTranslate()); //m_spHelpCamera->SetRotate( pCamera->GetWorldRotate() ); //m_spHelpCamera-> //NiCamera kCamera; //NiFrustum kFrustum(-iNumChunksX*GRIDINCHUNK/2, iNumChunksX*GRIDINCHUNK/2, // iNumChunksY*GRIDINCHUNK/2, -iNumChunksY*GRIDINCHUNK/2, 0.1f, 1000.0f, true); //kCamera.SetTranslate(iNumChunksX*GRIDINCHUNK/2, iNumChunksY*GRIDINCHUNK/2, 500); //kCamera.LookAtWorldPoint(NiPoint3(iNumChunksX*GRIDINCHUNK/2, iNumChunksY*GRIDINCHUNK/2, -1000.0f), NiPoint3(0, 1, 0)); //NiPoint3 kPos = -vLitDir*100; m_spHelpCamera->SetTranslate(0,0,0); m_spHelpCamera->LookAtWorldPoint(vLitDir, NiPoint3(0, 1, 0)); m_spHelpCamera->Update(0.0f); NiFrustum kFrustum(0, iChunkX*GRIDINCHUNK, iChunkY*GRIDINCHUNK, 0, 0.1f, 1000.0f, true); m_spHelpCamera->SetViewFrustum(kFrustum); m_spHelpCamera->Update(0.0f); //m_spHelpCamera = pCamera; // @step1 load shadow map material m_spDepthMtl = NiSingleShaderMaterial::Create( "Depth" ); m_spShadowMapMtl= NiSingleShaderMaterial::Create( "ShadowMap" ); if ( !m_spDepthMtl || !m_spShadowMapMtl ) return false; // @step2 load blurU/blurV material //m_spBlurUMapMtl = NiSingleShaderMaterial::Create( "SM_BlurU" ); //m_spBlurVMapMtl = NiSingleShaderMaterial::Create( "SM_BlurV" ); //if ( !m_spBlurUMapMtl || !m_spBlurVMapMtl ) goto err; unsigned int uiWidth = iChunkX * BLENDTEX_SIZE; //SHADOWMAP_SIZE_CHUNK; unsigned int uiHeight = iChunkY * BLENDTEX_SIZE; //SHADOWMAP_SIZE_CHUNK; m_spDepthMap = NiRenderedTexture::Create( uiWidth, uiHeight, pRenderer, NiTexture::FormatPrefs::FLOAT_COLOR_32 ); m_spBlurUMap = NiRenderedTexture::Create( uiWidth, uiHeight, pRenderer ); m_spBlurVMap = NiRenderedTexture::Create( uiWidth, uiHeight, pRenderer ); m_spShadowMap = NiRenderedTexture::Create( uiWidth, uiHeight, pRenderer ); //@ step4 m_spRTGroupDepth = NiRenderTargetGroup::Create( m_spDepthMap->GetBuffer(), pRenderer, true, true ); m_spRTGroupBlurU = NiRenderTargetGroup::Create( m_spBlurUMap->GetBuffer(), pRenderer, true, true ); m_spRTGroupBlurV = NiRenderTargetGroup::Create( m_spBlurVMap->GetBuffer(), pRenderer, true, true ); m_spRTGroupShadowMap = NiRenderTargetGroup::Create( m_spShadowMap->GetBuffer(), pRenderer, true, true ); if ( !m_spDepthMap || !m_spBlurUMap || !m_spBlurVMap ) goto err; if ( !m_spRTGroupDepth || !m_spRTGroupBlurU || !m_spRTGroupBlurV ) goto err; m_spRenderStep = NiNew NiDefaultClickRenderStep; NiViewRenderClick *pRenderClick = NiNew NiViewRenderClick; pRenderClick->AppendRenderView( pMainRenderView ); pRenderClick->SetClearAllBuffers(true); pRenderClick->SetRenderTargetGroup( m_spRTGroupDepth ); pRenderClick->SetPreProcessingCallbackFunc( _PreDepthCallback, this ); pRenderClick->SetPostProcessingCallbackFunc( _PostDepthCallback, this ); m_spRenderStep->AppendRenderClick( pRenderClick ); pRenderClick = NiNew NiViewRenderClick; pRenderClick->AppendRenderView( pMainRenderView ); pRenderClick->SetClearAllBuffers(true); pRenderClick->SetRenderTargetGroup( m_spRTGroupShadowMap ); pRenderClick->SetPreProcessingCallbackFunc( _PreShadowMapCallback, this ); pRenderClick->SetPostProcessingCallbackFunc( _PostShadowMapCallback, this ); m_spRenderStep->AppendRenderClick( pRenderClick ); return true; err: UnInit(); return false; } void CShadowMapProcess::Do( NiEntityRenderingContext* pkRenderingContext ) { // Backup current render target group. const NiRenderTargetGroup* pkCurRenderTarget = pkRenderingContext ->m_pkRenderer->GetCurrentRenderTargetGroup(); if (NULL != pkCurRenderTarget) { pkRenderingContext->m_pkRenderer->EndUsingRenderTargetGroup(); } //NIASSERT(pkCurRenderTarget != NULL); NiRenderer* pkRenderer = NiRenderer::GetRenderer(); //pkRenderer->BeginOffScreenFrame(); CWaterRenderView* pWaterRenderView = NiDynamicCast( CWaterRenderView, m_spMainRenderView ); pWaterRenderView->SetAlwaysUseCameraViewport( true ); pWaterRenderView->SetCamera( m_spHelpCamera ); m_spRenderStep->SetActive(true); m_spRenderStep->Render(); //pkRenderer->EndOffScreenFrame(); // Restore previous render target group. if (pkRenderingContext->m_pkRenderer->IsRenderTargetGroupActive()) pkRenderingContext->m_pkRenderer->EndUsingRenderTargetGroup(); if (NULL != pkCurRenderTarget) { pkRenderingContext->m_pkRenderer->BeginUsingRenderTargetGroup( (NiRenderTargetGroup*) pkCurRenderTarget, NiRenderer::CLEAR_NONE); } } void CShadowMapProcess::UnInit() { m_spHelpCamera= 0; m_spDepthMap = 0; m_spBlurUMap = 0; m_spBlurVMap = 0; m_spShadowMap = 0; //@ step4 m_spRTGroupDepth = 0; m_spRTGroupBlurU = 0; m_spRTGroupBlurV = 0; m_spRTGroupShadowMap = 0; m_spRenderStep = 0; } bool CShadowMapProcess::_PreDepthCallback( NiRenderClick* pkCurrentRenderClick, void* pvCallbackData ) { CShadowMapProcess* pThis = static_cast< CShadowMapProcess* >( pvCallbackData ); pThis->_setCameraInLightSpace(); NiRenderView *pRenderView = pThis->m_spMainRenderView; const NiVisibleArray& kVisibleArray = pRenderView->GetPVGeometry(0); for( unsigned int i = 0; i < kVisibleArray.GetCount(); ++i ) { NiGeometry& kGeom = kVisibleArray.GetAt( i ); kGeom.ApplyAndSetActiveMaterial( pThis->m_spDepthMtl ); kGeom.GetPropertyState()->GetStencil()->SetDrawMode(NiStencilProperty::DRAW_BOTH); } return true; } bool CShadowMapProcess::_PostDepthCallback( NiRenderClick* pkCurrentRenderClick, void* pvCallbackData ) { //CShadowMapProcess* pThis = static_cast< CShadowMapProcess* >( pvCallbackData ); //bool bChanged = true; //bool bMipMap = false; //bool bNonPow2 = false; //NiDX9Renderer* pRenderer = NiDynamicCast( NiDX9Renderer, NiRenderer::GetRenderer() ); //LPDIRECT3DBASETEXTURE9 pD3DTex = pRenderer->GetTextureManager() // ->PrepareTextureForRendering( pThis->m_spDepthMap, bChanged, bMipMap, bNonPow2 ); //HRESULT hr = D3DXSaveTextureToFile( "e:/depth.dds", D3DXIFF_DDS, pD3DTex, NULL ); //return ( hr!= E_FAIL ); return true; } bool CShadowMapProcess::_PreShadowMapCallback( NiRenderClick* pkCurrentRenderClick, void* pvCallbackData ) { CShadowMapProcess* pThis = static_cast< CShadowMapProcess* >( pvCallbackData ); // update camera matrix in light space NiDX9Renderer* pRenderer = NiDynamicCast( NiDX9Renderer, NiRenderer::GetRenderer() ); D3DXMATRIX mtxView = pRenderer->GetD3DView(); D3DXMATRIX mtxProj = pRenderer->GetD3DProj(); D3DXMATRIX mtxLightViewProj; D3DXMatrixMultiply( &mtxLightViewProj, &mtxView, &mtxProj ); bool b = NiShaderFactory::UpdateGlobalShaderConstant( "g_LightViewProj", sizeof(float)*4*4,mtxLightViewProj ); // reset camera in ortho space pThis->_setCameraInOrthoSpace(); NiRenderView *pRenderView = pThis->m_spMainRenderView; const NiVisibleArray& kVisibleArray = pRenderView->GetPVGeometry(0); for( unsigned int i = 0; i < kVisibleArray.GetCount(); ++i ) { NiGeometry& kGeom = kVisibleArray.GetAt( i ); kGeom.DetachAllProperties(); NiTexturingProperty * pTexProp = NiNew NiTexturingProperty; pTexProp->SetApplyMode( NiTexturingProperty::APPLY_MODULATE ); NiTexturingProperty::ShaderMap* pShaderMap = NiNew NiTexturingProperty::ShaderMap( pThis->m_spDepthMap, 0 ); pTexProp->SetShaderMap( 0, pShaderMap ); kGeom.AttachProperty( pTexProp ); kGeom.ApplyAndSetActiveMaterial( pThis->m_spShadowMapMtl ); kGeom.UpdateProperties(); } return true; } void CShadowMapProcess::_setCameraInLightSpace() {} void CShadowMapProcess::_setCameraInOrthoSpace() { NiPoint2 vSize = m_pTerrain->GetTotalSize(); NiPoint3 vTerrainCenter = NiPoint3( vSize.x * 0.5f, vSize.y * 0.5f, 0 ); NiPoint3 vLightPos = vTerrainCenter + NiPoint3( 0, 0, 1 ) * CAMERA_DIST; NiFrustum kFrustum( -vTerrainCenter.x, vTerrainCenter.x, vTerrainCenter.y, -vTerrainCenter.y, 0.1f, 2000, true ); kFrustum.m_bOrtho = true; m_spHelpCamera->SetViewFrustum( kFrustum ); NiPoint3 vUp( 0.0f, 1.0f, .0f ); //y NiPoint3 vRight; NiPoint3 vLookAt; //x vLookAt = NiPoint3( 0, 0, -1); vLookAt.Unitize(); vRight = vLookAt.UnitCross( vUp ); vUp = vRight.UnitCross( vLookAt ); vLookAt = vUp.UnitCross( vRight ); NiMatrix3 matCamera; matCamera.SetCol( 0, vLookAt ); matCamera.SetCol( 1, vUp ); matCamera.SetCol( 2, vRight ); m_spHelpCamera->SetRotate( matCamera ); m_spHelpCamera->SetTranslate( vLightPos ); m_spHelpCamera->Update( .0f ); } bool CShadowMapProcess::_PostShadowMapCallback( NiRenderClick* pkCurrentRenderClick, void* pvCallbackData ) { //CShadowMapProcess* pThis = static_cast< CShadowMapProcess* >( pvCallbackData ); //bool bChanged = true; //bool bMipMap = false; //bool bNonPow2 = false; //NiDX9Renderer* pRenderer = NiDynamicCast( NiDX9Renderer, NiRenderer::GetRenderer() ); //LPDIRECT3DBASETEXTURE9 pD3DTex = pRenderer->GetTextureManager() // ->PrepareTextureForRendering( pThis->m_spShadowMap, bChanged, bMipMap, bNonPow2 ); //HRESULT hr = D3DXSaveTextureToFile( "e:/shadowmap.dds", D3DXIFF_DDS, pD3DTex, NULL ); //return ( hr!= E_FAIL ); return true; } NiRenderedTexturePtr CShadowMapProcess::GetShadowTexture() { return m_spShadowMap; }