compositor - EWA filter was blurring too much by default, this caused the displace...
[blender.git] / source / blender / compositor / operations / COM_MapUVOperation.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor:
19  *              Dalai Felinto
20  */
21
22 #include "COM_MapUVOperation.h"
23 #include "BLI_math.h"
24
25 MapUVOperation::MapUVOperation() : NodeOperation()
26 {
27         this->addInputSocket(COM_DT_COLOR);
28         this->addInputSocket(COM_DT_VECTOR);
29         this->addOutputSocket(COM_DT_COLOR);
30         this->m_alpha = 0.0f;
31         this->setComplex(true);
32
33         this->m_inputUVProgram = NULL;
34         this->m_inputColorProgram = NULL;
35 }
36
37 void MapUVOperation::initExecution()
38 {
39         this->m_inputColorProgram = this->getInputSocketReader(0);
40         this->m_inputUVProgram = this->getInputSocketReader(1);
41 }
42
43 void MapUVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
44 {
45         float inputUV[4];
46         float uv_a[4], uv_b[4];
47         float u, v;
48
49         float dx, dy;
50         float uv_l, uv_r;
51         float uv_u, uv_d;
52
53         this->m_inputUVProgram->read(inputUV, x, y, sampler);
54         if (inputUV[2] == 0.f) {
55                 zero_v4(output);
56                 return;
57         }
58         /* adaptive sampling, red (U) channel */
59         this->m_inputUVProgram->read(uv_a, x - 1, y, COM_PS_NEAREST);
60         this->m_inputUVProgram->read(uv_b, x + 1, y, COM_PS_NEAREST);
61         uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
62         uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
63
64         dx = 0.5f * (uv_l + uv_r);
65
66         /* adaptive sampling, green (V) channel */
67         this->m_inputUVProgram->read(uv_a, x, y - 1, COM_PS_NEAREST);
68         this->m_inputUVProgram->read(uv_b, x, y + 1, COM_PS_NEAREST);
69         uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
70         uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
71
72         dy = 0.5f * (uv_u + uv_d);
73
74         /* more adaptive sampling, red and green (UV) channels */
75         this->m_inputUVProgram->read(uv_a, x - 1, y - 1, COM_PS_NEAREST);
76         this->m_inputUVProgram->read(uv_b, x - 1, y + 1, COM_PS_NEAREST);
77         uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
78         uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
79         uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
80         uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
81
82         dx += 0.25f * (uv_l + uv_r);
83         dy += 0.25f * (uv_u + uv_d);
84
85         this->m_inputUVProgram->read(uv_a, x + 1, y - 1, COM_PS_NEAREST);
86         this->m_inputUVProgram->read(uv_b, x + 1, y + 1, COM_PS_NEAREST);
87         uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
88         uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
89         uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
90         uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
91
92         dx += 0.25f * (uv_l + uv_r);
93         dy += 0.25f * (uv_u + uv_d);
94
95         /* UV to alpha threshold */
96         const float threshold = this->m_alpha * 0.05f;
97         float alpha = 1.0f - threshold * (dx + dy);
98         if (alpha < 0.f) alpha = 0.f;
99         else alpha *= inputUV[2];
100
101         /* should use mipmap */
102         dx = min(dx, 0.2f);
103         dy = min(dy, 0.2f);
104
105
106         /* EWA filtering */
107         u = inputUV[0] * this->m_inputColorProgram->getWidth();
108         v = inputUV[1] * this->m_inputColorProgram->getHeight();
109
110         this->m_inputColorProgram->read(output, u, v, dx, dy, COM_PS_NEAREST);
111
112         /* "premul" */
113         if (alpha < 1.0f) {
114                 mul_v4_fl(output, alpha);
115         }
116 }
117
118 void MapUVOperation::deinitExecution()
119 {
120         this->m_inputUVProgram = NULL;
121         this->m_inputColorProgram = NULL;
122 }
123
124 bool MapUVOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
125 {
126         rcti colorInput;
127         rcti uvInput;
128         NodeOperation *operation = NULL;
129
130         /* the uv buffer only needs a 3x3 buffer. The image needs whole buffer */
131
132         operation = getInputOperation(0);
133         colorInput.xmax = operation->getWidth();
134         colorInput.xmin = 0;
135         colorInput.ymax = operation->getHeight();
136         colorInput.ymin = 0;
137         if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) {
138                 return true;
139         }
140
141         operation = getInputOperation(1);
142         uvInput.xmax = input->xmax + 1;
143         uvInput.xmin = input->xmin - 1;
144         uvInput.ymax = input->ymax + 1;
145         uvInput.ymin = input->ymin - 1;
146         if (operation->determineDependingAreaOfInterest(&uvInput, readOperation, output)) {
147                 return true;
148         }
149
150         return false;
151 }
152