180 lines
5.9 KiB
C++
180 lines
5.9 KiB
C++
#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<ICommandUser*>& 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;
|
|
}
|