GHOST: Fix uninitialized var
[blender.git] / source / blender / render / intern / source / pixelblending.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Full recode, 2004-2006 Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/render/intern/source/pixelblending.c
27  *  \ingroup render
28  *
29  * Functions to blend pixels with or without alpha, in various formats
30  * nzc - June 2000
31  */
32
33
34 #include <math.h>
35 #include <string.h>
36
37 /* global includes */
38
39 /* own includes */
40 #include "render_types.h"
41 #include "pixelblending.h"
42
43 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
44 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
45 /* only to be used here in this file, it's for speed */
46 extern struct Render R;
47 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
48
49
50 /* ------------------------------------------------------------------------- */
51 /* Debug/behavior defines                                                   */
52 /* if defined: alpha blending with floats clips color, as with shorts       */
53 /* #define RE_FLOAT_COLOR_CLIPPING  */
54 /* if defined: alpha values are clipped                                      */
55 /* For now, we just keep alpha clipping. We run into thresholding and        */
56 /* blending difficulties otherwise. Be careful here.                         */
57 #define RE_ALPHA_CLIPPING
58
59
60
61 /* Threshold for a 'full' pixel: pixels with alpha above this level are      */
62 /* considered opaque This is the decimal value for 0xFFF0 / 0xFFFF           */
63 #define RE_FULL_COLOR_FLOAT 0.9998f
64 /* Threshold for an 'empty' pixel: pixels with alpha above this level are    */
65 /* considered completely transparent. This is the decimal value              */
66 /* for 0x000F / 0xFFFF                                                       */
67 #define RE_EMPTY_COLOR_FLOAT 0.0002f
68
69
70 /* ------------------------------------------------------------------------- */
71
72 void addAlphaOverFloat(float dest[4], const float source[4])
73 {
74         /* d = s + (1-alpha_s)d*/
75         float mul;
76
77         mul = 1.0f - source[3];
78
79         dest[0] = (mul * dest[0]) + source[0];
80         dest[1] = (mul * dest[1]) + source[1];
81         dest[2] = (mul * dest[2]) + source[2];
82         dest[3] = (mul * dest[3]) + source[3];
83
84 }
85
86
87 /* ------------------------------------------------------------------------- */
88
89 void addAlphaUnderFloat(float dest[4], const float source[4])
90 {
91         float mul;
92
93         mul = 1.0f - dest[3];
94
95         dest[0] += (mul * source[0]);
96         dest[1] += (mul * source[1]);
97         dest[2] += (mul * source[2]);
98         dest[3] += (mul * source[3]);
99 }
100
101
102 /* ------------------------------------------------------------------------- */
103 void addalphaAddfacFloat(float dest[4], const float source[4], char addfac)
104 {
105         float m; /* weiging factor of destination */
106         float c; /* intermediate color           */
107
108         /* Addfac is a number between 0 and 1: rescale */
109         /* final target is to diminish the influence of dest when addfac rises */
110         m = 1.0f - (source[3] * ((255 - addfac) / 255.0f));
111
112         /* blend colors*/
113         c = (m * dest[0]) + source[0];
114 #ifdef RE_FLOAT_COLOR_CLIPPING
115         if (c >= RE_FULL_COLOR_FLOAT) dest[0] = RE_FULL_COLOR_FLOAT;
116         else
117 #endif
118         dest[0] = c;
119
120         c = (m * dest[1]) + source[1];
121 #ifdef RE_FLOAT_COLOR_CLIPPING
122         if (c >= RE_FULL_COLOR_FLOAT) dest[1] = RE_FULL_COLOR_FLOAT;
123         else
124 #endif
125         dest[1] = c;
126
127         c = (m * dest[2]) + source[2];
128 #ifdef RE_FLOAT_COLOR_CLIPPING
129         if (c >= RE_FULL_COLOR_FLOAT) dest[2] = RE_FULL_COLOR_FLOAT;
130         else
131 #endif
132         dest[2] = c;
133
134         c = (m * dest[3]) + source[3];
135 #ifdef RE_ALPHA_CLIPPING
136         if (c >= RE_FULL_COLOR_FLOAT) dest[3] = RE_FULL_COLOR_FLOAT;
137         else
138 #endif
139         dest[3] = c;
140
141 }
142
143
144 /* ------------------------------------------------------------------------- */
145
146 /* filtered adding to scanlines */
147 void add_filt_fmask(unsigned int mask, const float col[4], float *rowbuf, int row_w)
148 {
149         /* calc the value of mask */
150         float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2;
151         float *rb1, *rb2, *rb3;
152         float val, r, g, b, al;
153         unsigned int a, maskand, maskshift;
154         int j;
155
156         r = col[0];
157         g = col[1];
158         b = col[2];
159         al = col[3];
160
161         rb2 = rowbuf - 4;
162         rb3 = rb2 - 4 * row_w;
163         rb1 = rb2 + 4 * row_w;
164
165         maskand = (mask & 255);
166         maskshift = (mask >> 8);
167
168         for (j = 2; j >= 0; j--) {
169
170                 a = j;
171
172                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
173                 if (val != 0.0f) {
174                         rb1[0] += val * r;
175                         rb1[1] += val * g;
176                         rb1[2] += val * b;
177                         rb1[3] += val * al;
178                 }
179                 a += 3;
180
181                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
182                 if (val != 0.0f) {
183                         rb2[0] += val * r;
184                         rb2[1] += val * g;
185                         rb2[2] += val * b;
186                         rb2[3] += val * al;
187                 }
188                 a += 3;
189
190                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
191                 if (val != 0.0f) {
192                         rb3[0] += val * r;
193                         rb3[1] += val * g;
194                         rb3[2] += val * b;
195                         rb3[3] += val * al;
196                 }
197
198                 rb1 += 4;
199                 rb2 += 4;
200                 rb3 += 4;
201         }
202 }
203
204
205 void mask_array(unsigned int mask, float filt[3][3])
206 {
207         float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2;
208         unsigned int maskand = (mask & 255);
209         unsigned int maskshift = (mask >> 8);
210         int a, j;
211
212         for (j = 2; j >= 0; j--) {
213
214                 a = j;
215
216                 filt[2][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
217
218                 a += 3;
219
220                 filt[1][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
221
222                 a += 3;
223
224                 filt[0][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
225         }
226 }
227
228
229 /**
230  * Index ordering, scanline based:
231  *
232  * <pre>
233  *      ---    ---   ---
234  *     | 2,0 | 2,1 | 2,2 |
235  *      ---    ---   ---
236  *     | 1,0 | 1,1 | 1,2 |
237  *      ---    ---   ---
238  *     | 0,0 | 0,1 | 0,2 |
239  *      ---    ---   ---
240  * </pre>
241  */
242
243 void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_stride, int x, int y, rcti *mask)
244 {
245         float *fpoin[3][3];
246         float val, r, g, b, al, lfilt[3][3];
247
248         r = col[0];
249         g = col[1];
250         b = col[2];
251         al = col[3];
252
253         memcpy(lfilt, filt, sizeof(lfilt));
254
255         fpoin[0][1] = rowbuf - 4 * row_stride;
256         fpoin[1][1] = rowbuf;
257         fpoin[2][1] = rowbuf + 4 * row_stride;
258
259         fpoin[0][0] = fpoin[0][1] - 4;
260         fpoin[1][0] = fpoin[1][1] - 4;
261         fpoin[2][0] = fpoin[2][1] - 4;
262
263         fpoin[0][2] = fpoin[0][1] + 4;
264         fpoin[1][2] = fpoin[1][1] + 4;
265         fpoin[2][2] = fpoin[2][1] + 4;
266
267         /* limit filtering to withing a mask for border rendering, so pixels don't
268          * leak outside of the border */
269         if (y <= mask->ymin) {
270                 fpoin[0][0] = fpoin[1][0];
271                 fpoin[0][1] = fpoin[1][1];
272                 fpoin[0][2] = fpoin[1][2];
273                 /* filter needs the opposite value yes! */
274                 lfilt[0][0] = filt[2][0];
275                 lfilt[0][1] = filt[2][1];
276                 lfilt[0][2] = filt[2][2];
277         }
278         else if (y >= mask->ymax - 1) {
279                 fpoin[2][0] = fpoin[1][0];
280                 fpoin[2][1] = fpoin[1][1];
281                 fpoin[2][2] = fpoin[1][2];
282
283                 lfilt[2][0] = filt[0][0];
284                 lfilt[2][1] = filt[0][1];
285                 lfilt[2][2] = filt[0][2];
286         }
287
288         if (x <= mask->xmin) {
289                 fpoin[2][0] = fpoin[2][1];
290                 fpoin[1][0] = fpoin[1][1];
291                 fpoin[0][0] = fpoin[0][1];
292
293                 lfilt[2][0] = filt[2][2];
294                 lfilt[1][0] = filt[1][2];
295                 lfilt[0][0] = filt[0][2];
296         }
297         else if (x >= mask->xmax - 1) {
298                 fpoin[2][2] = fpoin[2][1];
299                 fpoin[1][2] = fpoin[1][1];
300                 fpoin[0][2] = fpoin[0][1];
301
302                 lfilt[2][2] = filt[2][0];
303                 lfilt[1][2] = filt[1][0];
304                 lfilt[0][2] = filt[0][0];
305         }
306
307
308         /* loop unroll */
309 #define MASKFILT(i, j)                                                        \
310         val = lfilt[i][j];                                                        \
311         if (val != 0.0f) {                                                        \
312                 float *fp = fpoin[i][j];                                              \
313                 fp[0] += val * r;                                                     \
314                 fp[1] += val * g;                                                     \
315                 fp[2] += val * b;                                                     \
316                 fp[3] += val * al;                                                    \
317         } (void)0
318
319         MASKFILT(0, 0);
320         MASKFILT(0, 1);
321         MASKFILT(0, 2);
322         MASKFILT(1, 0);
323         MASKFILT(1, 1);
324         MASKFILT(1, 2);
325         MASKFILT(2, 0);
326         MASKFILT(2, 1);
327         MASKFILT(2, 2);
328
329 #undef MASKFILT
330 }
331
332 void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize)
333 {
334         /* calc the value of mask */
335         float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2;
336         float *rb1, *rb2, *rb3;
337         float val;
338         unsigned int a, maskand, maskshift;
339         int i, j;
340
341         rb2 = rowbuf - pixsize;
342         rb3 = rb2 - pixsize * row_w;
343         rb1 = rb2 + pixsize * row_w;
344
345         maskand = (mask & 255);
346         maskshift = (mask >> 8);
347
348         for (j = 2; j >= 0; j--) {
349
350                 a = j;
351
352                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
353                 if (val != 0.0f) {
354                         for (i = 0; i < pixsize; i++)
355                                 rb1[i] += val * in[i];
356                 }
357                 a += 3;
358
359                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
360                 if (val != 0.0f) {
361                         for (i = 0; i < pixsize; i++)
362                                 rb2[i] += val * in[i];
363                 }
364                 a += 3;
365
366                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
367                 if (val != 0.0f) {
368                         for (i = 0; i < pixsize; i++)
369                                 rb3[i] += val * in[i];
370                 }
371
372                 rb1 += pixsize;
373                 rb2 += pixsize;
374                 rb3 += pixsize;
375         }
376 }
377
378 /* ------------------------------------------------------------------------- */
379 void addalphaAddFloat(float dest[4], const float source[4])
380 {
381
382         /* Makes me wonder whether this is required... */
383         if (dest[3] < RE_EMPTY_COLOR_FLOAT) {
384                 dest[0] = source[0];
385                 dest[1] = source[1];
386                 dest[2] = source[2];
387                 dest[3] = source[3];
388                 return;
389         }
390
391         /* no clipping! */
392         dest[0] = dest[0] + source[0];
393         dest[1] = dest[1] + source[1];
394         dest[2] = dest[2] + source[2];
395         dest[3] = dest[3] + source[3];
396
397 }
398
399
400 /* ---------------------------------------------------------------------------- */