[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