Fixes for SSAO and SSR
This commit is contained in:
@@ -704,6 +704,12 @@ float RenderTools::GetDepthBounds(const RenderView& view, const Float3& point, b
|
||||
return Math::Clamp(depth, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float RenderTools::GetDepthBounds(const RenderView& view, float viewDistance, bool near)
|
||||
{
|
||||
Float3 point = view.Position + view.Direction * (viewDistance * 2.0f);
|
||||
return GetDepthBounds(view, point, near);
|
||||
}
|
||||
|
||||
Float3 RenderTools::GetColorQuantizationError(PixelFormat format)
|
||||
{
|
||||
Float3 mantissaBits;
|
||||
|
||||
@@ -155,6 +155,7 @@ public:
|
||||
static Float2 GetDepthBounds(const RenderView& view, const BoundingBox& bounds);
|
||||
static Float2 GetDepthBounds(const RenderView& view, const OrientedBoundingBox& bounds);
|
||||
static float GetDepthBounds(const RenderView& view, const Float3& point, bool near);
|
||||
static float GetDepthBounds(const RenderView& view, float viewDistance, bool near);
|
||||
static constexpr float DepthBoundMaxBackground = 1.0f - 0.0000001f; // Skip background/sky pixels from shading
|
||||
|
||||
// Calculates error for a given render target format to reduce floating-point precision artifacts via QuantizeColor (from Noise.hlsl).
|
||||
|
||||
@@ -270,12 +270,12 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
|
||||
// Cache data
|
||||
auto device = GPUDevice::Instance;
|
||||
auto context = device->GetMainContext();
|
||||
float m_sizeX = (float)renderContext.Buffers->GetWidth();
|
||||
float m_sizeY = (float)renderContext.Buffers->GetHeight();
|
||||
float m_halfSizeX = (m_sizeX + 1) / 2;
|
||||
float m_halfSizeY = (m_sizeY + 1) / 2;
|
||||
int32 m_sizeX = renderContext.Buffers->GetWidth();
|
||||
int32 m_sizeY = renderContext.Buffers->GetHeight();
|
||||
int32 m_halfSizeX = (m_sizeX + 1) / 2;
|
||||
int32 m_halfSizeY = (m_sizeY + 1) / 2;
|
||||
GPUTexture* depthBuffer = aoSettings.DepthResolution == ResolutionMode::Full ? renderContext.Buffers->DepthBuffer : renderContext.Buffers->RequestHalfResDepth(context);
|
||||
GPUTextureView* depthBufferApply = _depthBounds ? renderContext.Buffers->DepthBuffer ->ViewReadOnlyDepth() : nullptr;
|
||||
GPUTextureView* depthBufferApply = _depthBounds ? renderContext.Buffers->DepthBuffer->ViewReadOnlyDepth() : nullptr;
|
||||
|
||||
// Request temporary buffers
|
||||
GPUTexture* m_halfDepths[4];
|
||||
@@ -287,20 +287,20 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
#if SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET < 99
|
||||
tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, 0, SSAO_DEPTH_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews);
|
||||
tempDesc = GPUTextureDescription::New2D(m_halfSizeX, m_halfSizeY, 0, SSAO_DEPTH_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews);
|
||||
#else
|
||||
tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, SSAO_DEPTH_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget);
|
||||
tempDesc = GPUTextureDescription::New2D(m_halfSizeX, m_halfSizeY, SSAO_DEPTH_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget);
|
||||
#endif
|
||||
m_halfDepths[i] = RenderTargetPool::Get(tempDesc);
|
||||
RENDER_TARGET_POOL_SET_NAME(m_halfDepths[i], "SSAO.HalfDepth");
|
||||
}
|
||||
tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, SSAO_AO_RESULT_FORMAT);
|
||||
tempDesc = GPUTextureDescription::New2D(m_halfSizeX, m_halfSizeY, SSAO_AO_RESULT_FORMAT);
|
||||
m_pingPongHalfResultA = RenderTargetPool::Get(tempDesc);
|
||||
RENDER_TARGET_POOL_SET_NAME(m_pingPongHalfResultA, "SSAO.ResultsHalfA");
|
||||
tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, SSAO_AO_RESULT_FORMAT);
|
||||
tempDesc = GPUTextureDescription::New2D(m_halfSizeX, m_halfSizeY, SSAO_AO_RESULT_FORMAT);
|
||||
m_pingPongHalfResultB = RenderTargetPool::Get(tempDesc);
|
||||
RENDER_TARGET_POOL_SET_NAME(m_pingPongHalfResultA, "SSAO.ResultsHalfB");
|
||||
tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, SSAO_AO_RESULT_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget, 4);
|
||||
tempDesc = GPUTextureDescription::New2D(m_halfSizeX, m_halfSizeY, SSAO_AO_RESULT_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget, 4);
|
||||
m_finalResults = RenderTargetPool::Get(tempDesc);
|
||||
RENDER_TARGET_POOL_SET_NAME(m_finalResults, "SSAO.Results");
|
||||
}
|
||||
@@ -318,11 +318,12 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
|
||||
GBufferPass::SetInputs(view, _constantsBufferData.GBuffer);
|
||||
Matrix::Transpose(view.View, _constantsBufferData.ViewMatrix);
|
||||
|
||||
_constantsBufferData.ViewportPixelSize = Float2(1.0f / m_sizeX, 1.0f / m_sizeY);
|
||||
_constantsBufferData.HalfViewportPixelSize = Float2(1.0f / m_halfSizeX, 1.0f / m_halfSizeY);
|
||||
_constantsBufferData.ViewportPixelSize = Float2(1.0f / (float)m_sizeX, 1.0f / (float)m_sizeY);
|
||||
_constantsBufferData.HalfViewportPixelSize = Float2(1.0f / (float)m_halfSizeX, 1.0f / (float)m_halfSizeY);
|
||||
|
||||
_constantsBufferData.Viewport2xPixelSize = Float2(_constantsBufferData.ViewportPixelSize.X * 2.0f, _constantsBufferData.ViewportPixelSize.Y * 2.0f);
|
||||
_constantsBufferData.Viewport2xPixelSize_x_025 = Float2(_constantsBufferData.Viewport2xPixelSize.X * 0.25f, _constantsBufferData.Viewport2xPixelSize.Y * 0.25f);
|
||||
_constantsBufferData.InputDepthScale = aoSettings.DepthResolution == ResolutionMode::Full ? 2 : 1;
|
||||
|
||||
const float tanHalfFOVY = 1.0f / proj.Values[1][1];
|
||||
|
||||
@@ -375,7 +376,7 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
|
||||
|
||||
// Bind scene depth buffer and set proper viewport
|
||||
context->BindSR(SSAO_TEXTURE_SLOT0, depthBuffer);
|
||||
context->SetViewportAndScissors(m_halfSizeX, m_halfSizeY);
|
||||
context->SetViewportAndScissors((float)m_halfSizeX, (float)m_halfSizeY);
|
||||
|
||||
// Prepare depth in half resolution
|
||||
{
|
||||
@@ -437,7 +438,7 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
|
||||
|
||||
// Generate SSAO (interleaved in checkerboard pattern)
|
||||
{
|
||||
context->SetViewportAndScissors(m_halfSizeX, m_halfSizeY);
|
||||
context->SetViewportAndScissors((float)m_halfSizeX, (float)m_halfSizeY);
|
||||
for (int32 pass = 0; pass < 4; pass++)
|
||||
{
|
||||
if (settings.SkipHalfPixels && ((pass == 1) || (pass == 2)))
|
||||
@@ -526,10 +527,9 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
|
||||
}
|
||||
|
||||
// Apply
|
||||
Float3 depthBoundPoint = renderContext.View.Position + renderContext.View.Direction * (aoSettings.FadeOutDistance * 2.0f);
|
||||
context->SetDepthBounds(0.0f, RenderTools::GetDepthBounds(renderContext.View, depthBoundPoint, false));
|
||||
context->SetDepthBounds(0.0f, RenderTools::GetDepthBounds(renderContext.View, aoSettings.FadeOutDistance, false));
|
||||
context->BindSR(SSAO_TEXTURE_SLOT0, m_finalResults->ViewArray());
|
||||
context->SetViewportAndScissors(m_sizeX, m_sizeY);
|
||||
context->SetViewportAndScissors((float)m_sizeX, (float)m_sizeY);
|
||||
context->SetState(settings.SkipHalfPixels ? _psApplyHalf : _psApply);
|
||||
context->SetRenderTarget(depthBufferApply, renderContext.Buffers->GBuffer0->View());
|
||||
context->DrawFullscreenTriangle();
|
||||
|
||||
@@ -31,6 +31,9 @@ private:
|
||||
int32 PassIndex;
|
||||
float EffectMaxDistance;
|
||||
|
||||
Float3 Padding0;
|
||||
uint32 InputDepthScale;
|
||||
|
||||
Float2 Viewport2xPixelSize;
|
||||
Float2 Viewport2xPixelSize_x_025;
|
||||
|
||||
|
||||
@@ -362,15 +362,6 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
|
||||
{
|
||||
ScreenSpaceReflectionsPass::Instance()->Render(renderContext, *reflectionsBuffer, lightBuffer);
|
||||
context->SetViewportAndScissors(renderContext.Task->GetViewport());
|
||||
|
||||
/*
|
||||
// DEBUG_CODE
|
||||
context->RestoreViewport();
|
||||
context->SetRenderTarget(output);
|
||||
context->Draw(reflectionsRT);
|
||||
return;
|
||||
// DEBUG_CODE
|
||||
*/
|
||||
}
|
||||
|
||||
if (renderContext.View.Mode == ViewMode::Reflections)
|
||||
|
||||
@@ -166,14 +166,14 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture
|
||||
const int32 traceHeight = RenderTools::GetResolution(height, settings.RayTracePassResolution);
|
||||
const int32 resolveWidth = RenderTools::GetResolution(width, settings.ResolvePassResolution);
|
||||
const int32 resolveHeight = RenderTools::GetResolution(height, settings.ResolvePassResolution);
|
||||
const int32 colorBufferWidth = width / 2;
|
||||
const int32 colorBufferHeight = height / 2;
|
||||
const int32 temporalWidth = width;
|
||||
const int32 temporalHeight = height;
|
||||
const int32 colorBufferWidth = RenderTools::GetResolution(width, ResolutionMode::Half);
|
||||
const int32 colorBufferHeight = RenderTools::GetResolution(height, ResolutionMode::Half);
|
||||
const int32 temporalWidth = resolveWidth;
|
||||
const int32 temporalHeight = resolveHeight;
|
||||
const auto colorBufferMips = MipLevelsCount(colorBufferWidth, colorBufferHeight);
|
||||
|
||||
// Prepare buffers
|
||||
auto tempDesc = GPUTextureDescription::New2D(width / 2, height / 2, 0, PixelFormat::R11G11B10_Float, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews);
|
||||
auto tempDesc = GPUTextureDescription::New2D(colorBufferWidth, colorBufferHeight, 0, PixelFormat::R11G11B10_Float, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews);
|
||||
auto colorBuffer0 = RenderTargetPool::Get(tempDesc);
|
||||
RENDER_TARGET_POOL_SET_NAME(colorBuffer0, "SSR.ColorBuffer0");
|
||||
// TODO: maybe allocate colorBuffer1 smaller because mip0 is not used (the same as PostProcessingPass for Bloom), keep in sync to use the same buffer in frame
|
||||
@@ -305,9 +305,8 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture
|
||||
// and improves resolve pass performance (faster color texture lookups, less cache misses)
|
||||
// Also for high surface roughness values it adds more blur to the reflection tail which looks more realistic.
|
||||
|
||||
const auto filterMode = MultiScaler::FilterMode::GaussianBlur9;
|
||||
|
||||
// Downscale with gaussian blur
|
||||
auto filterMode = PLATFORM_ANDROID || PLATFORM_IOS || PLATFORM_SWITCH ? MultiScaler::FilterMode::GaussianBlur5 : MultiScaler::FilterMode::GaussianBlur9;
|
||||
for (int32 mipLevel = 1; mipLevel < colorBufferMips; mipLevel++)
|
||||
{
|
||||
const int32 mipWidth = Math::Max(colorBufferWidth >> mipLevel, 1);
|
||||
|
||||
Reference in New Issue
Block a user