Files
2026-04-18 22:31:51 +02:00

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;
}