Welcome to mirror list, hosted at ThFree Co, Russian Federation.

COM_ConvertDepthToRadiusOperation.cc « operations « compositor « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 89c1c7cb153507812735caef9fba52768d467218 (plain)
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