Addressing review feedback

Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com>
This commit is contained in:
antonmic
2021-10-21 20:15:39 -07:00
parent 7eaf54e48d
commit e5c7703aa7
8 changed files with 56 additions and 26 deletions
@@ -112,6 +112,7 @@
}
]
},
// Todo: remove the old depth of field implementation and rename NewDepthOfField -> DepthOfField
//{
// "Name": "DepthOfFieldPass",
// "TemplateName": "DepthOfFieldTemplate",
@@ -22,6 +22,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
Texture2D<float4> m_halfResColorAndCoc;
// Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height
// Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file
float4 m_fullResDimensions;
float4 m_halfResDimensions;
@@ -69,15 +70,15 @@ PSOutput MainPS(VSOutput IN)
// --- Weights based on pixel proximity ---
// Based on which pixel we're shading, we'll be closer/further to half res pixels
// Here are the pre-caculated weights, arranged to match the Gather pattern
// Based on which pixel we're shading, we'll be closer/farther to half res pixels
// Here are the pre-calculated weights, arranged to match the Gather pattern
//
// W Z
// X Y
//
// Note: These weights come down to the same contributions as if we did a linear sample
int2 pixel = int2(fullResPixelPos);
float4 weights = (pixel.x & 1)
float4 weights = (pixel.x & 1)
? ( (pixel.y & 1) ? float4(0.1875f, 0.0625f, 0.1875f, 0.5625f)
: float4(0.5625f, 0.1875f, 0.0625f, 0.1875f) )
: ( (pixel.y & 1) ? float4(0.0625f, 0.1875f, 0.5625f, 0.1875f)
@@ -22,6 +22,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
Texture2D<float4> m_depth;
// Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height
// Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file
float4 m_inputDimensions;
float4 m_outputDimensions;
@@ -61,7 +62,7 @@ PSOutput MainPS(VSOutput IN)
// Clamp CoC
cocGather = clamp(cocGather, -1.0f, 1.0f);
// Weigh samles by CoC to avoid in foces pixels bleeding into bokeh effect
// Weight samples by CoC to avoid in focus pixels bleeding into bokeh effect
float4 weights = abs(cocGather) + COC_EPSILON;
weights = weights / (weights.x + weights.y + weights.z + weights.w);
@@ -19,6 +19,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
Texture2D<float2> m_minMaxCocTile;
// Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height
// Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file
float4 m_textureDimensions;
NewDepthOfFieldConstants m_dofConstants;
@@ -51,7 +52,7 @@ float3 GetOffset(uint index, float2 offsetUVMultiplier)
return offset;
}
float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc)
float CalculateWeight(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));
@@ -109,7 +110,7 @@ PSOutput MainPS(VSOutput IN)
float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offset.xy).rgba;
// Calculate weight for sample
float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc);
float weight = CalculateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc);
// Accumulate
color += weight * sampleColorCoc;
@@ -135,7 +136,7 @@ PSOutput MainPS(VSOutput IN)
sampleColorCoc.rgb /= abs(sampleColorCoc.a);
// Calculate weight for sample
float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc);
float weight = CalculateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc);
sampleColorCoc.rgb *= weight;
bool isBackground = (sampleColorCoc.a < backgroundMin);
@@ -19,6 +19,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
Texture2D<float2> m_minMaxCocTile;
// Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height
// Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file
float4 m_textureDimensions;
NewDepthOfFieldConstants m_dofConstants;
@@ -51,7 +52,7 @@ float3 GetOffset(uint index, float2 offsetUVMultiplier)
return offset;
}
float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc)
float CalculateWeight(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));
@@ -102,7 +103,7 @@ PSOutput MainPS(VSOutput IN)
float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offset.xy).rgba;
// Calculate weight
float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc);
float weight = CalculateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc);
// Accumulate sample and weight
color.rgb += sampleColorCoc.rgb * weight;
@@ -15,6 +15,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
Texture2D<float2> m_minMaxSource;
// Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height
// Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file
float4 m_textureDimensions;
Sampler PointSampler
@@ -38,28 +39,28 @@ PSOutput MainPS(VSOutput IN)
{
// We want the min/max in a 3x3 region. Start sampling up left.
float2 startPixelPos = IN.m_position.xy - float2(1, 1);
float2 pixelSizeInUV = PassSrg::m_textureDimensions.zw;
float2 startUV = startPixelPos * pixelSizeInUV;
float cocMin = 1.0f;
float cocMax = -1.0f;
float cocMax = -1.0f;
// Gather min/max in 3x3 region
[unroll]
for(float Y = 0.0f; Y < 3.0f; Y += 1.0f)
[unroll]
for(float Y = 0.0f; Y < 3.0f; Y += 1.0f)
{
[unroll]
for(float X = 0.0f; X < 3.0f; X += 1.0f)
{
float2 sampleUV = mad(float2(X, Y), pixelSizeInUV, startUV);
float2 minMax = PassSrg::m_minMaxSource.SampleLevel(PassSrg::PointSampler, sampleUV, 0).xy;
cocMin = min(cocMin, minMax.x);
cocMax = max(cocMax, minMax.y);
}
[unroll]
for(float X = 0.0f; X < 3.0f; X += 1.0f)
{
float2 sampleUV = mad(float2(X, Y), pixelSizeInUV, startUV);
float2 minMax = PassSrg::m_minMaxSource.SampleLevel(PassSrg::PointSampler, sampleUV, 0).xy;
cocMin = min(cocMin, minMax.x);
cocMax = max(cocMax, minMax.y);
}
}
PSOutput output;
output.m_color.x = cocMin;
output.m_color.y = cocMax;
@@ -19,6 +19,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
RWTexture2D<float2> m_minMaxCoC;
// Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height
// Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file
float4 m_inputDimensions;
float4 m_outputDimensions;
@@ -59,7 +60,7 @@ void MainCS(uint3 group_thread_id : SV_GroupThreadID, uint3 group_id : SV_GroupI
// For atomic min/max to work with uints, floating point values should be positive
// Map from [-1, 1] range to [0, 2] and cast as uint
InterlockedMin( LDS_MIN_COC[group_thread_id.x], asuint(cocMin + 1) );
InterlockedMax( LDS_MAX_COC[group_thread_id.x], asuint(cocMax + 1) );
InterlockedMax( LDS_MAX_COC[group_thread_id.x], asuint(cocMax + 1) );
// Sync LDS
GroupMemoryBarrierWithGroupSync();
@@ -17,6 +17,29 @@ namespace AZ
{
namespace Render
{
// Technique
//
// 1. This Depth of Field technique starts by downsampling the lighting buffer and calculating
// the circle of confusion (CoC) for each downsampled pixel.
//
// 2. It then computes the min and max CoC for tiles of 16x16 pixels
//
// 3. It expands the min and max in a 3x3 region (twice, so 5x5 at the end) so that each tile
// tile pixel has the min and max CoCs of the 5x5 tile region around it
//
// 4. We perform a 48 tap scatter-as-gather blur around each pixel
//
// 5. We perform a follow up 8 tap scatter-as-gather blur to fill the holes from the first blur
//
// 6. We composite the blurred half resolution image onto the full resolution lighting buffer
//
// See http://advances.realtimerendering.com/s2013/Sousa_Graphics_Gems_CryENGINE3.pptx
// for a more detailed explanation.
//
// Notes: The name NewDepthOfField is in contrast to the previously implemented depth of field method
// That method will be removed in a follow up change and at that point NewDepthOfField will be renamed
// to simple DepthOfField.
//! Parent pass for the new depth of field technique
//! Main updates the view srg via the depth of field settings
//! And enables/disables all depth of field passes based on component activation