47 const ::Camera *camera = (camera_object_eval && camera_object_eval->
type ==
OB_CAMERA) ?
48 reinterpret_cast<const ::
Camera *
>(camera_object_eval->
data) :
50 if (camera ==
nullptr) {
56 int sce_flag = sce_eevee.
flag;
69 const ::Camera *camera_data = (camera_object_eval && camera_object_eval->
type ==
OB_CAMERA) ?
70 reinterpret_cast<const ::
Camera *
>(camera_object_eval->
data) :
76 "Debug Mode: Depth Of Field Buffers\n"
77 " - Purple: Gap Fill\n"
78 " - Blue: Background\n"
79 " - Red: Slight Out Of Focus\n"
80 " - Yellow: In Focus\n"
81 " - Green: Foreground\n");
84 if (camera_data ==
nullptr || (camera_data->dof.flag &
CAM_DOF_ENABLED) == 0) {
85 jitter_radius_ = 0.0f;
90 float2 anisotropic_scale = {
clamp_f(1.0f / camera_data->dof.aperture_ratio, 1e-5f, 1.0f),
91 clamp_f(camera_data->dof.aperture_ratio, 1e-5f, 1.0f)};
97 float fstop =
max_ff(camera_data->dof.aperture_fstop, 1e-5f);
99 float aperture = 1.0f / (2.0f * fstop);
100 if (camera.is_perspective()) {
101 aperture *= camera_data->lens * 1e-3f;
104 if (camera.is_orthographic()) {
109 if (camera.is_panoramic()) {
114 if (camera_data->dof.aperture_ratio < 1.0) {
117 aperture /=
max_ff(camera_data->dof.aperture_ratio, 1e-5f);
120 float jitter_radius, fx_radius;
131 fx_radius = (minimal_overblur + user_overblur_) * aperture;
133 jitter_radius =
max_ff(0.0f, aperture - fx_radius);
136 jitter_radius = 0.0f;
137 fx_radius = aperture;
141 if (fx_max_coc_ <= 0.5f) {
145 jitter_radius_ = jitter_radius;
146 fx_radius_ = fx_radius;
148 if (fx_radius_ == 0.0f) {
175 bokeh_lut_pass_sync();
177 stabilize_pass_sync();
178 downsample_pass_sync();
180 tiles_flatten_pass_sync();
181 tiles_dilate_pass_sync();
185 hole_fill_pass_sync();
191 if (jitter_radius_ == 0.0f) {
202 radius *= jitter_radius_;
214 const bool is_ortho = (winmat[2][3] != -1.0f);
216 sample *= focus_distance_;
230void DepthOfField::bokeh_lut_pass_sync()
235 use_bokeh_lut_ =
false;
238 use_bokeh_lut_ =
true;
241 bokeh_lut_ps_.
init();
243 bokeh_lut_ps_.
bind_ubo(
"dof_buf", data_);
244 bokeh_lut_ps_.
bind_image(
"out_gather_lut_img", &bokeh_gather_lut_tx_);
245 bokeh_lut_ps_.
bind_image(
"out_scatter_lut_img", &bokeh_scatter_lut_tx_);
246 bokeh_lut_ps_.
bind_image(
"out_resolve_lut_img", &bokeh_resolve_lut_tx_);
250void DepthOfField::setup_pass_sync()
258 setup_ps_.
bind_ubo(
"dof_buf", data_);
259 setup_ps_.
bind_image(
"out_color_img", &setup_color_tx_);
260 setup_ps_.
bind_image(
"out_coc_img", &setup_coc_tx_);
261 setup_ps_.
dispatch(&dispatch_setup_size_);
265void DepthOfField::stabilize_pass_sync()
268 VelocityModule &velocity = inst_.
velocity;
270 stabilize_ps_.
init();
281 stabilize_ps_.
bind_ubo(
"dof_buf", data_);
282 stabilize_ps_.
push_constant(
"u_use_history", &stabilize_valid_history_, 1);
285 stabilize_ps_.
bind_image(
"out_history_img", &stabilize_output_tx_);
286 stabilize_ps_.
dispatch(&dispatch_stabilize_size_);
290void DepthOfField::downsample_pass_sync()
292 downsample_ps_.
init();
296 downsample_ps_.
bind_image(
"out_color_img", &downsample_tx_);
297 downsample_ps_.
dispatch(&dispatch_downsample_size_);
301void DepthOfField::reduce_pass_sync()
305 reduce_ps_.
bind_ubo(
"dof_buf", data_);
307 reduce_ps_.
bind_ssbo(
"scatter_fg_list_buf", scatter_fg_list_buf_);
308 reduce_ps_.
bind_ssbo(
"scatter_bg_list_buf", scatter_bg_list_buf_);
309 reduce_ps_.
bind_ssbo(
"scatter_fg_indirect_buf", scatter_fg_indirect_buf_);
310 reduce_ps_.
bind_ssbo(
"scatter_bg_indirect_buf", scatter_bg_indirect_buf_);
319 reduce_ps_.
dispatch(&dispatch_reduce_size_);
324void DepthOfField::tiles_flatten_pass_sync()
326 tiles_flatten_ps_.
init();
332 tiles_flatten_ps_.
bind_image(
"out_tiles_fg_img", &tiles_fg_tx_.current());
333 tiles_flatten_ps_.
bind_image(
"out_tiles_bg_img", &tiles_bg_tx_.current());
334 tiles_flatten_ps_.
dispatch(&dispatch_tiles_flatten_size_);
338void DepthOfField::tiles_dilate_pass_sync()
340 for (
int pass = 0; pass < 2; pass++) {
341 PassSimple &drw_pass = (pass == 0) ? tiles_dilate_minmax_ps_ : tiles_dilate_minabs_ps_;
345 drw_pass.bind_image(
"in_tiles_fg_img", &tiles_fg_tx_.previous());
346 drw_pass.bind_image(
"in_tiles_bg_img", &tiles_bg_tx_.previous());
347 drw_pass.bind_image(
"out_tiles_fg_img", &tiles_fg_tx_.current());
348 drw_pass.bind_image(
"out_tiles_bg_img", &tiles_bg_tx_.current());
349 drw_pass.push_constant(
"ring_count", &tiles_dilate_ring_count_, 1);
350 drw_pass.push_constant(
"ring_width_multiplier", &tiles_dilate_ring_width_mul_, 1);
351 drw_pass.dispatch(&dispatch_tiles_dilate_size_);
356void DepthOfField::gather_pass_sync()
362 for (
int pass = 0; pass < 2; pass++) {
363 PassSimple &drw_pass = (pass == 0) ? gather_fg_ps_ : gather_bg_ps_;
364 SwapChain<TextureFromPool, 2> &color_chain = (pass == 0) ? color_fg_tx_ : color_bg_tx_;
365 SwapChain<TextureFromPool, 2> &weight_chain = (pass == 0) ? weight_fg_tx_ : weight_bg_tx_;
371 drw_pass.bind_resources(inst_.
sampling);
373 drw_pass.bind_ubo(
"dof_buf", data_);
374 drw_pass.bind_texture(
"color_bilinear_tx", reduced_color_tx_, gather_bilinear);
375 drw_pass.bind_texture(
"color_tx", reduced_color_tx_, gather_nearest);
376 drw_pass.bind_texture(
"coc_tx", reduced_coc_tx_, gather_nearest);
377 drw_pass.bind_image(
"in_tiles_fg_img", &tiles_fg_tx_.current());
378 drw_pass.bind_image(
"in_tiles_bg_img", &tiles_bg_tx_.current());
379 drw_pass.bind_image(
"out_color_img", &color_chain.current());
380 drw_pass.bind_image(
"out_weight_img", &weight_chain.current());
381 drw_pass.bind_image(
"out_occlusion_img", &occlusion_tx_);
382 drw_pass.bind_texture(
"bokeh_lut_tx", &bokeh_gather_lut_tx_);
383 drw_pass.dispatch(&dispatch_gather_size_);
388void DepthOfField::filter_pass_sync()
390 for (
int pass = 0; pass < 2; pass++) {
391 PassSimple &drw_pass = (pass == 0) ? filter_fg_ps_ : filter_bg_ps_;
392 SwapChain<TextureFromPool, 2> &color_chain = (pass == 0) ? color_fg_tx_ : color_bg_tx_;
393 SwapChain<TextureFromPool, 2> &weight_chain = (pass == 0) ? weight_fg_tx_ : weight_bg_tx_;
396 drw_pass.bind_texture(
"color_tx", &color_chain.previous());
397 drw_pass.bind_texture(
"weight_tx", &weight_chain.previous());
398 drw_pass.bind_image(
"out_color_img", &color_chain.current());
399 drw_pass.bind_image(
"out_weight_img", &weight_chain.current());
400 drw_pass.dispatch(&dispatch_filter_size_);
405void DepthOfField::scatter_pass_sync()
407 for (
int pass = 0; pass < 2; pass++) {
408 PassSimple &drw_pass = (pass == 0) ? scatter_fg_ps_ : scatter_bg_ps_;
412 drw_pass.bind_ubo(
"dof_buf", data_);
413 drw_pass.push_constant(
"use_bokeh_lut", use_bokeh_lut_);
414 drw_pass.bind_texture(
"bokeh_lut_tx", &bokeh_scatter_lut_tx_);
415 drw_pass.bind_texture(
"occlusion_tx", &occlusion_tx_);
417 drw_pass.bind_ssbo(
"scatter_list_buf", scatter_fg_list_buf_);
423 drw_pass.bind_ssbo(
"scatter_list_buf", scatter_bg_list_buf_);
429void DepthOfField::hole_fill_pass_sync()
435 hole_fill_ps_.
init();
438 hole_fill_ps_.
bind_ubo(
"dof_buf", data_);
439 hole_fill_ps_.
bind_texture(
"color_bilinear_tx", reduced_color_tx_, gather_bilinear);
440 hole_fill_ps_.
bind_texture(
"color_tx", reduced_color_tx_, gather_nearest);
441 hole_fill_ps_.
bind_texture(
"coc_tx", reduced_coc_tx_, gather_nearest);
442 hole_fill_ps_.
bind_image(
"in_tiles_fg_img", &tiles_fg_tx_.current());
443 hole_fill_ps_.
bind_image(
"in_tiles_bg_img", &tiles_bg_tx_.current());
444 hole_fill_ps_.
bind_image(
"out_color_img", &hole_fill_color_tx_);
445 hole_fill_ps_.
bind_image(
"out_weight_img", &hole_fill_weight_tx_);
446 hole_fill_ps_.
dispatch(&dispatch_gather_size_);
450void DepthOfField::resolve_pass_sync()
459 resolve_ps_.
bind_ubo(
"dof_buf", data_);
465 resolve_ps_.
bind_image(
"in_tiles_fg_img", &tiles_fg_tx_.current());
466 resolve_ps_.
bind_image(
"in_tiles_bg_img", &tiles_bg_tx_.current());
467 resolve_ps_.
bind_texture(
"weight_bg_tx", &weight_bg_tx_.current());
468 resolve_ps_.
bind_texture(
"weight_fg_tx", &weight_fg_tx_.current());
469 resolve_ps_.
bind_texture(
"color_hole_fill_tx", &hole_fill_color_tx_);
470 resolve_ps_.
bind_texture(
"weight_hole_fill_tx", &hole_fill_weight_tx_);
471 resolve_ps_.
bind_texture(
"bokeh_lut_tx", &bokeh_resolve_lut_tx_);
472 resolve_ps_.
bind_image(
"out_color_img", &output_color_tx_);
475 resolve_ps_.
dispatch(&dispatch_resolve_size_);
487void DepthOfField::update_sample_table()
491 subpixel_offset *= 0.5;
494 const std::array<int2, 4> plus_offsets = {
int2(-1, 0),
int2(0, -1),
int2(1, 0),
int2(0, 1)};
496 const float radius = 1.5f;
498 for (
int2 offset : plus_offsets) {
507 GPUTexture **output_tx,
510 if (fx_radius_ == 0.0f) {
515 output_color_tx_ = *output_tx;
522 float3 jitter =
float3(fx_radius_, 0.0f, -focus_distance_);
528 data_.
coc_mul = (center[0] - jitter[0]) * 0.5f * extent_[0];
532 data_.
coc_bias = -(center[0] - jitter[0]) * 0.5f * extent_[0];
548 update_sample_table();
563 dispatch_tiles_dilate_size_ =
int3(
590 if (use_bokeh_lut_) {
591 drw.
submit(bokeh_lut_ps_, view);
598 drw.
submit(setup_ps_, view);
605 if (stabilize_valid_history_ ==
false) {
612 drw.
submit(stabilize_ps_, view);
619 stabilize_output_tx_.
release();
631 drw.
submit(tiles_flatten_ps_, view);
641 for (
int pass = 0; pass < 2; pass++) {
643 int dilation_radius = 0;
644 while (dilation_radius < dilation_end_radius) {
645 int remainder = dilation_end_radius - dilation_radius;
647 int max_multiplier = dilation_radius + 1;
650 int multiplier =
min_ii(max_multiplier,
floorf(remainder /
float(ring_count)));
652 dilation_radius += ring_count * multiplier;
654 tiles_dilate_ring_count_ = ring_count;
655 tiles_dilate_ring_width_mul_ = multiplier;
660 drw.
submit((pass == 0) ? tiles_dilate_minmax_ps_ : tiles_dilate_minabs_ps_,
view);
664 tiles_fg_tx_.previous().release();
665 tiles_bg_tx_.previous().release();
672 drw.
submit(downsample_ps_, view);
677 drw.
submit(reduce_ps_, view);
685 for (
int is_background = 0; is_background < 2; is_background++) {
690 Framebuffer &scatter_fb = is_background ? scatter_bg_fb_ : scatter_fg_fb_;
691 PassSimple &gather_ps = is_background ? gather_bg_ps_ : gather_fg_ps_;
692 PassSimple &filter_ps = is_background ? filter_bg_ps_ : filter_fg_ps_;
693 PassSimple &scatter_ps = is_background ? scatter_bg_ps_ : scatter_fg_ps_;
699 drw.
submit(gather_ps, view);
709 drw.
submit(filter_ps, view);
720 drw.
submit(scatter_ps, view);
730 bokeh_gather_lut_tx_.
release();
731 bokeh_scatter_lut_tx_.
release();
736 drw.
submit(hole_fill_ps_, view);
747 drw.
submit(resolve_ps_, view);
749 color_bg_tx_.current().release();
750 color_fg_tx_.current().release();
751 weight_bg_tx_.current().release();
752 weight_fg_tx_.current().release();
753 tiles_fg_tx_.current().release();
754 tiles_bg_tx_.current().release();
756 hole_fill_weight_tx_.
release();
757 bokeh_resolve_lut_tx_.
release();
Camera data-block and utility functions.
float BKE_camera_object_dof_distance(const struct Object *ob)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
void mul_project_m4_v3(const float mat[4][4], float vec[3])
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
#define GPU_ATTACHMENT_TEXTURE(_texture)
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void GPU_memory_barrier(eGPUBarrier barrier)
@ GPU_BARRIER_SHADER_STORAGE
@ GPU_BARRIER_TEXTURE_FETCH
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
@ GPU_BARRIER_FRAMEBUFFER
int GPU_texture_height(const GPUTexture *texture)
int GPU_texture_width(const GPUTexture *texture)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_SAMPLER_FILTERING_MIPMAP
@ GPU_SAMPLER_FILTERING_LINEAR
struct GPUShader GPUShader
void ensure(GPUAttachment depth=GPU_ATTACHMENT_NONE, GPUAttachment color1=GPU_ATTACHMENT_NONE, GPUAttachment color2=GPU_ATTACHMENT_NONE, GPUAttachment color3=GPU_ATTACHMENT_NONE, GPUAttachment color4=GPU_ATTACHMENT_NONE, GPUAttachment color5=GPU_ATTACHMENT_NONE, GPUAttachment color6=GPU_ATTACHMENT_NONE, GPUAttachment color7=GPU_ATTACHMENT_NONE, GPUAttachment color8=GPU_ATTACHMENT_NONE)
void submit(PassSimple &pass, View &view)
void resize(int64_t new_size)
static void swap(TextureFromPool &a, Texture &b)
void acquire(int2 extent, eGPUTextureFormat format, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL)
bool ensure_mip_views(bool cube_as_array=false)
void clear(float4 values)
bool ensure_2d(eGPUTextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
GPUTexture * mip_view(int miplvl)
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void bind_resources(U &resources)
void bind_image(const char *name, GPUTexture *image)
void specialize_constant(GPUShader *shader, const char *name, const float &data)
void dispatch(int group_len)
void barrier(eGPUBarrier type)
void bind_ubo(const char *name, GPUUniformBuf *buffer)
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
bool is_orthographic() const
const CameraData & data_get() const
void render(View &view, GPUTexture **input_tx, GPUTexture **output_tx, DepthOfFieldBuffer &dof_buffer)
void jitter_apply(float4x4 &winmat, float4x4 &viewmat)
float2 pixel_jitter_get() const
int2 render_extent_get() const
Object * camera_eval_object
RenderBuffers render_buffers
void info_append(const char *msg, Args &&...args)
uint64_t dof_ring_count_get() const
void dof_disk_sample_get(float *r_radius, float *r_theta) const
uint64_t dof_sample_count_get() const
GPUShader * static_shader_get(eShaderType shader_type)
void DRW_stats_group_start(const char *name)
void DRW_stats_group_end()
@ DRW_STATE_BLEND_ADD_FULL
#define DOF_DEFAULT_GROUP_SIZE
#define DOF_REDUCE_GROUP_SIZE
#define DOF_TILES_DILATE_GROUP_SIZE
#define DOF_FILTER_GROUP_SIZE
#define DOF_STABILIZE_GROUP_SIZE
#define DOF_BOKEH_LUT_SIZE
#define DOF_GATHER_GROUP_SIZE
#define DOF_RESOLVE_GROUP_SIZE
#define DOF_MAX_SLIGHT_FOCUS_RADIUS
DOF_TILES_FLATTEN_GROUP_SIZE coc_tx GPU_R11F_G11F_B10F
draw_view in_light_buf[] float
#define DOF_DILATE_RING_COUNT
#define DOF_GATHER_RING_COUNT
detail::Pass< command::DrawCommandBuf > PassSimple
constexpr GPUSamplerState no_filter
@ DOF_GATHER_BACKGROUND_LUT
@ DOF_TILES_DILATE_MINABS
@ DOF_TILES_DILATE_MINMAX
@ DOF_GATHER_FOREGROUND_LUT
static float film_filter_weight(float filter_radius, float sample_distance_sqr)
constexpr GPUSamplerState with_filter
static float circle_to_polygon_angle(float sides_count, float theta)
static float coc_radius_from_camera_depth(DepthOfFieldData dof, float depth)
static float circle_to_polygon_radius(float sides_count, float theta)
T length_squared(const VecBase< T, Size > &a)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< T, Size > ceil_to_multiple(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
const c_style_mat & ptr() const
Texture stabilize_history_tx_
float scatter_coc_threshold
float2 bokeh_anisotropic_scale_inv
float2 bokeh_anisotropic_scale
float4 filter_samples_weight
float scatter_neighbor_max_color
float scatter_color_threshold
float filter_center_weight