#include "StdAfx.h" #include "PostProcessEffect.h" #include "ClientState.h" PostProcessEffect::PostProcessEffect() { Init(); } PostProcessEffect::~PostProcessEffect() { Release(); } float PostProcessEffect_ComputeGaussian(float n) { float theta = ClientState->GetBloomParams().fBlur; return (float)((1.0 / NiSqrt(2 * NI_PI * theta)) * NiExp(-(n * n) / (2 * theta * theta))); } void PostProcessEffect_SetGaussianGlobalShaderConstant(float x, float y) { const int definedSampleCount = 15; int sampleCount = definedSampleCount; float sampleWeights[ definedSampleCount ]; NiPoint2 sampleOffsets[ definedSampleCount ]; sampleWeights[0] = PostProcessEffect_ComputeGaussian(0); sampleOffsets[0] = NiPoint2( 0, 0 ); float totalWeights = sampleWeights[0]; for (int i = 0; i < sampleCount / 2; i++) { float weight = PostProcessEffect_ComputeGaussian( ( float )( i + 1) ); sampleWeights[i * 2 + 1] = weight; sampleWeights[i * 2 + 2] = weight; totalWeights += weight * 2; float sampleOffset = i * 2 + 1.5f; NiPoint2 delta = NiPoint2( x, y ) * sampleOffset; sampleOffsets[i * 2 + 1] = delta; sampleOffsets[i * 2 + 2] = -delta; } for (int i = 0; i < definedSampleCount; i++) { sampleWeights[i] /= totalWeights; } NiShaderFactory::UpdateGlobalShaderConstant( "g_gaussianBlurWeights", sizeof(float) * definedSampleCount, sampleWeights); NiShaderFactory::UpdateGlobalShaderConstant( "g_gaussianBlurOffsets", sizeof(NiPoint2) * definedSampleCount, sampleOffsets); } void PostProcessEffect::UpdateShaderConstant() { #ifdef WOW_BLOOM NiShaderFactory::UpdateGlobalShaderConstant("gakSampleOffsets", sizeof(NiPoint2) * MAX_SAMPLES, m_akSampleOffsets); #else NIASSERT(m_pTempTexture1); NIASSERT(m_pTempTexture2); NiShaderFactory::UpdateGlobalShaderConstant("g_bloomThreshold", sizeof(float), &ClientState->GetBloomParams().fThreshold); PostProcessEffect_SetGaussianGlobalShaderConstant(1.0f / (float)m_pTempTexture2->GetWidth(), 1.0f / (float)m_pTempTexture1->GetHeight()); NiShaderFactory::UpdateGlobalShaderConstant("g_bloomIntensity", sizeof(float), &ClientState->GetBloomParams().fIntensity); NiShaderFactory::UpdateGlobalShaderConstant("g_baseIntensity", sizeof(float), &ClientState->GetBloomParams().fBaseIntensity); NiShaderFactory::UpdateGlobalShaderConstant("g_bloomSaturation", sizeof(float), &ClientState->GetBloomParams().fSaturation); NiShaderFactory::UpdateGlobalShaderConstant("g_baseSaturation", sizeof(float), &ClientState->GetBloomParams().fBaseSaturation); #endif } void PostProcessEffect::PrepareRenderClick() { NiRenderer* pRenderer = NiRenderer::GetRenderer(); NIASSERT(pRenderer); NiRenderTargetGroup* pDefaultRenderTarget = pRenderer->GetDefaultRenderTargetGroup(); NIASSERT(pDefaultRenderTarget); unsigned int uiWidth = pDefaultRenderTarget->GetWidth(0); unsigned int uiHeight = pDefaultRenderTarget->GetHeight(0); NiTexture::FormatPrefs kPrefs; kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::TRUE_COLOR_32; kPrefs.m_eMipMapped = NiTexture::FormatPrefs::NO; kPrefs.m_eAlphaFmt = NiTexture::FormatPrefs::NONE; m_pBBTexture = NiRenderedTexture::Create(uiWidth, uiHeight, pRenderer, kPrefs); m_pBBRTG = NiRenderTargetGroup::Create(m_pBBTexture->GetBuffer(), pRenderer, true, true); #ifdef WOW_BLOOM m_spSmoothTexture = NiRenderedTexture::Create(uiWidth / 4, uiHeight / 4, pRenderer); m_spSmoothRenderTargetGroup = NiRenderTargetGroup::Create( m_spSmoothTexture->GetBuffer(), pRenderer, true, true); NIASSERT(m_spSmoothRenderTargetGroup && m_spSmoothTexture); m_spSmoothBigTexture = NiRenderedTexture::Create(uiWidth / 2, uiWidth / 2, pRenderer); m_spSmoothBigRenderTargetGroup = NiRenderTargetGroup::Create( m_spSmoothBigTexture->GetBuffer(), pRenderer, true, true); NIASSERT(m_spSmoothBigRenderTargetGroup && m_spSmoothBigTexture); m_spTexProp = NiNew NiTexturingProperty; NIASSERT(m_spTexProp); m_spTexProp->SetBaseTexture(m_pBBTexture); m_spTexProp->SetApplyMode(NiTexturingProperty::APPLY_REPLACE); m_spTexProp->SetBaseClampMode(NiTexturingProperty::CLAMP_S_CLAMP_T); m_spTexProp->SetShaderMap(1, NiNew NiTexturingProperty::ShaderMap(m_spSmoothTexture, 0)); m_spTexProp->SetShaderMap(2, NiNew NiTexturingProperty::ShaderMap(m_spSmoothBigTexture, 0)); GetSampleOffsets_DownScale4x4(uiWidth / 4, uiHeight / 4, m_akSampleOffsets); #else m_pTempTexture1 = NiRenderedTexture::Create(uiWidth / 2, uiHeight / 2, pRenderer, kPrefs); m_pTempRTG1 = NiRenderTargetGroup::Create(m_pTempTexture1->GetBuffer(), pRenderer, true, true); m_pTempTexture2 = NiRenderedTexture::Create(uiWidth / 2, uiHeight / 2, pRenderer, kPrefs); m_pTempRTG2 = NiRenderTargetGroup::Create(m_pTempTexture2->GetBuffer(), pRenderer, true, true); #endif m_pRenderStep = NiNew NiDefaultClickRenderStep; m_pRenderStep->SetActive(true); } #ifdef WOW_BLOOM void PostProcessEffect::CreateWowBloom() { //Bloom_SmoothPS NiScreenFillingRenderView* pBTView = NiNew NiScreenFillingRenderView; pBTView->AttachProperty(m_spTexProp); pBTView->GetScreenFillingQuad().UpdateProperties(); pBTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("Bloom_SmoothPS")); NiViewRenderClick* pRC = NiNew NiViewRenderClick; pRC->AppendRenderView(pBTView); pRC->SetRenderTargetGroup(m_spSmoothRenderTargetGroup); pRC->SetClearAllBuffers(true); m_pRenderStep->AppendRenderClick(pRC); //Bloom_SmoothBigPS pBTView = NiNew NiScreenFillingRenderView; pBTView->AttachProperty(m_spTexProp); pBTView->GetScreenFillingQuad().UpdateProperties(); pBTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("Bloom_SmoothBigPS")); pRC = NiNew NiViewRenderClick; pRC->AppendRenderView(pBTView); pRC->SetClearAllBuffers(true); pRC->SetRenderTargetGroup(m_spSmoothBigRenderTargetGroup); m_pRenderStep->AppendRenderClick(pRC); //Bloom_FinalPS pBTView = NiNew NiScreenFillingRenderView; pBTView->AttachProperty(m_spTexProp); pBTView->GetScreenFillingQuad().UpdateProperties(); pBTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("Bloom_FinalPS")); m_pFinalView = pBTView; pRC = NiNew NiViewRenderClick; pRC->AppendRenderView(pBTView); pRC->SetClearAllBuffers(true); m_pRenderStep->AppendRenderClick(pRC); } void PostProcessEffect::GetSampleOffsets_DownScale4x4(unsigned int uiWidth, unsigned int uiHeight, NiPoint2 akSampleOffsets[]) { NIASSERT(akSampleOffsets != 0); float fU = 1.0f / uiWidth; float fV = 1.0f / uiHeight; // Sample from the 16 surrounding points. // Since the center point will be in the exact center of 16 texels, // a 0.5f offset is needed to specify a texel center. int index = 0; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { akSampleOffsets[index].x = (x - 1.5f) * fU; akSampleOffsets[index].y = (y - 1.5f) * fV; index++; } } } #else void PostProcessEffect::CreateBloomThresholdRC() { NiScreenFillingRenderView* pBTView = NiNew NiScreenFillingRenderView; NiTexturingProperty* pTP = NiNew NiTexturingProperty; pTP->SetShaderMap(0, NiNew NiTexturingProperty::ShaderMap(m_pBBTexture, 0, NiTexturingProperty::CLAMP_S_CLAMP_T, NiTexturingProperty::FILTER_BILERP, 0)); pBTView->AttachProperty(pTP); pBTView->GetScreenFillingQuad().UpdateProperties(); pBTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("BloomThreshold")); NiViewRenderClick* pRC = NiNew NiViewRenderClick; pRC->AppendRenderView(pBTView); pRC->SetRenderTargetGroup(m_pTempRTG1); pRC->SetClearAllBuffers(true); m_pRenderStep->AppendRenderClick(pRC); } void PostProcessEffect::CreateGaussianBlurHRC() { NiScreenFillingRenderView* pBTView = NiNew NiScreenFillingRenderView; NiTexturingProperty* pTP = NiNew NiTexturingProperty; pTP->SetShaderMap(0, NiNew NiTexturingProperty::ShaderMap(m_pTempTexture1, 0, NiTexturingProperty::CLAMP_S_CLAMP_T, NiTexturingProperty::FILTER_BILERP, 0)); pBTView->AttachProperty(pTP); pBTView->GetScreenFillingQuad().UpdateProperties(); pBTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("GaussianBlurH")); NiViewRenderClick* pRC = NiNew NiViewRenderClick; pRC->AppendRenderView(pBTView); pRC->SetClearAllBuffers(true); pRC->SetRenderTargetGroup(m_pTempRTG2); m_pRenderStep->AppendRenderClick(pRC); } void PostProcessEffect::CreateGaussianBlurVRC() { NiScreenFillingRenderView* pBTView = NiNew NiScreenFillingRenderView; NiTexturingProperty* pTP = NiNew NiTexturingProperty; pTP->SetShaderMap(0, NiNew NiTexturingProperty::ShaderMap(m_pTempTexture2, 0, NiTexturingProperty::CLAMP_S_CLAMP_T, NiTexturingProperty::FILTER_BILERP, 0)); pBTView->AttachProperty(pTP); pBTView->GetScreenFillingQuad().UpdateProperties(); pBTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("GaussianBlurV")); NiViewRenderClick* pRC = NiNew NiViewRenderClick; pRC->AppendRenderView(pBTView); pRC->SetClearAllBuffers(true); pRC->SetRenderTargetGroup(m_pTempRTG1); m_pRenderStep->AppendRenderClick(pRC); } void PostProcessEffect::CreateBloomCombineRC() { NiScreenFillingRenderView* pBTView = NiNew NiScreenFillingRenderView; NiTexturingProperty* pTP = NiNew NiTexturingProperty; pTP->SetShaderMap(0, NiNew NiTexturingProperty::ShaderMap(m_pTempTexture1, 0, NiTexturingProperty::CLAMP_S_CLAMP_T, NiTexturingProperty::FILTER_BILERP, 0)); pTP->SetShaderMap(1, NiNew NiTexturingProperty::ShaderMap(m_pBBTexture, 0, NiTexturingProperty::CLAMP_S_CLAMP_T, NiTexturingProperty::FILTER_BILERP, 0)); pBTView->AttachProperty(pTP); pBTView->GetScreenFillingQuad().UpdateProperties(); pBTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("BloomCombine")); NiViewRenderClick* pRC = NiNew NiViewRenderClick; pRC->AppendRenderView(pBTView); pRC->SetClearAllBuffers(true); m_pRenderStep->AppendRenderClick(pRC); } #endif void PostProcessEffect::DeadEffect( bool bDeadEffect ) { if ( bDeadEffect ) m_pFinalView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("Bloom_DeadPS")); else { m_pFinalView->GetScreenFillingQuad().ApplyAndSetActiveMaterial(NiSingleShaderMaterial::Create("Bloom_FinalPS")); } } void PostProcessEffect::Init() { PrepareRenderClick(); #ifdef WOW_BLOOM CreateWowBloom(); #else CreateBloomThresholdRC(); CreateGaussianBlurHRC(); CreateGaussianBlurVRC(); CreateBloomCombineRC(); #endif UpdateShaderConstant(); } void PostProcessEffect::Release() { m_pBBTexture = NULL; m_pBBRTG = NULL; #ifdef WOW_BLOOM m_spBloomSmoothShader = 0; m_spBloomFinalShader = 0; m_spBloomBigSmoothShader = 0; m_spSmoothTexture = 0; m_spSmoothRenderTargetGroup = 0; #else m_pTempTexture1 = NULL; m_pTempRTG1 = NULL; m_pTempTexture2 = NULL; m_pTempRTG2 = NULL; m_pRenderStep = NULL; #endif } void PostProcessEffect::Render() { NiD3DRenderer* pRenderer = (NiD3DRenderer*)NiRenderer::GetRenderer(); NIASSERT(pRenderer); NiDX9RenderState* pkRenderState = pRenderer->GetRenderState(); pkRenderState->DisableAlpha(); unsigned int slopebias = pkRenderState->GetRenderState(D3DRS_SLOPESCALEDEPTHBIAS); unsigned int dbias = pkRenderState->GetRenderState(D3DRS_DEPTHBIAS); _asm nop pkRenderState->ApplyZBuffer(NiZBufferProperty::GetDefault()); m_pRenderStep->Render(); } NiRenderTargetGroup* PostProcessEffect::GetRenderTarget() const { return m_pBBRTG; }