Addressing review feedback
Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com>
This commit is contained in:
@@ -112,6 +112,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
// Todo: remove the old depth of field implementation and rename NewDepthOfField -> DepthOfField
|
||||
//{
|
||||
// "Name": "DepthOfFieldPass",
|
||||
// "TemplateName": "DepthOfFieldTemplate",
|
||||
|
||||
+4
-3
@@ -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)
|
||||
|
||||
+2
-1
@@ -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);
|
||||
|
||||
|
||||
+4
-3
@@ -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);
|
||||
|
||||
+3
-2
@@ -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;
|
||||
|
||||
+17
-16
@@ -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;
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user