Blender V4.3
COM_ConvertDepthToRadiusOperation.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_math_base.hh"
6
7#include "DNA_camera_types.h"
8#include "DNA_node_types.h"
9#include "DNA_object_types.h"
10#include "DNA_scene_types.h"
11
12#include "BKE_camera.h"
13
15
16namespace blender::compositor {
17
25
27{
28 depth_input_operation_ = this->get_input_socket_reader(0);
29 image_input_operation_ = this->get_input_socket_reader(1);
30
31 f_stop = get_f_stop();
32 focal_length = get_focal_length();
33 max_radius = data_->maxblur;
34 pixels_per_meter = compute_pixels_per_meter();
35 distance_to_image_of_focus = compute_distance_to_image_of_focus();
36
37 NodeBlurData blur_data;
38 blur_data.sizex = compute_maximum_defocus_radius();
39 blur_data.sizey = blur_data.sizex;
40 blur_data.relative = false;
41 blur_data.filtertype = R_FILTER_GAUSS;
42
43 blur_x_operation_->set_data(&blur_data);
44 blur_x_operation_->set_size(1.0f);
45 blur_y_operation_->set_data(&blur_data);
46 blur_y_operation_->set_size(1.0f);
47}
48
49/* Given a depth texture, compute the radius of the circle of confusion in pixels based on equation
50 * (8) of the paper:
51 *
52 * Potmesil, Michael, and Indranil Chakravarty. "A lens and aperture camera model for synthetic
53 * image generation." ACM SIGGRAPH Computer Graphics 15.3 (1981): 297-305. */
55 const rcti &area,
57{
58 for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
59 const float depth = *it.in(0);
60
61 /* Compute `Vu` in equation (7). */
62 const float distance_to_image_of_object = (focal_length * depth) / (depth - focal_length);
63
64 /* Compute C in equation (8). Notice that the last multiplier was included in the absolute
65 * since it is negative when the object distance is less than the focal length, as noted in
66 * equation (7). */
67 float diameter = abs((distance_to_image_of_object - distance_to_image_of_focus) *
68 (focal_length / (f_stop * distance_to_image_of_object)));
69
70 /* The diameter is in meters, so multiply by the pixels per meter. */
71 float radius = (diameter / 2.0f) * pixels_per_meter;
72
73 *it.out = math::min(max_radius, radius);
74 }
75}
76
77/* Computes the maximum possible defocus radius in pixels. */
78float ConvertDepthToRadiusOperation::compute_maximum_defocus_radius() const
79{
80 const float maximum_diameter = compute_maximum_diameter_of_circle_of_confusion();
81 const float pixels_per_meter = compute_pixels_per_meter();
82 const float radius = (maximum_diameter / 2.0f) * pixels_per_meter;
83 return math::min(radius, data_->maxblur);
84}
85
86/* Computes the diameter of the circle of confusion at infinity. This computes the limit in
87 * figure (5) of the paper:
88 *
89 * Potmesil, Michael, and Indranil Chakravarty. "A lens and aperture camera model for synthetic
90 * image generation." ACM SIGGRAPH Computer Graphics 15.3 (1981): 297-305.
91 *
92 * Notice that the diameter is asymmetric around the focus point, and we are computing the
93 * limiting diameter at infinity, while another limiting diameter exist at zero distance from the
94 * lens. This is a limitation of the implementation, as it assumes far defocusing only. */
95float ConvertDepthToRadiusOperation::compute_maximum_diameter_of_circle_of_confusion() const
96{
97 const float f_stop = get_f_stop();
98 const float focal_length = get_focal_length();
99 const float distance_to_image_of_focus = compute_distance_to_image_of_focus();
100 return math::abs((distance_to_image_of_focus / (f_stop * focal_length)) -
101 (focal_length / f_stop));
102}
103
104/* Computes the distance in meters to the image of the focus point across a lens of the specified
105 * focal length. This computes `Vp` in equation (7) of the paper:
106 *
107 * Potmesil, Michael, and Indranil Chakravarty. "A lens and aperture camera model for synthetic
108 * image generation." ACM SIGGRAPH Computer Graphics 15.3 (1981): 297-305. */
109float ConvertDepthToRadiusOperation::compute_distance_to_image_of_focus() const
110{
111 const float focal_length = get_focal_length();
112 const float focus_distance = compute_focus_distance();
113 return (focal_length * focus_distance) / (focus_distance - focal_length);
114}
115
116/* Returns the focal length in meters. Fallback to 50 mm in case of an invalid camera. Ensure a
117 * minimum of 1e-6. */
118float ConvertDepthToRadiusOperation::get_focal_length() const
119{
120 const Camera *camera = get_camera();
121 return camera ? math::max(1e-6f, camera->lens / 1000.0f) : 50.0f / 1000.0f;
122}
123
124/* Computes the distance to the point that is completely in focus. Default to 10 meters for null
125 * camera. */
126float ConvertDepthToRadiusOperation::compute_focus_distance() const
127{
128 const Object *camera_object = get_camera_object();
129 if (!camera_object) {
130 return 10.0f;
131 }
132 return BKE_camera_object_dof_distance(camera_object);
133}
134
135/* Computes the number of pixels per meter of the sensor size. This is essentially the resolution
136 * over the sensor size, using the sensor fit axis. Fallback to DEFAULT_SENSOR_WIDTH in case of
137 * an invalid camera. Note that the stored sensor size is in millimeter, so convert to meters. */
138float ConvertDepthToRadiusOperation::compute_pixels_per_meter() const
139{
140 const int2 size = int2(image_input_operation_->get_width(),
141 image_input_operation_->get_height());
142 const Camera *camera = get_camera();
143 const float default_value = size.x / (DEFAULT_SENSOR_WIDTH / 1000.0f);
144 if (!camera) {
145 return default_value;
146 }
147
148 switch (camera->sensor_fit) {
150 return size.x / (camera->sensor_x / 1000.0f);
152 return size.y / (camera->sensor_y / 1000.0f);
154 return size.x > size.y ? size.x / (camera->sensor_x / 1000.0f) :
155 size.y / (camera->sensor_y / 1000.0f);
156 }
157 default:
158 break;
159 }
160
161 return default_value;
162}
163
164/* Returns the f-stop number. Fallback to 1e-3 for zero f-stop. */
165float ConvertDepthToRadiusOperation::get_f_stop() const
166{
167 return math::max(1e-3f, data_->fstop);
168}
169
170const Camera *ConvertDepthToRadiusOperation::get_camera() const
171{
172 const Object *camera_object = get_camera_object();
173 if (!camera_object || camera_object->type != OB_CAMERA) {
174 return nullptr;
175 }
176
177 return reinterpret_cast<Camera *>(camera_object->data);
178}
179
180const Object *ConvertDepthToRadiusOperation::get_camera_object() const
181{
182 return scene_->camera;
183}
184
185} // namespace blender::compositor
Camera data-block and utility functions.
float BKE_camera_object_dof_distance(const struct Object *ob)
@ CAMERA_SENSOR_FIT_HOR
@ CAMERA_SENSOR_FIT_AUTO
@ CAMERA_SENSOR_FIT_VERT
#define DEFAULT_SENSOR_WIDTH
Object is a sort of wrapper for general info.
@ OB_CAMERA
@ R_FILTER_GAUSS
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
a MemoryBuffer contains access to the data
void add_output_socket(DataType datatype)
SocketReader * get_input_socket_reader(unsigned int index)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
T min(const T &a, const T &b)
T max(const T &a, const T &b)
T abs(const T &a)
VecBase< int32_t, 2 > int2
struct Object * camera
ccl_device_inline int abs(int x)
Definition util/math.h:120