New Depth Of Field working quite well with a small amount of artefacts

Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com>
monroegm-disable-blank-issue-2
antonmic 4 years ago
parent 9e8e08a815
commit d04d9883bc

@ -67,6 +67,20 @@
}
]
},
{
"Name": "Tile5x5",
"TemplateName": "NewDepthOfFieldTile3x3Template",
"Connections": [
{
"LocalSlot": "Input",
"AttachmentRef": {
"Pass": "Tile3x3",
"Attachment": "Output"
}
}
]
},
{
"Name": "LargeFilter",
"TemplateName": "NewDepthOfFieldFilterLargeTemplate",
@ -82,7 +96,7 @@
{
"LocalSlot": "CocTile",
"AttachmentRef": {
"Pass": "Tile3x3",
"Pass": "Tile5x5",
"Attachment": "Output"
}
}

@ -15,6 +15,8 @@
#define SAMPLES_LOOP_2 16
#define SAMPLES_LOOP_3 24
#define SAMPLES_LOOP_TOTAL 48
// Must match the struct in NewDepthOfFieldPasses.cpp
struct NewDepthOfFieldConstants
{

@ -54,22 +54,25 @@ PSOutput MainPS(VSOutput IN)
// Calculate Alpha
float cocRadius = abs(coc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f;
float maxPixelDist = max(PassSrg::m_halfResDimensions.z, PassSrg::m_halfResDimensions.w);
float alpha = saturate(0.25f * cocRadius / maxPixelDist);
float alpha = saturate(cocRadius / maxPixelDist);
// Sample half res color and CoC
float4 colorAndCoC = PassSrg::m_halfResColorAndCoc.Sample(PassSrg::LinearSampler, halfResUV);
// Make out of focus foreground increasingly blue
float multiplier = saturate(1.0f + coc);
colorAndCoC.r *= multiplier;
colorAndCoC.g *= multiplier;
if(false)
{
// Make out of focus foreground increasingly blue
float multiplier = saturate(1.0f + coc);
colorAndCoC.r *= multiplier;
colorAndCoC.g *= multiplier;
// Make out of focus background increasingly red
multiplier = saturate(1.0f - coc);
colorAndCoC.b *= multiplier;
colorAndCoC.g *= multiplier;
}
// Make out of focus background increasingly red
multiplier = saturate(1.0f - coc);
colorAndCoC.b *= multiplier;
colorAndCoC.g *= multiplier;
// Output
PSOutput OUT;
OUT.m_color.rgb = colorAndCoC.rgb;

@ -93,8 +93,8 @@ PSOutput MainPS(VSOutput IN)
// See http://advances.realtimerendering.com/s2013/Sousa_Graphics_Gems_CryENGINE3.pptx
coc = abs(coc) > COC_EPSILON ? coc : -COC_EPSILON;
OUT.m_color.rgb *= abs(coc);
OUT.m_color.a = coc;
return OUT;
}

@ -31,20 +31,103 @@ ShaderResourceGroup PassSrg : SRG_PerPass
AddressV = Clamp;
AddressW = Clamp;
};
Sampler PointSampler
{
MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
AddressU = Clamp;
AddressV = Clamp;
AddressW = Clamp;
};
}
float3 GetOffsetUV(uint index, float2 offsetMultiplier)
{
float3 offset = PassSrg::m_dofConstants.samplePositions[index].xyz;
offset.xy *= offsetMultiplier;
return offset;
}
float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc)
{
// The maximum distance for which samples are valid is the min of the sample CoC and the center CoC
float maxRadius = abs(min(sampleCoc, centerCoc));
// radius = samplingRadius * offsetRadius;
// falloff = maxRadius - radius;
// weight = 1 + (4 * falloff)
float falloff = mad(-samplingRadius, offsetRadius, maxRadius);
float weight = saturate(mad(4, falloff, 1));
return weight;
}
PSOutput MainPS(VSOutput IN)
{
PSOutput OUT = (PSOutput)0;
// Get center sample
float2 pixelUV = IN.m_texCoord;
float4 color = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba;
float centerCoc = color.a;
// Get tile min and max
int2 tile = int2(IN.m_position.xy) / 16;
float minCoc = PassSrg::m_minMaxCocTile[tile].x;
// Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w
float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w;
// Sampling radius
float cocRadius = max( abs(centerCoc), -minCoc);
float screenRadius = cocRadius * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f;
float2 offsetMultiplier = float2(screenRadius / aspectRatio, screenRadius);
float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, IN.m_texCoord);
float3 centerColor = centerSample.rgb;
float centerCoc = centerSample.a;
centerColor /= centerCoc;
float4 backgroundColor = float4(0, 0, 0, 0);
{
float backgroundMin = min(0, centerCoc);
color.rgb /= abs(color.a);
color.a = 1;
for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i)
{
// Calculate sample offset
float3 offset = GetOffsetUV(i, offsetMultiplier);
// Get sample
float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offset.xy).rgba;
sampleColorCoc.rgb /= abs(sampleColorCoc.a);
// Calculate weight for sample
float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc);
sampleColorCoc.rgb *= weight;
bool isBackground = (sampleColorCoc.a < backgroundMin);
// We accumulate weight in alpha channel of color and backgroundColor
sampleColorCoc.a = weight;
// Accumulate
backgroundColor += isBackground * sampleColorCoc;
color += !isBackground * sampleColorCoc;
}
}
float backgroundRatio = backgroundColor.a / float(SAMPLES_LOOP_TOTAL);
float alpha = backgroundRatio > abs(centerCoc) ? -backgroundRatio : centerCoc;
color.rgb /= max(color.a, COC_EPSILON);
backgroundColor.rgb /= max(backgroundColor.a, COC_EPSILON);
color = color * saturate(1 - backgroundRatio) + backgroundColor * backgroundRatio;
//color.rgb += backgroundColor.rgb;
OUT.m_color.rgb = centerColor;
OUT.m_color.a = centerCoc;
PSOutput OUT = (PSOutput)0;
OUT.m_color.rgb = color.rgb;
OUT.m_color.a = alpha;
return OUT;
}

@ -0,0 +1,105 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/Features/PostProcessing/FullscreenPixelInfo.azsli>
#include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
#include "DepthOfField.azsli"
#include "NewDepthOfFieldCommon.azsli"
#include <viewsrg.srgi>
ShaderResourceGroup PassSrg : SRG_PerPass
{
Texture2D<float4> m_colorAndCoc;
Texture2D<float2> m_minMaxCocTile;
float4 m_textureDimensions;
NewDepthOfFieldConstants m_dofConstants;
Sampler LinearSampler
{
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = Clamp;
AddressV = Clamp;
AddressW = Clamp;
};
}
float2 GetOffsetUV(uint index, float2 offsetMultiplier)
{
return PassSrg::m_dofConstants.samplePositions[index].xy * offsetMultiplier;
}
PSOutput MainPS(VSOutput IN)
{
// Get center sample
float2 pixelUV = IN.m_texCoord;
float4 color = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba;
float centerCoc = color.a;
// Get tile min and max
int2 tile = int2(IN.m_position.xy) / 16;
float minCoc = PassSrg::m_minMaxCocTile[tile].x;
// Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w
float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w;
// Sampling radius
float cocRadius = max( abs(centerCoc), -minCoc);
cocRadius *= ViewSrg::m_dof.m_cocToScreenRatio * 0.5f;
float2 offsetMultiplier = float2(cocRadius / aspectRatio, cocRadius);
float4 negColor = float4(0, 0, 0, 0);
{
float negMin = min(0, centerCoc);
color.rgb /= abs(color.a);
color.a = 1;
for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i)
{
// Calculate sample offset
float2 offsetUV = GetOffsetUV(i, offsetMultiplier);
// Get sample
float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba;
// Calculate weight and adjust sample
float cocDiff = sampleColorCoc.a - centerCoc;
float weight = saturate( 2 - (20 * cocDiff));
sampleColorCoc.rgb *= (weight / abs(sampleColorCoc.a));
//
// bool isNeg = (sampleColorCoc.a < negMin);
// sampleColorCoc.a = weight;
//
// // Accumulate
// negColor += isNeg * sampleColorCoc;
// color += !isNeg * sampleColorCoc;
}
}
float negRatio = negColor.a / float(SAMPLES_LOOP_TOTAL);
float alpha = negRatio > abs(centerCoc) ? -negRatio : centerCoc;
color = color * saturate(1 - negRatio) + negColor;
color.rgb /= max(color.a, COC_EPSILON);
color.rgb += negColor.rgb;
//float alpha = 1.0f;
PSOutput OUT = (PSOutput)0;
OUT.m_color.rgb = color.rgb;
OUT.m_color.a = alpha;
return OUT;
}

@ -33,9 +33,9 @@ ShaderResourceGroup PassSrg : SRG_PerPass
};
}
float2 GetOffsetUV(uint index, float radiusMultiplier)
float2 GetOffsetUV(uint index, float2 offsetMultiplier)
{
return PassSrg::m_dofConstants.samplePositions[index] * radiusMultiplier * PassSrg::m_textureDimensions.zw;
return PassSrg::m_dofConstants.samplePositions[index].xy * offsetMultiplier;
}
PSOutput MainPS(VSOutput IN)
@ -47,27 +47,41 @@ PSOutput MainPS(VSOutput IN)
float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba;
float centerCoc = centerSample.a;
// Color and weight accumulation
float3 color = centerSample.rgb;
float totalWeight = 1;
// Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w
float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w;
// Sampling radius
float cocRadius = abs(centerCoc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f;
cocRadius *= 0.5f; // This is the small filter, half the sampling radius
float2 offsetMultiplier = float2(cocRadius / aspectRatio, cocRadius);
for(uint i = 0; i < SAMPLES_LOOP_1; ++i)
// Color and weight accumulation
float3 color = centerSample.rgb;
float totalWeight = 1;
for(uint i = 0; i < 8; ++i)
{
float2 offsetUV = GetOffsetUV(i, cocRadius);
float4 sample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba;
float cocDiff = abs(sample.a - centerCoC);
// Calculate sample offset
float2 offsetUV = GetOffsetUV(i, offsetMultiplier);
// Get sample
float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba;
// Calculate weight
float cocDiff = sampleColorCoc.a - centerCoc;
float weight = saturate( 2 - (20 * cocDiff));
color += sample.rgb * weight;
// Accumulate sample and weight
color += sampleColorCoc.rgb * weight;
totalWeight += weight;
}
// Normalize accumulated sample
color /= totalWeight;
// Output
PSOutput OUT;
OUT.m_color.rgb = color / totalWeight;
OUT.m_color.rgb = color;
OUT.m_color.a = centerCoc;
return OUT;
}

Loading…
Cancel
Save