New Depth Of Field working quite well with a small amount of artefacts
Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
+13
-10
@@ -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;
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+92
-9
@@ -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)
|
||||
{
|
||||
// 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 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;
|
||||
|
||||
|
||||
|
||||
PSOutput OUT = (PSOutput)0;
|
||||
|
||||
float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, IN.m_texCoord);
|
||||
float3 centerColor = centerSample.rgb;
|
||||
float centerCoc = centerSample.a;
|
||||
|
||||
centerColor /= centerCoc;
|
||||
|
||||
OUT.m_color.rgb = centerColor;
|
||||
OUT.m_color.a = centerCoc;
|
||||
OUT.m_color.rgb = color.rgb;
|
||||
OUT.m_color.a = alpha;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
|
||||
+105
@@ -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;
|
||||
}
|
||||
|
||||
+25
-11
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user