@@ -15,9 +15,13 @@
|
||||
#endif
|
||||
|
||||
#if FLAX_REVERSE_Z
|
||||
#define GPU_DEPTH_CLEAR_VALUE 0.0f
|
||||
#define GPU_DEPTH_MIN_VALUE 1.0f
|
||||
#define GPU_DEPTH_MAX_VALUE 0.0f
|
||||
#define GPU_DEPTH_BOUNDS_SWAP(min, max) max, min
|
||||
#else
|
||||
#define GPU_DEPTH_CLEAR_VALUE 1.0f
|
||||
#define GPU_DEPTH_MIN_VALUE 0.0f
|
||||
#define GPU_DEPTH_MAX_VALUE 1.0f
|
||||
#define GPU_DEPTH_BOUNDS_SWAP(min, max) min, max
|
||||
#endif
|
||||
|
||||
class GPUConstantBuffer;
|
||||
@@ -214,7 +218,7 @@ public:
|
||||
/// <param name="depthBuffer">The depth buffer to clear.</param>
|
||||
/// <param name="depthValue">The clear depth value.</param>
|
||||
/// <param name="stencilValue">The clear stencil value.</param>
|
||||
API_FUNCTION() virtual void ClearDepth(GPUTextureView* depthBuffer, float depthValue = GPU_DEPTH_CLEAR_VALUE, uint8 stencilValue = 0) = 0;
|
||||
API_FUNCTION() virtual void ClearDepth(GPUTextureView* depthBuffer, float depthValue = GPU_DEPTH_MAX_VALUE, uint8 stencilValue = 0) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Clears an unordered access buffer with a float value.
|
||||
@@ -634,9 +638,10 @@ public:
|
||||
/// <summary>
|
||||
/// Sets the minimum and maximum depth values for depth bounds test.
|
||||
/// </summary>
|
||||
/// <remarks>Both values must be between 0.0 and 1.0, MinDepth must be less than or equal to MaxDepth.</remarks>
|
||||
/// <param name="minDepth">The minimum value for depth bound test.</param>
|
||||
/// <param name="maxDepth">The maximum value for depth bound test.</param>
|
||||
API_FUNCTION() virtual void SetDepthBounds(float minDepth, float maxDepth) = 0;
|
||||
API_FUNCTION() virtual void SetDepthBounds(float minDepth = 0.0f, float maxDepth = 1.0f) = 0;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -684,6 +684,20 @@ float RenderTools::TemporalHalton(int32 index, int32 base)
|
||||
|
||||
Float2 RenderTools::GetDepthBounds(const RenderView& view, const Float3& nearPoint, const Float3& farPoint)
|
||||
{
|
||||
#if FLAX_REVERSE_Z
|
||||
Float3 viewNearPoint = Float3::Transform(nearPoint, view.View);
|
||||
Float3 viewFarPoint = Float3::Transform(farPoint, view.View);
|
||||
|
||||
viewNearPoint.Z = Math::Max(viewNearPoint.Z, view.Near);
|
||||
viewFarPoint.Z = Math::Min(viewFarPoint.Z, view.Far);
|
||||
|
||||
Float4 clipNearPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewNearPoint.Z, 1));
|
||||
Float4 clipFarPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewFarPoint.Z, 1));
|
||||
clipNearPoint /= clipNearPoint.W;
|
||||
clipFarPoint /= clipFarPoint.W;
|
||||
|
||||
return Float2(clipNearPoint.Z, clipFarPoint.Z);
|
||||
#else
|
||||
// Point closest the view
|
||||
const Float4 nearPointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(nearPoint, 1.0));
|
||||
float nearDepth = nearPointClip.Z / nearPointClip.W;
|
||||
@@ -700,8 +714,8 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const Float3& nearPoi
|
||||
nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f);
|
||||
farDepth = Math::Clamp(farDepth, nearDepth, 1.0f);
|
||||
|
||||
// TODO: swap depths when using reversed depth buffer
|
||||
return Float2(nearDepth, farDepth);
|
||||
#endif
|
||||
}
|
||||
|
||||
Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingSphere& bounds)
|
||||
@@ -713,6 +727,24 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingSphere&
|
||||
|
||||
Float2 RenderTools::GetDepthBounds(const RenderView& view, const Span<Float3>& points)
|
||||
{
|
||||
#if FLAX_REVERSE_Z
|
||||
// Find min and max view depth range for list of points
|
||||
float nearDepth = view.Far, farDepth = view.Near;
|
||||
for (int32 i = 0; i < points.Length(); i++)
|
||||
{
|
||||
const Float3 viewPoint = Float3::Transform(points[i], view.View);
|
||||
nearDepth = Math::Min(nearDepth, viewPoint.Z);
|
||||
farDepth = Math::Max(farDepth, viewPoint.Z);
|
||||
}
|
||||
|
||||
// Project end points to clip space
|
||||
Float4 clipNearPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, nearDepth, 1));
|
||||
Float4 clipFarPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, farDepth, 1));
|
||||
clipNearPoint /= clipNearPoint.W;
|
||||
clipFarPoint /= clipFarPoint.W;
|
||||
|
||||
return Float2(clipNearPoint.Z, clipFarPoint.Z);
|
||||
#else
|
||||
// Find min and max depth range for list of points
|
||||
float nearDepth = 1.0f, farDepth = 0.0f;
|
||||
for (int32 i = 0; i < points.Length(); i++)
|
||||
@@ -729,8 +761,8 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const Span<Float3>& p
|
||||
nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f);
|
||||
farDepth = Math::Clamp(farDepth, nearDepth, 1.0f);
|
||||
|
||||
// TODO: swap depths when using reversed depth buffer
|
||||
return Float2(nearDepth, farDepth);
|
||||
#endif
|
||||
}
|
||||
|
||||
Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingBox& bounds)
|
||||
@@ -749,11 +781,21 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const OrientedBoundin
|
||||
|
||||
float RenderTools::GetDepthBounds(const RenderView& view, const Float3& point, bool near)
|
||||
{
|
||||
#if FLAX_REVERSE_Z
|
||||
Float3 viewPoint = Float3::Transform(point, view.View);
|
||||
viewPoint.Z = Math::Clamp(viewPoint.Z, view.Near, view.Far);
|
||||
|
||||
Float4 clipPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewPoint.Z, 1));
|
||||
clipPoint /= clipPoint.W;
|
||||
|
||||
return clipPoint.Z;
|
||||
#else
|
||||
const Float4 pointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(point, 1.0));
|
||||
float depth = pointClip.Z / pointClip.W;
|
||||
if (depth >= 1.0f)
|
||||
depth = near ? 0.0f : 1.0f; // Point is behind the view
|
||||
return Math::Clamp(depth, 0.0f, 1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float RenderTools::GetDepthBounds(const RenderView& view, float viewDistance, bool near)
|
||||
|
||||
@@ -173,7 +173,12 @@ public:
|
||||
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
|
||||
// Skip background/sky pixels from shading
|
||||
#if FLAX_REVERSE_Z
|
||||
static constexpr float DepthBoundMaxBackground = 0.0000001f;
|
||||
#else
|
||||
static constexpr float DepthBoundMaxBackground = 1.0f - 0.0000001f;
|
||||
#endif
|
||||
|
||||
// Calculates error for a given render target format to reduce floating-point precision artifacts via QuantizeColor (from Noise.hlsl).
|
||||
static Float3 GetColorQuantizationError(PixelFormat format);
|
||||
|
||||
@@ -796,9 +796,8 @@ void GPUContextVulkan::OnDrawCall()
|
||||
if (_psDirtyFlag && pipelineState && (_rtDepth || _rtCount))
|
||||
{
|
||||
_psDirtyFlag = false;
|
||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer()->GetHandle();
|
||||
const auto pipeline = pipelineState->GetState(_renderPass, _vertexLayout);
|
||||
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
RENDER_STAT_PS_STATE_CHANGE();
|
||||
if (_depthBoundsEnable && (!_currentState || !_currentState->DepthBoundsEnable))
|
||||
{
|
||||
|
||||
@@ -536,7 +536,7 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
|
||||
}
|
||||
|
||||
// Apply
|
||||
context->SetDepthBounds(0.0f, RenderTools::GetDepthBounds(renderContext.View, aoSettings.FadeOutDistance, false));
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(GPU_DEPTH_MIN_VALUE, RenderTools::GetDepthBounds(renderContext.View, aoSettings.FadeOutDistance, false)));
|
||||
context->BindSR(SSAO_TEXTURE_SLOT0, m_finalResults->ViewArray());
|
||||
context->SetViewportAndScissors((float)m_sizeX, (float)m_sizeY);
|
||||
context->SetState(settings.SkipHalfPixels ? _psApplyHalf : _psApply);
|
||||
|
||||
@@ -283,7 +283,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV
|
||||
if (_depthBounds)
|
||||
{
|
||||
Float2 minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, light.Radius));
|
||||
context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y);
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(minMaxDepth.X, minMaxDepth.Y));
|
||||
}
|
||||
context->UpdateCB(cb0, &perLight);
|
||||
context->BindCB(0, cb0);
|
||||
@@ -331,7 +331,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV
|
||||
if (_depthBounds)
|
||||
{
|
||||
Float2 minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, light.Radius));
|
||||
context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y);
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(minMaxDepth.X, minMaxDepth.Y));
|
||||
}
|
||||
context->UpdateCB(cb0, &perLight);
|
||||
context->BindCB(0, cb0);
|
||||
@@ -365,7 +365,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV
|
||||
|
||||
// Calculate lighting
|
||||
if (_depthBounds)
|
||||
context->SetDepthBounds(0.0f, RenderTools::DepthBoundMaxBackground);
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(GPU_DEPTH_MIN_VALUE, RenderTools::DepthBoundMaxBackground));
|
||||
context->UpdateCB(cb0, &perLight);
|
||||
context->BindCB(0, cb0);
|
||||
context->BindCB(1, cb1);
|
||||
@@ -398,7 +398,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV
|
||||
if (_depthBounds)
|
||||
{
|
||||
Float2 minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, light.Radius));
|
||||
context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y);
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(minMaxDepth.X, minMaxDepth.Y));
|
||||
}
|
||||
context->UpdateCB(cb0, &perLight);
|
||||
context->BindCB(0, cb0);
|
||||
@@ -411,7 +411,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV
|
||||
|
||||
// Restore state
|
||||
if (_depthBounds)
|
||||
context->SetDepthBounds(0, 1);
|
||||
context->SetDepthBounds();
|
||||
context->ResetRenderTarget();
|
||||
context->ResetSR();
|
||||
context->ResetCB();
|
||||
|
||||
@@ -347,7 +347,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
|
||||
|
||||
// Setup depth bounds (if device supports it)
|
||||
if (_depthBounds)
|
||||
context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y);
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(minMaxDepth.X, minMaxDepth.Y));
|
||||
|
||||
// Pack probe properties buffer
|
||||
probe.SetShaderData(data.PData);
|
||||
@@ -368,7 +368,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
|
||||
context->UnBindSR(4);
|
||||
context->ResetRenderTarget();
|
||||
if (_depthBounds)
|
||||
context->SetDepthBounds(0, 1);
|
||||
context->SetDepthBounds();
|
||||
}
|
||||
|
||||
// Screen Space Reflections pass
|
||||
@@ -417,7 +417,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
|
||||
if (_depthBounds)
|
||||
{
|
||||
context->SetRenderTarget(depthBufferRTV, lightBuffer);
|
||||
context->SetDepthBounds(0, RenderTools::DepthBoundMaxBackground);
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(GPU_DEPTH_MIN_VALUE, RenderTools::DepthBoundMaxBackground));
|
||||
}
|
||||
else
|
||||
context->SetRenderTarget(lightBuffer);
|
||||
@@ -430,7 +430,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
|
||||
context->SetState(_psCombinePass);
|
||||
context->DrawFullscreenTriangle();
|
||||
if (_depthBounds)
|
||||
context->SetDepthBounds(0, 1);
|
||||
context->SetDepthBounds();
|
||||
}
|
||||
|
||||
RenderTargetPool::Release(ssrBuffer);
|
||||
|
||||
@@ -1147,11 +1147,7 @@ void ShadowsPass::SetupLight(ShadowsCustomBuffer& shadows, RenderContext& render
|
||||
void ShadowsPass::ClearShadowMapTile(GPUContext* context, GPUConstantBuffer* quadShaderCB, QuadShaderData& quadShaderData) const
|
||||
{
|
||||
// Color.r is used by PS_DepthClear in Quad shader to clear depth
|
||||
#if FLAX_REVERSE_Z
|
||||
quadShaderData.Color = Float4::Zero;
|
||||
#else
|
||||
quadShaderData.Color = Float4::One;
|
||||
#endif
|
||||
quadShaderData.Color = GPU_DEPTH_MAX_VALUE;
|
||||
context->UpdateCB(quadShaderCB, &quadShaderData);
|
||||
context->BindCB(0, quadShaderCB);
|
||||
|
||||
@@ -1753,8 +1749,8 @@ void ShadowsPass::RenderShadowMask(RenderContextBatch& renderContextBatch, Rende
|
||||
if (light.IsPointLight || light.IsSpotLight)
|
||||
minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, ((RenderLocalLightData&)light).Radius));
|
||||
else //if (light.IsDirectionalLight)
|
||||
minMaxDepth = Float2(0.0f, RenderTools::DepthBoundMaxBackground);
|
||||
context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y);
|
||||
minMaxDepth = Float2(GPU_DEPTH_MIN_VALUE, RenderTools::DepthBoundMaxBackground);
|
||||
context->SetDepthBounds(GPU_DEPTH_BOUNDS_SWAP(minMaxDepth.X, minMaxDepth.Y));
|
||||
}
|
||||
if (light.IsPointLight)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user