This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/compositor/operations/COM_MapUVOperation.cpp
Jeroen Bakker e795b8410b * fix for regression test [compo_map_uv.blend]
the wrapping was resized to fit the uv map. this step was wrong and has
been deleted.
2012-10-02 11:37:15 +00:00

153 lines
4.6 KiB
C++

/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor:
* Dalai Felinto
*/
#include "COM_MapUVOperation.h"
#include "BLI_math.h"
MapUVOperation::MapUVOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
this->addInputSocket(COM_DT_VECTOR);
this->addOutputSocket(COM_DT_COLOR);
this->m_alpha = 0.0f;
this->setComplex(true);
this->m_inputUVProgram = NULL;
this->m_inputColorProgram = NULL;
}
void MapUVOperation::initExecution()
{
this->m_inputColorProgram = this->getInputSocketReader(0);
this->m_inputUVProgram = this->getInputSocketReader(1);
}
void MapUVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
float inputUV[4];
float uv_a[4], uv_b[4];
float u, v;
float dx, dy;
float uv_l, uv_r;
float uv_u, uv_d;
this->m_inputUVProgram->read(inputUV, x, y, sampler);
if (inputUV[2] == 0.f) {
zero_v4(output);
return;
}
/* adaptive sampling, red (U) channel */
this->m_inputUVProgram->read(uv_a, x - 1, y, COM_PS_NEAREST);
this->m_inputUVProgram->read(uv_b, x + 1, y, COM_PS_NEAREST);
uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
dx = 0.5f * (uv_l + uv_r);
/* adaptive sampling, green (V) channel */
this->m_inputUVProgram->read(uv_a, x, y - 1, COM_PS_NEAREST);
this->m_inputUVProgram->read(uv_b, x, y + 1, COM_PS_NEAREST);
uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
dy = 0.5f * (uv_u + uv_d);
/* more adaptive sampling, red and green (UV) channels */
this->m_inputUVProgram->read(uv_a, x - 1, y - 1, COM_PS_NEAREST);
this->m_inputUVProgram->read(uv_b, x - 1, y + 1, COM_PS_NEAREST);
uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
dx += 0.25f * (uv_l + uv_r);
dy += 0.25f * (uv_u + uv_d);
this->m_inputUVProgram->read(uv_a, x + 1, y - 1, COM_PS_NEAREST);
this->m_inputUVProgram->read(uv_b, x + 1, y + 1, COM_PS_NEAREST);
uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
dx += 0.25f * (uv_l + uv_r);
dy += 0.25f * (uv_u + uv_d);
/* UV to alpha threshold */
const float threshold = this->m_alpha * 0.05f;
float alpha = 1.0f - threshold * (dx + dy);
if (alpha < 0.f) alpha = 0.f;
else alpha *= inputUV[2];
/* should use mipmap */
dx = min(dx, 0.2f);
dy = min(dy, 0.2f);
/* EWA filtering */
u = inputUV[0] * this->m_inputColorProgram->getWidth();
v = inputUV[1] * this->m_inputColorProgram->getHeight();
this->m_inputColorProgram->read(output, u, v, dx, dy, COM_PS_NEAREST);
/* "premul" */
if (alpha < 1.0f) {
mul_v4_fl(output, alpha);
}
}
void MapUVOperation::deinitExecution()
{
this->m_inputUVProgram = NULL;
this->m_inputColorProgram = NULL;
}
bool MapUVOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
rcti colorInput;
rcti uvInput;
NodeOperation *operation = NULL;
/* the uv buffer only needs a 3x3 buffer. The image needs whole buffer */
operation = getInputOperation(0);
colorInput.xmax = operation->getWidth();
colorInput.xmin = 0;
colorInput.ymax = operation->getHeight();
colorInput.ymin = 0;
if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) {
return true;
}
operation = getInputOperation(1);
uvInput.xmax = input->xmax + 1;
uvInput.xmin = input->xmin - 1;
uvInput.ymax = input->ymax + 1;
uvInput.ymin = input->ymin - 1;
if (operation->determineDependingAreaOfInterest(&uvInput, readOperation, output)) {
return true;
}
return false;
}