1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011 Blender Foundation. */
#include "COM_ConvertDepthToRadiusOperation.h"
#include "BKE_camera.h"
#include "DNA_camera_types.h"
namespace blender::compositor {
ConvertDepthToRadiusOperation::ConvertDepthToRadiusOperation()
{
this->add_input_socket(DataType::Value);
this->add_output_socket(DataType::Value);
input_operation_ = nullptr;
f_stop_ = 128.0f;
camera_object_ = nullptr;
max_radius_ = 32.0f;
blur_post_operation_ = nullptr;
}
float ConvertDepthToRadiusOperation::determine_focal_distance()
{
if (camera_object_ && camera_object_->type == OB_CAMERA) {
Camera *camera = (Camera *)camera_object_->data;
cam_lens_ = camera->lens;
return BKE_camera_object_dof_distance(camera_object_);
}
return 10.0f;
}
void ConvertDepthToRadiusOperation::init_execution()
{
float cam_sensor = DEFAULT_SENSOR_WIDTH;
Camera *camera = nullptr;
if (camera_object_ && camera_object_->type == OB_CAMERA) {
camera = (Camera *)camera_object_->data;
cam_sensor = BKE_camera_sensor_size(camera->sensor_fit, camera->sensor_x, camera->sensor_y);
}
input_operation_ = this->get_input_socket_reader(0);
float focal_distance = determine_focal_distance();
if (focal_distance == 0.0f) {
focal_distance = 1e10f; /* If the DOF is 0.0 then set it to be far away. */
}
inverse_focal_distance_ = 1.0f / focal_distance;
aspect_ = (this->get_width() > this->get_height()) ?
(this->get_height() / (float)this->get_width()) :
(this->get_width() / (float)this->get_height());
aperture_ = 0.5f * (cam_lens_ / (aspect_ * cam_sensor)) / f_stop_;
const float minsz = MIN2(get_width(), get_height());
dof_sp_ = minsz / ((cam_sensor / 2.0f) /
cam_lens_); /* <- == `aspect * MIN2(img->x, img->y) / tan(0.5f * fov)` */
if (blur_post_operation_) {
blur_post_operation_->set_sigma(MIN2(aperture_ * 128.0f, max_radius_));
}
}
void ConvertDepthToRadiusOperation::execute_pixel_sampled(float output[4],
float x,
float y,
PixelSampler sampler)
{
float input_value[4];
float z;
float radius;
input_operation_->read_sampled(input_value, x, y, sampler);
z = input_value[0];
if (z != 0.0f) {
float iZ = (1.0f / z);
/* bug T6656 part 2b, do not re-scale. */
#if 0
bcrad = 0.5f * fabs(aperture * (dof_sp * (cam_invfdist - iZ) - 1.0f));
/* Scale crad back to original maximum and blend. */
crad->rect[px] = bcrad + wts->rect[px] * (scf * crad->rect[px] - bcrad);
#endif
radius = 0.5f * fabsf(aperture_ * (dof_sp_ * (inverse_focal_distance_ - iZ) - 1.0f));
/* 'bug' T6615, limit minimum radius to 1 pixel,
* not really a solution, but somewhat mitigates the problem. */
if (radius < 0.0f) {
radius = 0.0f;
}
if (radius > max_radius_) {
radius = max_radius_;
}
output[0] = radius;
}
else {
output[0] = 0.0f;
}
}
void ConvertDepthToRadiusOperation::deinit_execution()
{
input_operation_ = nullptr;
}
void ConvertDepthToRadiusOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const float z = *it.in(0);
if (z == 0.0f) {
*it.out = 0.0f;
continue;
}
const float inv_z = (1.0f / z);
/* Bug T6656 part 2b, do not re-scale. */
#if 0
bcrad = 0.5f * fabs(aperture * (dof_sp * (cam_invfdist - iZ) - 1.0f));
/* Scale crad back to original maximum and blend:
* `crad->rect[px] = bcrad + wts->rect[px] * (scf * crad->rect[px] - bcrad);` */
#endif
const float radius = 0.5f *
fabsf(aperture_ * (dof_sp_ * (inverse_focal_distance_ - inv_z) - 1.0f));
/* Bug T6615, limit minimum radius to 1 pixel,
* not really a solution, but somewhat mitigates the problem. */
*it.out = CLAMPIS(radius, 0.0f, max_radius_);
}
}
} // namespace blender::compositor
|