[Bf-blender-cvs] [5be7f872c4c] tmp-workbench-rewrite2: dof

Miguel Pozo noreply at git.blender.org
Fri Oct 28 15:11:17 CEST 2022


Commit: 5be7f872c4c3e65b75be9533f1e48269a9595933
Author: Miguel Pozo
Date:   Mon Oct 24 18:29:03 2022 +0200
Branches: tmp-workbench-rewrite2
https://developer.blender.org/rB5be7f872c4c3e65b75be9533f1e48269a9595933

dof

===================================================================

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/workbench/workbench_effect_cavity.cc
A	source/blender/draw/engines/workbench/workbench_effect_dof.cc
M	source/blender/draw/engines/workbench/workbench_engine.cc
M	source/blender/draw/engines/workbench/workbench_private.hh

===================================================================

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 7a649bb67a1..243186e0c22 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -159,6 +159,7 @@ set(SRC
   engines/workbench/workbench_effect_cavity.c
   engines/workbench/workbench_effect_cavity.cc
   engines/workbench/workbench_effect_dof.c
+  engines/workbench/workbench_effect_dof.cc
   engines/workbench/workbench_effect_outline.c
   engines/workbench/workbench_engine.c
   engines/workbench/workbench_engine.cc
diff --git a/source/blender/draw/engines/workbench/workbench_effect_cavity.cc b/source/blender/draw/engines/workbench/workbench_effect_cavity.cc
index 5e395cff494..46a2f55ae34 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_cavity.cc
+++ b/source/blender/draw/engines/workbench/workbench_effect_cavity.cc
@@ -50,7 +50,7 @@ void CavityEffect::init(const View3DShading &shading,
   world_buf.curvature_ridge = 0.5f / max_ff(square_f(shading.curvature_ridge_factor), 1e-4f);
   world_buf.curvature_valley = 0.7f / max_ff(square_f(shading.curvature_valley_factor), 1e-4f);
 
-  if (cavity_enabled) {
+  if (cavity_enabled || true /*TODO(Miguel Pozo): Remove this (needed for DoF)*/) {
     setup_resources(sample_count);
   }
 }
diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.cc b/source/blender/draw/engines/workbench/workbench_effect_dof.cc
new file mode 100644
index 00000000000..b6b9908d80d
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_effect_dof.cc
@@ -0,0 +1,387 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2016 Blender Foundation. */
+
+/** \file
+ * \ingroup draw_engine
+ *
+ * Depth of Field Effect:
+ *
+ * We use a gather approach by sampling a lowres version of the color buffer.
+ * The process can be summarized like this:
+ * - down-sample the color buffer using a COC (Circle of Confusion) aware down-sample algorithm.
+ * - do a gather pass using the COC computed in the previous pass.
+ * - do a median filter to reduce noise amount.
+ * - composite on top of main color buffer.
+ *
+ * This is done after all passes and affects every surfaces.
+ */
+
+#include "workbench_private.hh"
+
+#include "BKE_camera.h"
+#include "DEG_depsgraph_query.h"
+
+#include "DNA_camera_types.h"
+
+namespace blender::workbench {
+/**
+ * Transform [-1..1] square to unit circle.
+ */
+static void square_to_circle(float x, float y, float &r, float &T)
+{
+  if (x > -y) {
+    if (x > y) {
+      r = x;
+      T = M_PI_4 * (y / x);
+    }
+    else {
+      r = y;
+      T = M_PI_4 * (2 - (x / y));
+    }
+  }
+  else {
+    if (x < y) {
+      r = -x;
+      T = M_PI_4 * (4 + (y / x));
+    }
+    else {
+      r = -y;
+      if (y != 0) {
+        T = M_PI_4 * (6 - (x / y));
+      }
+      else {
+        T = 0.0f;
+      }
+    }
+  }
+}
+
+void DofPass::setup_samples()
+{
+  float4 *sample = samples_buf.begin();
+  for (int i = 0; i <= KERNEL_RADIUS; i++) {
+    for (int j = -KERNEL_RADIUS; j <= KERNEL_RADIUS; j++) {
+      for (int k = -KERNEL_RADIUS; k <= KERNEL_RADIUS; k++) {
+        if (abs(j) > i || abs(k) > i) {
+          continue;
+        }
+        if (abs(j) < i && abs(k) < i) {
+          continue;
+        }
+
+        float2 coord = float2(j, k) / float2(KERNEL_RADIUS);
+        float r = 0;
+        float T = 0;
+        square_to_circle(coord.x, coord.y, r, T);
+        sample->z = r;
+
+        /* Bokeh shape parameterization. */
+        if (blades > 1.0f) {
+          float denom = T - (2.0 * M_PI / blades) * floorf((blades * T + M_PI) / (2.0 * M_PI));
+          r *= cosf(M_PI / blades) / cosf(denom);
+        }
+
+        T += rotation;
+
+        sample->x = r * cosf(T) * ratio;
+        sample->y = r * sinf(T);
+        sample->w = 0;
+        sample++;
+      }
+    }
+  }
+  samples_buf.push_update();
+}
+
+void DofPass::init(const View3DShading &shading, int2 resolution)
+{
+  const DRWContextState *draw_ctx = DRW_context_state_get();
+  RegionView3D *rv3d = draw_ctx->rv3d;
+  View3D *v3d = draw_ctx->v3d;
+
+  Object *camera = nullptr;
+  if (v3d && rv3d) {
+    camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : nullptr;
+  }
+  else {
+    /*TODO(Miguel Pozo)*/
+    // camera = wpd->cam_original_ob;
+  }
+
+  Camera *cam = camera ? static_cast<Camera *>(camera->data) : nullptr;
+
+  enabled = cam && cam->dof.flag & CAM_DOF_ENABLED && shading.flag & V3D_SHADING_DEPTH_OF_FIELD;
+  if (!enabled) {
+    source_tx.free();
+    coc_halfres_tx.free();
+    return;
+  }
+
+  int2 half_res = {max_ii(resolution.x / 2, 1), max_ii(resolution.y / 2, 1)};
+
+  source_tx.ensure_2d(GPU_RGBA16F, half_res, nullptr, 3);
+  source_tx.ensure_mip_views();
+  source_tx.filter_mode(true);
+  coc_halfres_tx.ensure_2d(GPU_RG8, half_res, nullptr, 3);
+  coc_halfres_tx.ensure_mip_views();
+  coc_halfres_tx.filter_mode(true);
+
+  /* Parameters */
+  float fstop = cam->dof.aperture_fstop;
+  float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
+  float focus_dist = BKE_camera_object_dof_distance(camera);
+  float focal_len = cam->lens;
+
+  /* TODO(fclem): de-duplicate with EEVEE. */
+  const float scale_camera = 0.001f;
+  /* We want radius here for the aperture number. */
+  float aperture = 0.5f * scale_camera * focal_len / fstop;
+  float focal_len_scaled = scale_camera * focal_len;
+  float sensor_scaled = scale_camera * sensor;
+
+  if (rv3d != nullptr) {
+    sensor_scaled *= rv3d->viewcamtexcofac[0];
+  }
+
+  aperture_size = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
+  distance = -focus_dist;
+  invsensor_size = resolution.x / sensor_scaled;
+
+  near = -cam->clip_start;
+  far = -cam->clip_end;
+
+  float _blades = cam->dof.aperture_blades;
+  float _rotation = cam->dof.aperture_rotation;
+  float _ratio = 1.0f / cam->dof.aperture_ratio;
+
+  if (blades != _blades || rotation != _rotation || ratio != _ratio) {
+    blades = _blades;
+    rotation = _rotation;
+    ratio = _ratio;
+    setup_samples();
+  }
+
+#if 0 /* TODO(fclem): finish COC min_max optimization. */
+  const float *full_size = DRW_viewport_size_get();
+  const int size[2] = {max_ii(1, (int)full_size[0] / 2), max_ii(1, (int)full_size[1] / 2)};
+  
+  /* NOTE: We Ceil here in order to not miss any edge texel if using a NPO2 texture. */
+  int shrink_h_size[2] = {ceilf(size[0] / 8.0f), size[1]};
+  int shrink_w_size[2] = {shrink_h_size[0], ceilf(size[1] / 8.0f)};
+
+  wpd->coc_temp_tx = DRW_texture_pool_query_2d(
+      shrink_h_size[0], shrink_h_size[1], GPU_RG8, &draw_engine_workbench);
+  wpd->coc_tiles_tx[0] = DRW_texture_pool_query_2d(
+      shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench);
+  wpd->coc_tiles_tx[1] = DRW_texture_pool_query_2d(
+      shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench);
+
+  GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_h_fb,
+                                {
+                                    GPU_ATTACHMENT_NONE,
+                                    GPU_ATTACHMENT_TEXTURE(wpd->coc_temp_tx),
+                                });
+  GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_v_fb,
+                                {
+                                    GPU_ATTACHMENT_NONE,
+                                    GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[0]),
+                                });
+  GPU_framebuffer_ensure_config(&fbl->dof_coc_dilate_fb,
+                                {
+                                    GPU_ATTACHMENT_NONE,
+                                    GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[1]),
+                                });
+#endif
+}
+
+void DofPass::sync(SceneResources &resources)
+{
+  if (!enabled) {
+    return;
+  }
+
+  if (prepare_sh == nullptr) {
+    prepare_sh = GPU_shader_create_from_info_name("workbench_effect_dof_prepare");
+    downsample_sh = GPU_shader_create_from_info_name("workbench_effect_dof_downsample");
+    blur1_sh = GPU_shader_create_from_info_name("workbench_effect_dof_blur1");
+    blur2_sh = GPU_shader_create_from_info_name("workbench_effect_dof_blur2");
+    resolve_sh = GPU_shader_create_from_info_name("workbench_effect_dof_resolve");
+#if 0 /* TODO(fclem): finish COC min_max optimization */
+      flatten_v_sh = GPU_shader_create_from_info_name("workbench_effect_dof_flatten_v");
+      flatten_h_sh = GPU_shader_create_from_info_name("workbench_effect_dof_flatten_h");
+      dilate_v_sh = GPU_shader_create_from_info_name("workbench_effect_dof_dilate_v");
+      dilate_h_sh = GPU_shader_create_from_info_name("workbench_effect_dof_dilate_h");
+#endif
+  }
+
+  eGPUSamplerState sampler_state = GPU_SAMPLER_FILTER | GPU_SAMPLER_MIPMAP;
+
+  down_ps.init();
+  down_ps.state_set(DRW_STATE_WRITE_COLOR);
+  down_ps.shader_set(prepare_sh);
+  down_ps.bind_texture("sceneColorTex", &resources.color_tx);
+  down_ps.bind_texture("sceneDepthTex", &resources.depth_tx);
+  down_ps.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
+  down_ps.push_constant("dofParams", float3(aperture_size, distance, invsensor_size));
+  down_ps.push_constant("nearFar", float2(near, far));
+  down_ps.draw_procedural(GPU_PRIM_TRIS, 1, 3);
+
+  down2_ps.init();
+  down2_ps.state_set(DRW_STATE_WRITE_COLOR);
+  down2_ps.shader_set(downsample_sh);
+  down2_ps.bind_texture("sceneColorTex", &source_tx, sampler_state);
+  down2_ps.bind_texture("inputCocTex", &coc_halfres_tx, sampler_state);
+  down2_ps.draw_procedural(GPU_PRIM_TRIS, 1, 3);
+
+#if 0 /* TODO(fclem): finish COC min_max optimization */
+    {
+      psl->dof_flatten_h_ps = DRW_pass_create("DoF Flatten Coc H", DRW_STATE_WRITE_COLOR);
+
+      DRWShadingGroup *grp = DRW_shgroup_create(flatten_h_sh, psl->dof_flatten_h_ps);
+      DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx);
+      DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
+    }
+    {
+      psl->dof_flatten_v_ps = DRW_pass_create("DoF Flatten Coc V", DRW_STATE_WRITE_COLOR);
+
+      DRWShadingGroup *grp = DRW_shgroup_create(flatten_v_sh, psl->dof_flatten_v_ps);
+      DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_temp_tx);
+  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list