diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-08-05 14:51:29 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-08-05 15:45:39 +0300 |
commit | 2a4cc0c81c1748d2a18c49ce2f13e49428a55d62 (patch) | |
tree | e04672b6c45311a77102cfb0f45f69477a6f3c47 /source/blender/draw/engines | |
parent | 3690dad40a8e2a8850c0f8f2f5a789c4ebc7a75b (diff) |
EEVEE-Next: Depth Of Field: Use random sampling in slight focus gather
This replace the previous square rings approach by sampling a disk the
footprint of the search area. This avoids sampling in areas in corners
where there isn't any weight.
This results in much less samples needed to acheive a good enough result.
The max number of samples for an area of 11x11 px is hard coded to 16 and
still gives good results with the final clamp.
The number of samples is adaptative and is scaled by the search area (max
CoC).
The High Quality Slight Defocus is not required anymore. If there is a
quality parameter to add, it would be sample count option. But I consider
the temporal stability enough for viewport work and render can still
render many full scene samples. So I don't see a need for that yet.
Diffstat (limited to 'source/blender/draw/engines')
7 files changed, 53 insertions, 74 deletions
diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index 2067d1c708c..c1e901845f1 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -57,6 +57,7 @@ #define DOF_TILES_DILATE_GROUP_SIZE 8 #define DOF_BOKEH_LUT_SIZE 32 #define DOF_MAX_SLIGHT_FOCUS_RADIUS 5 +#define DOF_SLIGHT_FOCUS_SAMPLE_MAX 16 #define DOF_MIP_COUNT 4 #define DOF_REDUCE_GROUP_SIZE (1 << (DOF_MIP_COUNT - 1)) #define DOF_DEFAULT_GROUP_SIZE 32 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 713fcf77dc8..ffef9da5e29 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 @@ -55,8 +55,6 @@ void DepthOfField::init() /* Reminder: These are parameters not interpolated by motion blur. */ int update = 0; int sce_flag = sce_eevee.flag; - update += assign_if_different(do_hq_slight_focus_, - (sce_flag & SCE_EEVEE_DOF_HQ_SLIGHT_FOCUS) != 0); update += assign_if_different(do_jitter_, (sce_flag & SCE_EEVEE_DOF_JITTER) != 0); update += assign_if_different(user_overblur_, sce_eevee.bokeh_overblur / 100.0f); update += assign_if_different(fx_max_coc_, sce_eevee.bokeh_max_size); @@ -462,8 +460,7 @@ void DepthOfField::resolve_pass_sync() resolve_ps_ = DRW_pass_create("Dof.resolve_ps_", DRW_STATE_NO_DRAW); bool use_lut = bokeh_lut_ps_ != nullptr; - eShaderType sh_type = do_hq_slight_focus_ ? (use_lut ? DOF_RESOLVE_LUT_HQ : DOF_RESOLVE_HQ) : - (use_lut ? DOF_RESOLVE_LUT : DOF_RESOLVE); + eShaderType sh_type = use_lut ? DOF_RESOLVE_LUT : DOF_RESOLVE; GPUShader *sh = inst_.shaders.static_shader_get(sh_type); DRWShadingGroup *grp = DRW_shgroup_create(sh, resolve_ps_); inst_.sampling.bind_resources(grp); 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 84134e94483..6b235489d18 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 @@ -136,8 +136,6 @@ class DepthOfField { /** Scene settings that are immutable. */ float user_overblur_; float fx_max_coc_; - /** Use High Quality (expensive) in-focus gather pass. */ - bool do_hq_slight_focus_; /** Use jittered depth of field where we randomize camera location. */ bool do_jitter_; diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index 209aff9c168..357f2796a7e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -99,23 +99,19 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_ case DOF_GATHER_FOREGROUND_LUT: return "eevee_depth_of_field_gather_foreground_lut"; case DOF_GATHER_FOREGROUND: - return "eevee_depth_of_field_gather_foreground"; + return "eevee_depth_of_field_gather_foreground_no_lut"; case DOF_GATHER_BACKGROUND_LUT: return "eevee_depth_of_field_gather_background_lut"; case DOF_GATHER_BACKGROUND: - return "eevee_depth_of_field_gather_background"; + return "eevee_depth_of_field_gather_background_no_lut"; case DOF_GATHER_HOLE_FILL: return "eevee_depth_of_field_hole_fill"; case DOF_REDUCE: return "eevee_depth_of_field_reduce"; case DOF_RESOLVE: - return "eevee_depth_of_field_resolve_lq"; - case DOF_RESOLVE_HQ: - return "eevee_depth_of_field_resolve_hq"; + return "eevee_depth_of_field_resolve_no_lut"; case DOF_RESOLVE_LUT: - return "eevee_depth_of_field_resolve_lq_lut"; - case DOF_RESOLVE_LUT_HQ: - return "eevee_depth_of_field_resolve_hq_lut"; + return "eevee_depth_of_field_resolve_lut"; case DOF_SETUP: return "eevee_depth_of_field_setup"; case DOF_SCATTER: diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh index 13f2022e0d7..dd6b9c9d4ab 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh @@ -38,8 +38,6 @@ enum eShaderType { DOF_GATHER_FOREGROUND, DOF_GATHER_HOLE_FILL, DOF_REDUCE, - DOF_RESOLVE_HQ, - DOF_RESOLVE_LUT_HQ, DOF_RESOLVE_LUT, DOF_RESOLVE, DOF_SCATTER, 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 97c53ce3692..57f229feedb 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 @@ -578,68 +578,63 @@ void dof_slight_focus_gather(sampler2D depth_tx, out float out_center_coc) { vec2 frag_coord = vec2(gl_GlobalInvocationID.xy) + 0.5; - float noise_offset = sampling_rng_1D_get(SAMPLING_LENS_U); - float noise = no_gather_random ? 0.0 : interlieved_gradient_noise(frag_coord, 3, noise_offset); + vec2 noise_offset = sampling_rng_2D_get(SAMPLING_LENS_U); + vec2 noise = no_gather_random ? vec2(0.0) : + vec2(interlieved_gradient_noise(frag_coord, 3, noise_offset.x), + interlieved_gradient_noise(frag_coord, 5, noise_offset.y)); DofGatherData fg_accum = GATHER_DATA_INIT; DofGatherData bg_accum = GATHER_DATA_INIT; int i_radius = clamp(int(radius), 0, int(dof_layer_threshold)); - const int resolve_ring_density = DOF_SLIGHT_FOCUS_DENSITY; - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - bool first_ring = true; - - for (int ring = i_radius; ring > 0; ring--) { - DofGatherData fg_ring = GATHER_DATA_INIT; - DofGatherData bg_ring = GATHER_DATA_INIT; - - int ring_distance = ring; - int ring_sample_count = resolve_ring_density * ring_distance; - for (int sample_id = 0; sample_id < ring_sample_count; sample_id++) { - int s = sample_id * (4 / resolve_ring_density) + - int(noise * float((4 - resolve_ring_density) * ring_distance)); - ivec2 offset = dof_square_ring_sample_offset(ring_distance, s); - float ring_dist = length(vec2(offset)); + const float sample_count_max = float(DOF_SLIGHT_FOCUS_SAMPLE_MAX); + /* Scale by search area. */ + float sample_count = sample_count_max * saturate(sqr(radius) / sqr(dof_layer_threshold)); - DofGatherData pair_data[2]; - for (int i = 0; i < 2; i++) { - ivec2 sample_offset = ((i == 0) ? offset : -offset); - ivec2 sample_texel = texel + sample_offset; - /* OPTI: could precompute the factor. */ - vec2 sample_uv = (vec2(sample_texel) + 0.5) / vec2(textureSize(depth_tx, 0)); - float depth = textureLod(depth_tx, sample_uv, 0.0).r; - pair_data[i].coc = dof_coc_from_depth(dof_buf, sample_uv, depth); - pair_data[i].color = safe_color(textureLod(color_tx, sample_uv, 0.0)); - pair_data[i].dist = ring_dist; - if (DOF_BOKEH_TEXTURE) { - /* Contains subpixel distance to bokeh shape. */ - sample_offset += dof_max_slight_focus_radius; - pair_data[i].dist = texelFetch(bkh_lut_tx, sample_offset, 0).r; - } - pair_data[i].coc = clamp(pair_data[i].coc, -dof_buf.coc_abs_max, dof_buf.coc_abs_max); - } + bool first_ring = true; - float bordering_radius = ring_dist + 0.5; - const float isect_mul = 1.0; - dof_gather_accumulate_sample_pair( - pair_data, bordering_radius, isect_mul, first_ring, false, false, bg_ring, bg_accum); + for (float s = 0.0; s < sample_count; s++) { + vec2 rand2 = fract(hammersley_2d(s, sample_count) + noise); + vec2 offset = sample_disk(rand2); + float ring_dist = sqrt(rand2.y); + DofGatherData pair_data[2]; + for (int i = 0; i < 2; i++) { + vec2 sample_offset = ((i == 0) ? offset : -offset); + /* OPTI: could precompute the factor. */ + vec2 sample_uv = (frag_coord + sample_offset) / vec2(textureSize(depth_tx, 0)); + float depth = textureLod(depth_tx, sample_uv, 0.0).r; + pair_data[i].coc = dof_coc_from_depth(dof_buf, sample_uv, depth); + pair_data[i].color = safe_color(textureLod(color_tx, sample_uv, 0.0)); + pair_data[i].dist = ring_dist; if (DOF_BOKEH_TEXTURE) { - /* Swap distances in order to flip bokeh shape for foreground. */ - float tmp = pair_data[0].dist; - pair_data[0].dist = pair_data[1].dist; - pair_data[1].dist = tmp; + /* Contains subpixel distance to bokeh shape. */ + ivec2 lut_texel = ivec2(round(sample_offset)) + dof_max_slight_focus_radius; + pair_data[i].dist = texelFetch(bkh_lut_tx, lut_texel, 0).r; } - dof_gather_accumulate_sample_pair( - pair_data, bordering_radius, isect_mul, first_ring, false, true, fg_ring, fg_accum); + pair_data[i].coc = clamp(pair_data[i].coc, -dof_buf.coc_abs_max, dof_buf.coc_abs_max); } - dof_gather_accumulate_sample_ring( - bg_ring, ring_sample_count * 2, first_ring, false, false, bg_accum); - dof_gather_accumulate_sample_ring( - fg_ring, ring_sample_count * 2, first_ring, false, true, fg_accum); + float bordering_radius = ring_dist + 0.5; + const float isect_mul = 1.0; + DofGatherData bg_ring = GATHER_DATA_INIT; + dof_gather_accumulate_sample_pair( + pair_data, bordering_radius, isect_mul, first_ring, false, false, bg_ring, bg_accum); + /* Treat each sample as a ring. */ + dof_gather_accumulate_sample_ring(bg_ring, 2, first_ring, false, false, bg_accum); + + if (DOF_BOKEH_TEXTURE) { + /* Swap distances in order to flip bokeh shape for foreground. */ + float tmp = pair_data[0].dist; + pair_data[0].dist = pair_data[1].dist; + pair_data[1].dist = tmp; + } + DofGatherData fg_ring = GATHER_DATA_INIT; + dof_gather_accumulate_sample_pair( + pair_data, bordering_radius, isect_mul, first_ring, false, true, fg_ring, fg_accum); + /* Treat each sample as a ring. */ + dof_gather_accumulate_sample_ring(fg_ring, 2, first_ring, false, true, fg_accum); first_ring = false; } @@ -666,7 +661,7 @@ void dof_slight_focus_gather(sampler2D depth_tx, float bg_weight, fg_weight; vec2 unused_occlusion; - int total_sample_count = dof_gather_total_sample_count(i_radius + 1, resolve_ring_density); + int total_sample_count = int(sample_count) * 2 + 1; 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); 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 54f8ca3e61b..94ff694b147 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 @@ -130,24 +130,18 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_lut) GPU_SHADER_CREATE_INFO(eevee_depth_of_field_background).define("DOF_FOREGROUND_PASS", "false"); GPU_SHADER_CREATE_INFO(eevee_depth_of_field_foreground).define("DOF_FOREGROUND_PASS", "true"); -GPU_SHADER_CREATE_INFO(eevee_depth_of_field_hq).define("DOF_SLIGHT_FOCUS_DENSITY", "4"); -GPU_SHADER_CREATE_INFO(eevee_depth_of_field_lq).define("DOF_SLIGHT_FOCUS_DENSITY", "2"); #define EEVEE_DOF_FINAL_VARIATION(name, ...) \ GPU_SHADER_CREATE_INFO(name).additional_info(__VA_ARGS__).do_static_compilation(true); #define EEVEE_DOF_LUT_VARIATIONS(prefix, ...) \ EEVEE_DOF_FINAL_VARIATION(prefix##_lut, "eevee_depth_of_field_lut", __VA_ARGS__) \ - EEVEE_DOF_FINAL_VARIATION(prefix, "eevee_depth_of_field_no_lut", __VA_ARGS__) + EEVEE_DOF_FINAL_VARIATION(prefix##_no_lut, "eevee_depth_of_field_no_lut", __VA_ARGS__) #define EEVEE_DOF_GROUND_VARIATIONS(name, ...) \ EEVEE_DOF_LUT_VARIATIONS(name##_background, "eevee_depth_of_field_background", __VA_ARGS__) \ EEVEE_DOF_LUT_VARIATIONS(name##_foreground, "eevee_depth_of_field_foreground", __VA_ARGS__) -#define EEVEE_DOF_HQ_VARIATIONS(name, ...) \ - EEVEE_DOF_LUT_VARIATIONS(name##_hq, "eevee_depth_of_field_hq", __VA_ARGS__) \ - EEVEE_DOF_LUT_VARIATIONS(name##_lq, "eevee_depth_of_field_lq", __VA_ARGS__) - /** \} */ /* -------------------------------------------------------------------- */ @@ -247,6 +241,6 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_resolve) .image(2, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_color_img") .compute_source("eevee_depth_of_field_resolve_comp.glsl"); -EEVEE_DOF_HQ_VARIATIONS(eevee_depth_of_field_resolve, "eevee_depth_of_field_resolve") +EEVEE_DOF_LUT_VARIATIONS(eevee_depth_of_field_resolve, "eevee_depth_of_field_resolve") /** \} */ |