Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-08-04 23:30:09 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-08-05 15:45:09 +0300
commit72cdb0ed2d2cc4eebe9c756d2a87e2513b6bf1db (patch)
treeaf86ee2596082365bd048ec86f041307b8b59799 /source/blender/draw/engines
parent897aa777c53439d67401b4ae3d567394a80f8be7 (diff)
EEVEE-Next: Depth Of Field: Improve image stability
This adds anti-flicker pass to the slight focus region by using the temporaly stable output from stabilize pass. This also fixes the bilateral weight factor which was reversed.
Diffstat (limited to 'source/blender/draw/engines')
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc5
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh1
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl12
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl52
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl34
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh3
6 files changed, 78 insertions, 29 deletions
diff --git a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
index e3db4a7f0ef..713fcf77dc8 100644
--- a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
@@ -470,6 +470,7 @@ void DepthOfField::resolve_pass_sync()
DRW_shgroup_uniform_block(grp, "dof_buf", data_);
DRW_shgroup_uniform_texture_ref_ex(grp, "depth_tx", &render_buffers.depth_tx, no_filter);
DRW_shgroup_uniform_texture_ref_ex(grp, "color_tx", &input_color_tx_, no_filter);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "stable_color_tx", &resolve_stable_color_tx_, no_filter);
DRW_shgroup_uniform_texture_ref_ex(grp, "color_bg_tx", &color_bg_tx_.current(), with_filter);
DRW_shgroup_uniform_texture_ref_ex(grp, "color_fg_tx", &color_fg_tx_.current(), with_filter);
DRW_shgroup_uniform_image_ref(grp, "in_tiles_fg_img", &tiles_fg_tx_.current());
@@ -593,7 +594,7 @@ void DepthOfField::render(GPUTexture **input_tx,
}
{
setup_color_tx_.acquire(half_res, GPU_RGBA16F);
- setup_coc_tx_.acquire(half_res, GPU_RG16F);
+ setup_coc_tx_.acquire(half_res, GPU_R16F);
DRW_draw_pass(setup_ps_);
}
@@ -741,6 +742,8 @@ void DepthOfField::render(GPUTexture **input_tx,
{
DRW_stats_group_start("Resolve");
+ resolve_stable_color_tx_ = dof_buffer.stabilize_history_tx_;
+
DRW_draw_pass(resolve_ps_);
color_bg_tx_.current().release();
diff --git a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh
index a11924c3806..84134e94483 100644
--- a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh
@@ -127,6 +127,7 @@ class DepthOfField {
DRWPass *scatter_bg_ps_ = nullptr;
/** Recombine the results and also perform a slight out of focus gather. */
+ GPUTexture *resolve_stable_color_tx_ = nullptr;
int3 dispatch_resolve_size_ = int3(-1);
DRWPass *resolve_ps_ = nullptr;
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
index 15c1073309a..97c53ce3692 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
@@ -6,6 +6,7 @@
**/
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_colorspace_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_depth_of_field_lib.glsl)
@@ -339,10 +340,10 @@ void dof_gather_accumulate_resolve(int total_sample_count,
out_weight = 0.0;
}
/* Same thing for alpha channel. */
- if (out_col.a > 0.99) {
+ if (out_col.a > 0.993) {
out_col.a = 1.0;
}
- else if (out_col.a < 0.01) {
+ else if (out_col.a < 0.003) {
out_col.a = 0.0;
}
}
@@ -573,7 +574,8 @@ void dof_slight_focus_gather(sampler2D depth_tx,
sampler2D bkh_lut_tx, /* Renamed because of ugly macro job. */
float radius,
out vec4 out_color,
- out float out_weight)
+ out float out_weight,
+ out float out_center_coc)
{
vec2 frag_coord = vec2(gl_GlobalInvocationID.xy) + 0.5;
float noise_offset = sampling_rng_1D_get(SAMPLING_LENS_U);
@@ -650,6 +652,8 @@ void dof_slight_focus_gather(sampler2D depth_tx,
center_data.coc = clamp(center_data.coc, -dof_buf.coc_abs_max, dof_buf.coc_abs_max);
center_data.dist = 0.0;
+ out_center_coc = center_data.coc;
+
/* Slide 38. */
float bordering_radius = 0.5;
@@ -666,7 +670,7 @@ void dof_slight_focus_gather(sampler2D depth_tx,
dof_gather_accumulate_resolve(total_sample_count, bg_accum, bg_col, bg_weight, unused_occlusion);
dof_gather_accumulate_resolve(total_sample_count, fg_accum, fg_col, fg_weight, unused_occlusion);
- /* Fix weighting issues on perfectly focus > slight focus transitionning areas. */
+ /* Fix weighting issues on perfectly focus to slight focus transitionning areas. */
if (abs(center_data.coc) < 0.5) {
bg_col = center_data.color;
bg_weight = 1.0;
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl
index 2efcf43a0f6..a4b58f950a0 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl
@@ -41,6 +41,45 @@ float dof_slight_focus_coc_tile_get(vec2 frag_coord)
return uintBitsToFloat(shared_max_slight_focus_abs_coc);
}
+vec3 dof_neighborhood_clamp(vec2 frag_coord, vec3 color, float center_coc, float weight)
+{
+ /* Stabilize color by clamping with the stable half res neighboorhood. */
+ vec3 neighbor_min, neighbor_max;
+ const vec2 corners[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));
+ for (int i = 0; i < 4; i++) {
+ /**
+ * Visit the 4 half-res texels around (and containing) the fullres texel.
+ * Here a diagram of a fullscreen texel (f) in the bottom left corner of a half res texel.
+ * We sample the stable half-resolution texture at the 4 location denoted by (h).
+ * ┌───────┬───────┐
+ * │ h │ h │
+ * │ │ │
+ * │ │ f │
+ * ├───────┼───────┤
+ * │ h │ h │
+ * │ │ │
+ * │ │ │
+ * └───────┴───────┘
+ */
+ vec2 uv_sample = ((frag_coord + corners[i]) * 0.5) / vec2(textureSize(stable_color_tx, 0));
+ /* Reminder: The content of this buffer is YCoCg + CoC. */
+ vec3 ycocg_sample = textureLod(stable_color_tx, uv_sample, 0.0).rgb;
+ neighbor_min = (i == 0) ? ycocg_sample : min(neighbor_min, ycocg_sample);
+ neighbor_max = (i == 0) ? ycocg_sample : max(neighbor_max, ycocg_sample);
+ }
+ /* Pad the bounds in the near in focus region to get back a bit of detail. */
+ float padding = 0.125 * saturate(1.0 - sqr(center_coc) / sqr(8.0));
+ neighbor_max += abs(neighbor_min) * padding;
+ neighbor_min -= abs(neighbor_min) * padding;
+ /* Progressively apply the clamp to avoid harsh transition. Also mask by weight. */
+ float fac = saturate(sqr(center_coc) * 4.0) * weight;
+ /* Clamp in YCoCg space to avoid too much color drift. */
+ color = colorspace_YCoCg_from_scene_linear(color);
+ color = mix(color, clamp(color, neighbor_min, neighbor_max), fac);
+ color = colorspace_scene_linear_from_YCoCg(color);
+ return color;
+}
+
void main()
{
vec2 frag_coord = vec2(gl_GlobalInvocationID.xy) + 0.5;
@@ -94,11 +133,20 @@ void main()
}
if (!no_slight_focus_pass && prediction.do_slight_focus) {
- dof_slight_focus_gather(
- depth_tx, color_tx, bokeh_lut_tx, slight_focus_max_coc, layer_color, layer_weight);
+ float center_coc;
+ dof_slight_focus_gather(depth_tx,
+ color_tx,
+ bokeh_lut_tx,
+ slight_focus_max_coc,
+ layer_color,
+ layer_weight,
+ center_coc);
+
/* Composite slight defocus. */
out_color = out_color * (1.0 - layer_weight) + layer_color;
weight = weight * (1.0 - layer_weight) + layer_weight;
+
+ out_color.rgb = dof_neighborhood_clamp(frag_coord, out_color.rgb, center_coc, layer_weight);
}
if (!no_focus_pass && prediction.do_focus) {
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl
index 254cacc45b7..b22af0e88f0 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl
@@ -110,8 +110,9 @@ float dof_bilateral_weight(float reference_coc, float sample_coc)
{
/* NOTE: The difference between the cocs should be inside a abs() function,
* but we follow UE4 implementation to improve how dithered transparency looks (see slide 19).
+ * Effectively bleed background into foreground.
* Compared to dof_bilateral_coc_weights() this saturates as 2x the reference CoC. */
- return saturate(1.0 - (reference_coc - sample_coc) / max(1.0, abs(reference_coc)));
+ return saturate(1.0 - (sample_coc - reference_coc) / max(1.0, abs(reference_coc)));
}
DofSample dof_spatial_filtering()
@@ -218,7 +219,7 @@ DofSample dof_sample_history(vec2 input_texel)
vec2 uv = vec2(input_texel + 0.5) / textureSize(in_history_tx, 0);
vec4 color = textureLod(in_history_tx, uv, 0.0);
-#elif 0 /* Catmull Rom interpolation. 5 Bilinear Taps. */
+#else /* Catmull Rom interpolation. 5 Bilinear Taps. */
vec2 center_texel;
vec2 inter_texel = modf(input_texel, center_texel);
vec2 weights[4];
@@ -254,31 +255,22 @@ DofSample dof_sample_history(vec2 input_texel)
return DofSample(color.xyzz, color.w);
}
-/* 1D equivalent of line_aabb_clipping_dist(). */
-float dof_aabb_clipping_dist_coc(float origin, float direction, float aabb_min, float aabb_max)
-{
- if (abs(direction) < 1e-5) {
- return 0.0;
- }
- float nearest_plane = (direction > 0.0) ? aabb_min : aabb_max;
- return (nearest_plane - origin) / direction;
-}
-
/* Modulate the history color to avoid ghosting artifact. */
DofSample dof_amend_history(DofNeighborhoodMinMax bbox, DofSample history, DofSample src)
{
+#if 0
/* Clip instead of clamping to avoid color accumulating in the AABB corners. */
- DofSample clip_dir;
- clip_dir.color = src.color - history.color;
- clip_dir.coc = src.coc - history.coc;
+ vec3 clip_dir = src.color.rgb - history.color.rgb;
float t = line_aabb_clipping_dist(
- history.color.rgb, clip_dir.color.rgb, bbox.min.color.rgb, bbox.max.color.rgb);
- history.color.rgb += clip_dir.color.rgb * saturate(t);
-
- /* Clip CoC on its own to avoid interference with other chanels. */
- float t_a = dof_aabb_clipping_dist_coc(history.coc, clip_dir.coc, bbox.min.coc, bbox.max.coc);
- history.coc += clip_dir.coc * saturate(t_a);
+ history.color.rgb, clip_dir, bbox.min.color.rgb, bbox.max.color.rgb);
+ history.color.rgb += clip_dir * saturate(t);
+#else
+ /* More responsive. */
+ history.color = clamp(history.color, bbox.min.color, bbox.max.color);
+#endif
+ /* Clamp CoC to reduce convergence time. Otherwise the result is laggy. */
+ history.coc = clamp(history.coc, bbox.min.coc, bbox.max.coc);
return history;
}
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh
index 1dd9178ae84..54f8ca3e61b 100644
--- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh
@@ -24,7 +24,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_setup)
.sampler(0, ImageType::FLOAT_2D, "color_tx")
.sampler(1, ImageType::DEPTH_2D, "depth_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_color_img")
- .image(1, GPU_RG16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_coc_img")
+ .image(1, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_coc_img")
.compute_source("eevee_depth_of_field_setup_comp.glsl");
GPU_SHADER_CREATE_INFO(eevee_depth_of_field_stabilize)
@@ -243,6 +243,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_resolve)
.sampler(7, ImageType::FLOAT_2D, "weight_bg_tx")
.sampler(8, ImageType::FLOAT_2D, "weight_fg_tx")
.sampler(9, ImageType::FLOAT_2D, "weight_hole_fill_tx")
+ .sampler(10, ImageType::FLOAT_2D, "stable_color_tx")
.image(2, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_color_img")
.compute_source("eevee_depth_of_field_resolve_comp.glsl");