/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Code/Engine/RendererCore/Pipeline/Implementation/Passes/AOPass.cpp
339 строк
14 KB
Sanakan8472
Render Graph (#1948)
03 июн 2026, 10:19
Не верифицирован
03 июн 2026, 10:19
60bb12c
Код
Авторство
О чём код?
#include <RendererCore/RendererCorePCH.h> #include <Foundation/IO/TypeVersionContext.h> #include <RendererCore/GPUResourcePool/GPUResourcePool.h> #include <RendererCore/Pipeline/Passes/AOPass.h> #include <RendererCore/Pipeline/View.h> #include <RendererCore/RenderContext/RenderContext.h> #include <RendererCore/Textures/Texture2DResource.h> #include <RendererFoundation/Profiling/Profiling.h> #include <RendererCore/../../../Data/Base/Shaders/Pipeline/DownscaleDepthConstants.h> #include <RendererCore/../../../Data/Base/Shaders/Pipeline/SSAOConstants.h> // clang-format off EZ_BEGIN_DYNAMIC_REFLECTED_TYPE(ezAOPass, 1, ezRTTIDefaultAllocator<ezAOPass>) { EZ_BEGIN_PROPERTIES { EZ_MEMBER_PROPERTY("DepthInput", m_PinDepthInput), EZ_MEMBER_PROPERTY("Output", m_PinOutput), EZ_MEMBER_PROPERTY("Radius", m_fRadius)->AddAttributes(new ezDefaultValueAttribute(1.0f), new ezClampValueAttribute(0.01f, 10.0f)), EZ_MEMBER_PROPERTY("MaxScreenSpaceRadius", m_fMaxScreenSpaceRadius)->AddAttributes(new ezDefaultValueAttribute(1.0f), new ezClampValueAttribute(0.01f, 2.0f)), EZ_MEMBER_PROPERTY("Contrast", m_fContrast)->AddAttributes(new ezDefaultValueAttribute(2.0f)), EZ_MEMBER_PROPERTY("Intensity", m_fIntensity)->AddAttributes(new ezDefaultValueAttribute(0.7f)), EZ_ACCESSOR_PROPERTY("FadeOutStart", GetFadeOutStart, SetFadeOutStart)->AddAttributes(new ezDefaultValueAttribute(80.0f), new ezClampValueAttribute(0.0f, ezVariant())), EZ_ACCESSOR_PROPERTY("FadeOutEnd", GetFadeOutEnd, SetFadeOutEnd)->AddAttributes(new ezDefaultValueAttribute(100.0f), new ezClampValueAttribute(0.0f, ezVariant())), EZ_MEMBER_PROPERTY("PositionBias", m_fPositionBias)->AddAttributes(new ezDefaultValueAttribute(5.0f), new ezClampValueAttribute(0.0f, 1000.0f)), EZ_MEMBER_PROPERTY("MipLevelScale", m_fMipLevelScale)->AddAttributes(new ezDefaultValueAttribute(10.0f), new ezClampValueAttribute(0.0f, ezVariant())), EZ_MEMBER_PROPERTY("DepthBlurThreshold", m_fDepthBlurThreshold)->AddAttributes(new ezDefaultValueAttribute(2.0f), new ezClampValueAttribute(0.01f, ezVariant())), } EZ_END_PROPERTIES; EZ_BEGIN_ATTRIBUTES { new ezCategoryAttribute("Post Processing") } EZ_END_ATTRIBUTES; } EZ_END_DYNAMIC_REFLECTED_TYPE; // clang-format on ezAOPass::ezAOPass() : ezRenderPipelinePass("AOPass", true) { m_hNoiseTexture = ezResourceManager::LoadResource<ezTexture2DResource>("Textures/SSAONoise.dds"); m_hDownscaleShader = ezResourceManager::LoadResource<ezShaderResource>("Shaders/Pipeline/DownscaleDepth.ezShader"); EZ_ASSERT_DEV(m_hDownscaleShader.IsValid(), "Could not load downsample shader!"); m_hSSAOShader = ezResourceManager::LoadResource<ezShaderResource>("Shaders/Pipeline/SSAO.ezShader"); EZ_ASSERT_DEV(m_hSSAOShader.IsValid(), "Could not load SSAO shader!"); m_hBlurShader = ezResourceManager::LoadResource<ezShaderResource>("Shaders/Pipeline/SSAOBlur.ezShader"); EZ_ASSERT_DEV(m_hBlurShader.IsValid(), "Could not load SSAO shader!"); m_hDownscaleConstantBuffer = ezRenderContext::CreateConstantBufferStorage<ezDownscaleDepthConstants>(); m_hSSAOConstantBuffer = ezRenderContext::CreateConstantBufferStorage<ezSSAOConstants>(); } ezAOPass::~ezAOPass() { ezGALDevice::GetDefaultDevice()->DestroySamplerState(m_hSSAOSamplerState); ezRenderContext::DeleteConstantBufferStorage(m_hDownscaleConstantBuffer); ezRenderContext::DeleteConstantBufferStorage(m_hSSAOConstantBuffer); } ezStatus ezAOPass::AddRenderPasses(const ezViewData& viewData, const ezCamera& camera, ezRenderGraph& ref_graph, const ezArrayPtr<const ezRenderPipelinePinConnection> inputs, ezArrayPtr<ezRenderPipelinePinConnection> outputs) { // Validate input ezRenderGraphTextureHandle hDepthInput = inputs[m_PinDepthInput.m_uiInputIndex].m_TextureHandle; if (hDepthInput.IsInvalidated()) return ezStatus(ezFmt("DepthInput pin: Not connected ")); ezGALTextureCreationDescription depthDesc = ref_graph.GetTextureDesc(hDepthInput); if (depthDesc.m_SampleCount != ezGALMSAASampleCount::None) return ezStatus(ezFmt("DepthInput pin: Input must be resolved")); // #TODO_RG CHECK IS DEPTH // Create output ezGALTextureCreationDescription outputDesc = depthDesc; outputDesc.m_Format = ezGALResourceFormat::RGHalf; ezRenderGraphTextureHandle hSSAOOutput = ref_graph.CreateTexture(outputDesc); outputs[m_PinOutput.m_uiOutputIndex].m_TextureHandle = hSSAOOutput; // Add passes ezUInt32 uiWidth = depthDesc.m_uiWidth; ezUInt32 uiHeight = depthDesc.m_uiHeight; ezUInt32 uiNumMips = 3; ezUInt32 uiHzbWidth = ezMath::RoundUp(uiWidth, 1u << uiNumMips); ezUInt32 uiHzbHeight = ezMath::RoundUp(uiHeight, 1u << uiNumMips); float fHzbScaleX = (float)uiWidth / uiHzbWidth; float fHzbScaleY = (float)uiHeight / uiHzbHeight; // Find temp targets { { ezGALTextureCreationDescription desc; desc.m_uiWidth = uiHzbWidth / 2; desc.m_uiHeight = uiHzbHeight / 2; desc.m_uiMipLevelCount = 3; desc.m_Type = ezGALTextureType::Texture2DArray; desc.m_Format = ezGALResourceFormat::RHalf; desc.m_TextureFlags.Add(ezGALTextureUsageFlags::RenderTarget | ezGALTextureUsageFlags::ShaderResource); desc.m_uiArraySize = outputDesc.m_uiArraySize; m_hHzbTexture = ref_graph.CreateTexture(desc); } for (ezUInt32 i = 0; i < uiNumMips; ++i) { uiHzbWidth = uiHzbWidth / 2; uiHzbHeight = uiHzbHeight / 2; m_HzbSizes.PushBack(ezVec2((float)uiHzbWidth, (float)uiHzbHeight)); { ezGALTextureRange desc; desc.m_uiBaseMipLevel = i; desc.m_uiMipLevels = 1; desc.m_uiArraySlices = outputDesc.m_uiArraySize; m_HzbResourceViews.PushBack(desc); } } ezGALTextureCreationDescription descTemp; descTemp.SetAsRenderTarget(uiWidth, uiHeight, ezGALResourceFormat::RGHalf, ezGALMSAASampleCount::None); descTemp.m_Type = ezGALTextureType::Texture2DArray; descTemp.m_uiArraySize = outputDesc.m_uiArraySize; m_hSSAOTemp = ref_graph.CreateTexture(descTemp); } // Mip map passes { CreateSamplerState(); for (ezUInt32 i = 0; i < uiNumMips; ++i) { ezRenderGraphTextureHandle hInputView = i == 0 ? hDepthInput : m_hHzbTexture; ezVec2 pixelSize; ezGALTextureRange range; if (i == 0) { pixelSize = ezVec2(1.0f / uiWidth, 1.0f / uiHeight); } else { range = m_HzbResourceViews[i - 1]; pixelSize = ezVec2(1.0f).CompDiv(m_HzbSizes[i - 1]); } auto pass = ref_graph.AddGraphicsPass("DownscaleDepth"); pass.AddColorTarget(m_hHzbTexture, ezGALRenderTargetRange::MakeFromMipLevel(i)); pass.ReadTexture(hInputView, range, i == 0 ? ezGALResourceState::DepthStencilRead : ezGALResourceState::ShaderResource, ezGALShaderStageFlags::PixelShader); pass.SetStereoscopic(camera.IsStereoscopic()); pass.SetExecuteCallback([=](const ezRenderGraphContext& ctx) { const ezRenderViewContext& renderViewContext = *ctx.GetUserData<ezRenderViewContext>(); ezDownscaleDepthConstants* constants = ezRenderContext::GetConstantBufferData<ezDownscaleDepthConstants>(m_hDownscaleConstantBuffer); constants->PixelSize = pixelSize; constants->FadeOutEnd = m_fFadeOutEnd; constants->LinearizeDepth = (i == 0); ezBindGroupBuilder& bindGroup = ezRenderContext::GetDefaultInstance()->GetBindGroup(); bindGroup.BindBuffer("ezDownscaleDepthConstants", m_hDownscaleConstantBuffer); renderViewContext.m_pRenderContext->BindShader(m_hDownscaleShader); bindGroup.BindTexture("DepthTexture", ctx.ResolveTexture(hInputView), range); bindGroup.BindSampler("DepthSampler", m_hSSAOSamplerState); renderViewContext.m_pRenderContext->BindNullMeshBuffer(ezGALPrimitiveTopology::Triangles, 1); renderViewContext.m_pRenderContext->DrawMeshBuffer().IgnoreResult(); // }); } } // SSAO pass { auto pass = ref_graph.AddGraphicsPass("SSAO"); pass.AddColorTarget(m_hSSAOTemp); pass.ReadTexture(m_hHzbTexture, {}, ezGALResourceState::ShaderResource, ezGALShaderStageFlags::PixelShader); pass.ReadTexture(hDepthInput, {}, ezGALResourceState::DepthStencilRead, ezGALShaderStageFlags::PixelShader); pass.SetStereoscopic(camera.IsStereoscopic()); pass.SetExecuteCallback([=](const ezRenderGraphContext& ctx) { const ezRenderViewContext& renderViewContext = *ctx.GetUserData<ezRenderViewContext>(); // Update constants { float fadeOutScale = -1.0f / ezMath::Max(0.001f, (m_fFadeOutEnd - m_fFadeOutStart)); float fadeOutOffset = -fadeOutScale * m_fFadeOutStart + 1.0f; ezSSAOConstants* constants = ezRenderContext::GetConstantBufferData<ezSSAOConstants>(m_hSSAOConstantBuffer); constants->TexCoordsScale = ezVec2(fHzbScaleX, fHzbScaleY); constants->FadeOutParams = ezVec2(fadeOutScale, fadeOutOffset); constants->WorldRadius = m_fRadius; constants->MaxScreenSpaceRadius = m_fMaxScreenSpaceRadius; constants->Contrast = m_fContrast; constants->Intensity = m_fIntensity; constants->PositionBias = m_fPositionBias / 1000.0f; constants->MipLevelScale = m_fMipLevelScale; constants->DepthBlurScale = 1.0f / m_fDepthBlurThreshold; constants->FadeOutEnd = m_fFadeOutEnd; } renderViewContext.m_pRenderContext->BindShader(m_hSSAOShader); ezBindGroupBuilder& bindGroupRenderPass = renderViewContext.m_pRenderContext->GetBindGroup(EZ_GAL_BIND_GROUP_RENDER_PASS); bindGroupRenderPass.BindBuffer("ezSSAOConstants", m_hSSAOConstantBuffer); bindGroupRenderPass.BindTexture("DepthTexture", ctx.ResolveTexture(hDepthInput)); bindGroupRenderPass.BindTexture("LowResDepthTexture", ctx.ResolveTexture(m_hHzbTexture)); bindGroupRenderPass.BindSampler("DepthSampler", m_hSSAOSamplerState); bindGroupRenderPass.BindTexture("NoiseTexture", m_hNoiseTexture, ezResourceAcquireMode::BlockTillLoaded); renderViewContext.m_pRenderContext->BindNullMeshBuffer(ezGALPrimitiveTopology::Triangles, 1); renderViewContext.m_pRenderContext->DrawMeshBuffer().IgnoreResult(); // }); } // Blur pass { auto pass = ref_graph.AddGraphicsPass("SSAO Blur"); pass.AddColorTarget(hSSAOOutput); pass.ReadTexture(m_hSSAOTemp, {}, ezGALResourceState::ShaderResource, ezGALShaderStageFlags::PixelShader); pass.SetStereoscopic(camera.IsStereoscopic()); pass.SetExecuteCallback([=](const ezRenderGraphContext& ctx) { const ezRenderViewContext& renderViewContext = *ctx.GetUserData<ezRenderViewContext>(); ezBindGroupBuilder& bindGroupRenderPass = renderViewContext.m_pRenderContext->GetBindGroup(EZ_GAL_BIND_GROUP_RENDER_PASS); renderViewContext.m_pRenderContext->BindShader(m_hBlurShader); bindGroupRenderPass.BindBuffer("ezSSAOConstants", m_hSSAOConstantBuffer); bindGroupRenderPass.BindTexture("SSAOTexture", ctx.ResolveTexture(m_hSSAOTemp)); renderViewContext.m_pRenderContext->BindNullMeshBuffer(ezGALPrimitiveTopology::Triangles, 1); renderViewContext.m_pRenderContext->DrawMeshBuffer().IgnoreResult(); }); } return EZ_SUCCESS; } ezStatus ezAOPass::AddRenderPassesInactive(const ezViewData& viewData, const ezCamera& camera, ezRenderGraph& ref_graph, const ezArrayPtr<const ezRenderPipelinePinConnection> inputs, ezArrayPtr<ezRenderPipelinePinConnection> outputs) { ezRenderGraphTextureHandle hDepthInput = inputs[m_PinDepthInput.m_uiInputIndex].m_TextureHandle; if (hDepthInput.IsInvalidated()) return ezStatus(ezFmt("DepthInput pin: Not connected ")); ezGALTextureCreationDescription outputDesc = ref_graph.GetTextureDesc(hDepthInput); outputDesc.m_Format = ezGALResourceFormat::RGHalf; ezRenderGraphTextureHandle hSSAOOutput = ref_graph.CreateTexture(outputDesc); outputs[m_PinOutput.m_uiOutputIndex].m_TextureHandle = hSSAOOutput; auto pass = ref_graph.AddGraphicsPass("InactiveSSAO"); pass.AddColorTarget(hSSAOOutput, {}, ezGALRenderTargetLoadOp::Clear); pass.SetClearColor(0, ezColor::White); return EZ_SUCCESS; } ezResult ezAOPass::Serialize(ezStreamWriter& inout_stream) const { EZ_SUCCEED_OR_RETURN(SUPER::Serialize(inout_stream)); inout_stream << m_fRadius; inout_stream << m_fMaxScreenSpaceRadius; inout_stream << m_fContrast; inout_stream << m_fIntensity; inout_stream << m_fFadeOutStart; inout_stream << m_fFadeOutEnd; inout_stream << m_fPositionBias; inout_stream << m_fMipLevelScale; inout_stream << m_fDepthBlurThreshold; return EZ_SUCCESS; } ezResult ezAOPass::Deserialize(ezStreamReader& inout_stream) { EZ_SUCCEED_OR_RETURN(SUPER::Deserialize(inout_stream)); const ezUInt32 uiVersion = ezTypeVersionReadContext::GetContext()->GetTypeVersion(GetStaticRTTI()); EZ_IGNORE_UNUSED(uiVersion); inout_stream >> m_fRadius; inout_stream >> m_fMaxScreenSpaceRadius; inout_stream >> m_fContrast; inout_stream >> m_fIntensity; inout_stream >> m_fFadeOutStart; inout_stream >> m_fFadeOutEnd; inout_stream >> m_fPositionBias; inout_stream >> m_fMipLevelScale; inout_stream >> m_fDepthBlurThreshold; return EZ_SUCCESS; } void ezAOPass::SetFadeOutStart(float fStart) { m_fFadeOutStart = ezMath::Clamp(fStart, 0.0f, m_fFadeOutEnd); } float ezAOPass::GetFadeOutStart() const { return m_fFadeOutStart; } void ezAOPass::SetFadeOutEnd(float fEnd) { if (m_fFadeOutEnd == fEnd) return; m_fFadeOutEnd = ezMath::Max(fEnd, m_fFadeOutStart); ezGALDevice::GetDefaultDevice()->DestroySamplerState(m_hSSAOSamplerState); } float ezAOPass::GetFadeOutEnd() const { return m_fFadeOutEnd; } void ezAOPass::CreateSamplerState() { if (m_hSSAOSamplerState.IsInvalidated()) { ezGALSamplerStateCreationDescription desc; desc.m_MinFilter = ezGALTextureFilterMode::Point; desc.m_MagFilter = ezGALTextureFilterMode::Point; desc.m_MipFilter = ezGALTextureFilterMode::Point; desc.m_AddressU = ezImageAddressMode::ClampBorder; desc.m_AddressV = ezImageAddressMode::ClampBorder; desc.m_AddressW = ezImageAddressMode::ClampBorder; desc.m_BorderColor = ezColor::White * m_fFadeOutEnd; m_hSSAOSamplerState = ezGALDevice::GetDefaultDevice()->CreateSamplerState(desc); } } EZ_STATICLINK_FILE(RendererCore, RendererCore_Pipeline_Implementation_Passes_AOPass);