#include "stdafx.h" #include "ICommonObjectFactory.h" #include "PingPongBuffer.h" #include "../Resources/ShaderParameterCollection/Types/Texture.h" PingPongBuffer::PingPongBuffer(IEngine& argEngine) : m_Engine(argEngine) , m_RenderTargetNodeA(NULL) , m_RenderTargetNodeB(NULL) , m_ShaderA(NULL) , m_ShaderB(NULL) , m_ShaderPreProcess(NULL) , m_TextureA(NULL) , m_TextureB(NULL) , m_ScreenQuad(NULL) , m_ShaderParameterA(NULL) , m_ShaderParameterB(NULL) , m_ShaderParameterPreProcess(NULL) , m_InputTexture(NULL) { m_RootNode = &m_Engine.get_ResourceFactory().CreateRenderCommandNode(); m_PreProcessNode = &m_Engine.get_ResourceFactory().CreateRenderCommandNode(); } PingPongBuffer::~PingPongBuffer() { IResourceFactory& resourceFac = m_Engine.get_ResourceFactory(); resourceFac.DeleteTexture(*m_InputTexture); resourceFac.DeleteShader(*m_ShaderA); resourceFac.DeleteShader(*m_ShaderB); resourceFac.DeleteShader(*m_ShaderPreProcess); resourceFac.DeleteRenderTargetTexture(*m_TextureA); resourceFac.DeleteRenderTargetTexture(*m_TextureB); resourceFac.DeleteGeometryBuffer(*m_ScreenQuad); resourceFac.DeleteShaderParameterCollection(*m_ShaderParameterA); resourceFac.DeleteShaderParameterCollection(*m_ShaderParameterB); resourceFac.DeleteShaderParameterCollection(*m_ShaderParameterPreProcess); resourceFac.DeleteRenderCommandNode(*m_RootNode); resourceFac.DeleteRenderCommandNode(*m_PreProcessNode); resourceFac.DeleteRenderCommandNode(*m_RenderTargetNodeA); resourceFac.DeleteRenderCommandNode(*m_RenderTargetNodeB); } ITexture& PingPongBuffer::get_InputTexture() const { return *m_InputTexture; } void PingPongBuffer::set_InputTexture(ITexture& argTexture) { m_InputTexture = &argTexture; this->Rebuild(m_Descriptor); } ITexture& PingPongBuffer::get_OutputTexture() const { return m_TextureB->get_TextureResource(); } const PingPongBufferDescription& PingPongBuffer::get_Descriptor() const { return m_Descriptor; } void PingPongBuffer::set_Descriptor(const PingPongBufferDescription& argValue) { this->Rebuild(argValue); } IRenderCommandNode& PingPongBuffer::get_RootNode() const { return *m_RootNode; } IRenderCommandNode& PingPongBuffer::get_PreProcessNode() const { return *m_PreProcessNode; } void PingPongBuffer::Rebuild(const PingPongBufferDescription& argValue) { // Shader A if (argValue.ShaderFileName.empty()) return; if (m_ShaderA == NULL || argValue.ShaderFileName != m_Descriptor.ShaderFileName) { m_ShaderA = &m_Engine.get_ResourceFactory().CreateOrFindShader(); m_ShaderA->LoadFromFile(argValue.ShaderFileName); } if (argValue.ShaderTechniqueA != m_Descriptor.ShaderTechniqueA) m_ShaderA->set_TechniqueName(argValue.ShaderTechniqueA); // ShaderB if (m_ShaderB == NULL || argValue.ShaderFileName != m_Descriptor.ShaderFileName) { m_ShaderB = &m_Engine.get_ResourceFactory().CreateOrFindShader(); m_ShaderB->LoadFromFile(argValue.ShaderFileName); } if (argValue.ShaderTechniqueB != m_Descriptor.ShaderTechniqueB) m_ShaderB->set_TechniqueName(argValue.ShaderTechniqueB); // PreProcessShader (downscale, input to buffer) if (m_ShaderPreProcess == NULL || argValue.ShaderFileName != m_Descriptor.ShaderFileName) { m_ShaderPreProcess = &m_Engine.get_ResourceFactory().CreateOrFindShader(); m_ShaderPreProcess->LoadFromFile(argValue.ShaderFileName); } if (argValue.PreProcessShaderTechnique != m_Descriptor.PreProcessShaderTechnique) m_ShaderPreProcess->set_TechniqueName(argValue.PreProcessShaderTechnique); if (m_TextureA == NULL || m_TextureB == NULL || argValue.TextureWidth != m_Descriptor.TextureWidth || argValue.TextureHeight != m_Descriptor.TextureHeight || argValue.TextureFormat != m_Descriptor.TextureFormat) { if (m_TextureA == NULL) m_TextureA = &m_Engine.get_ResourceFactory().CreateOrFindRenderTargetTexture(); if (m_TextureB == NULL) m_TextureB = &m_Engine.get_ResourceFactory().CreateOrFindRenderTargetTexture(); m_TextureA->SetTextureParameters(argValue.TextureWidth, argValue.TextureHeight, argValue.TextureFormat); m_TextureB->SetTextureParameters(argValue.TextureWidth, argValue.TextureHeight, argValue.TextureFormat); } m_ShaderParameterA = &m_Engine.get_ResourceFactory().CreateOrFindShaderParameterCollection(); m_ShaderParameterA->SetParameter("InputTexture", m_TextureB->get_TextureResource()); m_ShaderParameterB = &m_Engine.get_ResourceFactory().CreateOrFindShaderParameterCollection(); m_ShaderParameterB->SetParameter("InputTexture", m_TextureA->get_TextureResource()); m_ShaderParameterPreProcess = &m_Engine.get_ResourceFactory().CreateOrFindShaderParameterCollection(); m_ShaderParameterPreProcess->SetParameter("InputTexture", new TextureShaderParameter(*m_InputTexture, ParameterBindType::BindBySemantic)); if (m_ScreenQuad == NULL) m_ScreenQuad = m_Engine.get_CommonObjectFactory().CreateQuad(2.0f, 2.0f, false); m_RenderTargetNodeA = &m_Engine.get_ResourceFactory().CreateRenderCommandNode(); AddToNode(*m_RenderTargetNodeA, m_TextureA); AddToNode(*m_RenderTargetNodeA ,m_ShaderA); AddToNode(*m_RenderTargetNodeA, m_ShaderParameterA); AddToNode(*m_RenderTargetNodeA, m_ScreenQuad); m_RenderTargetNodeB = &m_Engine.get_ResourceFactory().CreateRenderCommandNode(); AddToNode(*m_RenderTargetNodeB, m_TextureB); AddToNode(*m_RenderTargetNodeB, m_ShaderB); AddToNode(*m_RenderTargetNodeB, m_ShaderParameterB); AddToNode(*m_RenderTargetNodeB, m_ScreenQuad); const std::vector& lk_CommandUsers = m_RootNode->get_CommandUsers(); while (!lk_CommandUsers.empty()) m_RootNode->RemoveCommandUser(*lk_CommandUsers[0]); // preprocessing AddToNode(*m_RootNode, m_TextureB); AddToNode(*m_RootNode, m_ShaderPreProcess); AddToNode(*m_RootNode, m_ShaderParameterPreProcess); AddToNode(*m_RootNode, m_ScreenQuad); AddToNode(*m_RootNode, m_PreProcessNode); // real pingpongs for (uint32 i = 0; i < argValue.LoopCount; ++i) { AddToNode(*m_RootNode, m_RenderTargetNodeA); AddToNode(*m_RootNode, m_RenderTargetNodeB); } m_Descriptor = argValue; }