diff options
author | Manuel Castilla <manzanillawork@gmail.com> | 2021-08-23 16:30:18 +0300 |
---|---|---|
committer | Manuel Castilla <manzanillawork@gmail.com> | 2021-08-23 18:07:37 +0300 |
commit | 344aca3b1bf2718904455ea6cef1ffd8bedf51a6 (patch) | |
tree | e71d120e19ed64c1475250e226082c4325bfe2c1 /source/blender/compositor/operations/COM_MapUVOperation.cc | |
parent | 064167fce70e3d7c382c374334a1bd0b520fe9fe (diff) |
Compositor: Full frame distort nodes
Adds full frame implementation to "Displace", "Crop", "Flip",
"Plane Track Deform", "Corner Pin", "Movie Distortion",
"Lens Distortion" and "Map UV" nodes.
The other nodes in "Distort" sub-menu are implemented
separately in other commits.
No functional changes.
Part of T88150.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D12166
Diffstat (limited to 'source/blender/compositor/operations/COM_MapUVOperation.cc')
-rw-r--r-- | source/blender/compositor/operations/COM_MapUVOperation.cc | 97 |
1 files changed, 91 insertions, 6 deletions
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cc b/source/blender/compositor/operations/COM_MapUVOperation.cc index 74e3d965d41..ad047c619f8 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.cc +++ b/source/blender/compositor/operations/COM_MapUVOperation.cc @@ -34,10 +34,26 @@ MapUVOperation::MapUVOperation() this->m_inputColorProgram = nullptr; } +void MapUVOperation::init_data() +{ + NodeOperation *image_input = get_input_operation(0); + image_width_ = image_input->getWidth(); + image_height_ = image_input->getHeight(); + + NodeOperation *uv_input = get_input_operation(1); + uv_width_ = uv_input->getWidth(); + uv_height_ = uv_input->getHeight(); +} + void MapUVOperation::initExecution() { this->m_inputColorProgram = this->getInputSocketReader(0); this->m_inputUVProgram = this->getInputSocketReader(1); + if (execution_model_ == eExecutionModel::Tiled) { + uv_input_read_fn_ = [=](float x, float y, float *out) { + this->m_inputUVProgram->readSampled(out, x, y, PixelSampler::Bilinear); + }; + } } void MapUVOperation::executePixelSampled(float output[4], @@ -81,9 +97,7 @@ void MapUVOperation::executePixelSampled(float output[4], bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha) { - float width = m_inputUVProgram->getWidth(); - float height = m_inputUVProgram->getHeight(); - if (x < 0.0f || x >= width || y < 0.0f || y >= height) { + if (x < 0.0f || x >= uv_width_ || y < 0.0f || y >= uv_height_) { r_u = 0.0f; r_v = 0.0f; r_alpha = 0.0f; @@ -91,9 +105,9 @@ bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_ } float vector[3]; - m_inputUVProgram->readSampled(vector, x, y, PixelSampler::Bilinear); - r_u = vector[0] * m_inputColorProgram->getWidth(); - r_v = vector[1] * m_inputColorProgram->getHeight(); + uv_input_read_fn_(x, y, vector); + r_u = vector[0] * image_width_; + r_v = vector[1] * image_height_; r_alpha = vector[2]; return true; } @@ -186,4 +200,75 @@ bool MapUVOperation::determineDependingAreaOfInterest(rcti *input, return false; } +void MapUVOperation::get_area_of_interest(const int input_idx, + const rcti &output_area, + rcti &r_input_area) +{ + switch (input_idx) { + case 0: { + r_input_area.xmin = 0; + r_input_area.xmax = image_width_; + r_input_area.ymin = 0; + r_input_area.ymax = image_height_; + break; + } + case 1: { + r_input_area = output_area; + expand_area_for_sampler(r_input_area, PixelSampler::Bilinear); + break; + } + } +} + +void MapUVOperation::update_memory_buffer_started(MemoryBuffer *UNUSED(output), + const rcti &UNUSED(area), + Span<MemoryBuffer *> inputs) +{ + const MemoryBuffer *uv_input = inputs[1]; + uv_input_read_fn_ = [=](float x, float y, float *out) { + uv_input->read_elem_bilinear(x, y, out); + }; +} + +void MapUVOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + const MemoryBuffer *input_image = inputs[0]; + for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) { + float xy[2] = {(float)it.x, (float)it.y}; + float uv[2]; + float deriv[2][2]; + float alpha; + pixelTransform(xy, uv, deriv, alpha); + if (alpha == 0.0f) { + zero_v4(it.out); + continue; + } + + /* EWA filtering. */ + input_image->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], it.out); + + /* UV to alpha threshold. */ + const float threshold = this->m_alpha * 0.05f; + /* XXX alpha threshold is used to fade out pixels on boundaries with invalid derivatives. + * this calculation is not very well defined, should be looked into if it becomes a problem ... + */ + const float du = len_v2(deriv[0]); + const float dv = len_v2(deriv[1]); + const float factor = 1.0f - threshold * (du / image_width_ + dv / image_height_); + if (factor < 0.0f) { + alpha = 0.0f; + } + else { + alpha *= factor; + } + + /* "premul" */ + if (alpha < 1.0f) { + mul_v4_fl(it.out, alpha); + } + } +} + } // namespace blender::compositor |