#include "StdAfx.h" #include "DepthAlphaEffectManager.h" #include using namespace SceneCore; CDepthAlphaEffectManagerPtr CDepthAlphaEffectManager::ms_pkInstance = NULL; CDepthAlphaEffectManager::CDepthAlphaEffectManager(void) : m_spRenderer(NULL), m_spDepthMap(NULL), m_spSceneRTG(NULL) { SetName("Depth Alpha Effect Manager"); } //---------------------------------------------------------------------------------------- CDepthAlphaEffectManager::~CDepthAlphaEffectManager(void) { //list::iterator iter = m_EffectList.begin(); //while (iter != m_EffectList.end()) //{ // (*iter)->Destory(); // iter++; //} m_EffectList.clear(); m_spDepthMap = NULL; // depth buffer m_spRenderer = NULL; m_spSceneRTG = NULL; } //---------------------------------------------------------------------------------------- CDepthAlphaEffectManager* CDepthAlphaEffectManager::GetInstance() { if (NULL == ms_pkInstance) { ms_pkInstance = NiNew CDepthAlphaEffectManager; } return ms_pkInstance; } //---------------------------------------------------------------------------------------- // 初始化 DepthAlpha effect,主要工作是在 stand material 中增加一个 render target 保存 depth buffer bool CDepthAlphaEffectManager::Initialize(NiRendererPtr spRenderer) { if (NULL == spRenderer) { return false; } if (m_spRenderer != NULL) { return true; } //__super::_SDMInit(); m_spRenderer = spRenderer; // Set default rendering material to be the a material which will // write the camera-space depth to an additional render target. MRT_ColorDepthMaterialPtr spDefaultMat = NiNew MRT_ColorDepthMaterial; spDefaultMat->AddDefaultFallbacks(); //m_spRenderer->SetDefaultMaterial(spDefaultMat); return true; } //---------------------------------------------------------------------------------------- // 销毁 void CDepthAlphaEffectManager::Destory() { ms_pkInstance = NULL; //__super::_SDMShutdown(); } //---------------------------------------------------------------------------------------- bool CDepthAlphaEffectManager::CreateFrame(NiRenderFramePtr spFrame) { // Get the back buffer that we will use NiTexture::FormatPrefs kPrefs; Ni2DBuffer* pkDefaultBackBuffer = m_spRenderer->GetDefaultBackBuffer(); unsigned int uiWidth = pkDefaultBackBuffer->GetWidth(); unsigned int uiHeight = pkDefaultBackBuffer->GetHeight(); Ni2DBuffer::MultiSamplePreference eMSAAPref = Ni2DBuffer::MULTISAMPLE_NONE; // pkDefaultBackBuffer->GetMSAAPref(); // Xenon and PC can render to the backbuffer directly in an MRT Ni2DBuffer* pkBackBuffer = pkDefaultBackBuffer; // Additional render target format kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::SINGLE_COLOR_32; // r32 // Create an additional render target to store the camera-space depth in m_spDepthMap = NiRenderedTexture::Create(uiWidth, uiHeight, m_spRenderer, kPrefs, eMSAAPref); // Create a render target using the default back buffer and stencil buffer, // but with the newly created buffer as a second render target. NiRenderTargetGroup* pkNewGroup = NiRenderTargetGroup::Create(2, m_spRenderer); pkNewGroup->AttachBuffer(pkBackBuffer, 0); pkNewGroup->AttachBuffer(m_spDepthMap->GetBuffer(), 1); // Get the main depth stencil buffer. NiDepthStencilBuffer* pkDSB = NULL; pkDSB = m_spRenderer-> GetDefaultRenderTargetGroup()->GetDepthStencilBuffer(); NIASSERT(pkDSB); pkNewGroup->AttachDepthStencilBuffer(pkDSB); m_spSceneRTG = pkNewGroup; // Set the scene rendering step to output to this target. if (!m_spRenderer->ValidateRenderTargetGroup(pkNewGroup)) return false; // m_sp // Grab NiApplication's default click step NIASSERT(spFrame); NiRenderStep* pkStep = spFrame->GetRenderStepByName(MAIN_RENDER_STEP_NAME); NIASSERT(pkStep); NIASSERT(NiIsKindOf(NiDefaultClickRenderStep, pkStep)); NiDefaultClickRenderStep* pkCStep = (NiDefaultClickRenderStep*)pkStep; // Grab the first click, which we know is NiApplication's "render the // scene click" NiTPointerList& kClickList = pkCStep->GetRenderClickList(); NiTListIterator kIter = kClickList.GetHeadPos(); NiRenderClick* pkFirstClick = (NiRenderClick*)kClickList.GetHead(); // Set the scene to render into the new render target. pkFirstClick->SetRenderTargetGroup(pkNewGroup); pkFirstClick->SetClearAllBuffers(true); NiColorA kBlack(0.0f, 0.0f, 0.0f, 0.0f); m_spRenderer->SetBackgroundColor(kBlack); // Add the soft particles manager as a render click after that. It // will use the default render target and not the new group that we used // above, because it uses the additional buffer as an input. kClickList.InsertAfter(kIter, (NiRenderClickPtr)this); this->SetRenderTargetGroup(NULL); this->SetClearAllBuffers(false); return true; } //--------------------------------------------------------------------------- // utility functor class MAIN_ENTRY RecursiveAddDepthAlphaEffect { public: RecursiveAddDepthAlphaEffect(CDepthAlphaEffectManager* pkSP) : m_spManager(pkSP) { } bool operator() (NiAVObject* pkAVObject) { // Add any particle systems found to soft particle system if (NiIsKindOf(IDepthAlphaEffect, pkAVObject)) { m_spManager->RegisteEffect((IDepthAlphaEffect*)pkAVObject); } return true; } protected: CDepthAlphaEffectManager* m_spManager; }; //--------------------------------------------------------------------------- void CDepthAlphaEffectManager::RecursiveFindAndAddDepthAlphaEffect(NiAVObjectPtr pkObj) { RecursiveAddDepthAlphaEffect kFunctor(this); NiTNodeTraversal::DepthFirst_AllObjects(pkObj, kFunctor); } //---------------------------------------------------------------------------------------- // 添加新的 depth alpha effect void CDepthAlphaEffectManager::RegisteEffect(IDepthAlphaEffect* pEffect) { if (_Find(pEffect) == m_EffectList.end()) { pEffect->SetDepthTexture(NiSmartPointerCast(NiTexture, m_spDepthMap)); m_EffectList.push_back(pEffect); } } //---------------------------------------------------------------------------------------- /// 删除 depth alpha effect void CDepthAlphaEffectManager::UnregisteEffect(IDepthAlphaEffect* pEffect) { list::iterator iter = _Find(pEffect); if (iter != m_EffectList.end()) { m_EffectList.erase(iter); } } //---------------------------------------------------------------------------------------- void CDepthAlphaEffectManager::UnregisteAllEffect() { m_EffectList.clear(); } //---------------------------------------------------------------------------------------- list::iterator CDepthAlphaEffectManager::_Find(IDepthAlphaEffect* pkDAEffect) { list::iterator iter = m_EffectList.begin(); while (iter != m_EffectList.end()) { if (pkDAEffect == *iter) { break; } iter++; } return iter; } //---------------------------------------------------------------------------------------- NiTexturePtr CDepthAlphaEffectManager::GetDepthTexture() { return NiSmartPointerCast(NiTexture, m_spDepthMap); } //---------------------------------------------------------------------------------------- void CDepthAlphaEffectManager::SetDepthTexture(NiRenderedTexturePtr pkDepthTexture) { m_spDepthMap = pkDepthTexture; list::iterator iter = m_EffectList.begin(); while (iter != m_EffectList.end()) { (*iter)->SetDepthTexture(NiSmartPointerCast(NiTexture, m_spDepthMap)); iter++; } } //---------------------------------------------------------------------------------------- void CDepthAlphaEffectManager::BuildVisibleSet(NiEntityRenderingContextPtr pkRenderingCondtex) { list::iterator iter = m_EffectList.begin(); while (iter != m_EffectList.end()) { (*iter)->BuildVisibleSet(pkRenderingCondtex); iter++; } } //---------------------------------------------------------------------------------------- void CDepthAlphaEffectManager::SetCamera(NiCameraPtr pkCamera) { m_spCamera = pkCamera; } //---------------------------------------------------------------------------------------- void CDepthAlphaEffectManager::PerformRendering(unsigned int uiFrameID) { //NiVisibleArray kVisibleArray; //NiEntityRenderingContext kRenderingCondtex; //kRenderingCondtex.m_pkCamera = m_spCamera; //kRenderingCondtex.m_pkCullingProcess = NiNew NiCullingProcess(&kVisibleArray); //kRenderingCondtex.m_pkRenderer = NiRenderer::GetRenderer(); //// 创建可视集 渲染体雾本身 //BuildVisibleSet(&kRenderingCondtex); //NiDrawVisibleArray(kRenderingCondtex.m_pkCamera, kVisibleArray); __super::PerformRendering( uiFrameID ); } //---------------------------------------------------------------------------------------- NiRenderTargetGroup* CDepthAlphaEffectManager::CreateRenderTargetGroup(NiRenderedTexture* pkTexture) { // 客户端使用 CreateFrame 的方法。场景编辑器中没有 Frame, 使用 // 1. 通过RenderTargetGroup 增加 depth buffer 的 RenderTarget // 2. 场景其他物件渲染完后再渲染 体雾本身 // Get the back buffer that we will use NiTexture::FormatPrefs kPrefs; Ni2DBuffer* pkDefaultBackBuffer = pkTexture->GetBuffer(); //m_spRenderer->GetDefaultBackBuffer(); unsigned int uiWidth = pkDefaultBackBuffer->GetWidth(); unsigned int uiHeight = pkDefaultBackBuffer->GetHeight(); Ni2DBuffer::MultiSamplePreference eMSAAPref = Ni2DBuffer::MULTISAMPLE_NONE; //pkDefaultBackBuffer->GetMSAAPref(); // Additional render target format kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::SINGLE_COLOR_32; // r32 // Create an additional render target to store the camera-space depth in m_spDepthMap = NiRenderedTexture::Create(uiWidth, uiHeight, m_spRenderer, kPrefs, eMSAAPref); // Create a render target using the default back buffer and stencil buffer, // but with the newly created buffer as a second render target. NiRenderTargetGroup* pkNewGroup = NiRenderTargetGroup::Create(2, m_spRenderer); pkNewGroup->AttachBuffer(pkDefaultBackBuffer, 0); pkNewGroup->AttachBuffer(m_spDepthMap->GetBuffer(), 1); NiDepthStencilBuffer* pkDSB = NiDepthStencilBuffer::Create( uiWidth, uiHeight, m_spRenderer, NiPixelFormat::STENCILDEPTH824 ); pkNewGroup->AttachDepthStencilBuffer(pkDSB); m_spSceneRTG = NiRenderTargetGroup::Create(pkTexture->GetBuffer(), m_spRenderer, true, false); m_spSceneRTG->AttachDepthStencilBuffer(pkDSB); if (!m_spRenderer->ValidateRenderTargetGroup( m_spSceneRTG )) { return NULL; } SetDepthTexture(m_spDepthMap); return pkNewGroup; } //---------------------------------------------------------------------------------------- #ifndef CODE_INGAME void CDepthAlphaEffectManager::PerformRendering(NiEntityRenderingContextPtr pkRenderingCondtex) { bool bResult = true; // back up current RTG const NiRenderTargetGroup* pkCurrentRTG = m_spRenderer->GetCurrentRenderTargetGroup(); if (pkCurrentRTG != NULL) { bResult = m_spRenderer->EndUsingRenderTargetGroup(); } bResult = m_spRenderer->BeginUsingRenderTargetGroup(m_spSceneRTG, NiRenderer::CLEAR_NONE); NiVisibleArray kVisibleArray; NiVisibleArray* pkOldVisibleArray = pkRenderingCondtex->m_pkCullingProcess->GetVisibleSet(); pkRenderingCondtex->m_pkCullingProcess->SetVisibleSet(&kVisibleArray); // 创建可视集 渲染体雾本身 BuildVisibleSet(pkRenderingCondtex); NiDrawVisibleArray(pkRenderingCondtex->m_pkCamera, kVisibleArray); pkRenderingCondtex->m_pkCullingProcess->SetVisibleSet(pkOldVisibleArray); bResult =m_spRenderer->EndUsingRenderTargetGroup(); if (pkCurrentRTG != NULL) { bResult =m_spRenderer->BeginUsingRenderTargetGroup((NiRenderTargetGroup*)pkCurrentRTG, NiRenderer::CLEAR_NONE); } } void CDepthAlphaEffectManager::Update(float fElapsedTime, float fTotalTime ) { list::iterator iter = m_EffectList.begin(); while (iter != m_EffectList.end()) { (*iter)->Update(fElapsedTime); iter++; } } #endif