Cycles: add "Blur Glossy" integrator option.
[blender.git] / source / blender / nodes / composite / nodes / node_composite_image.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) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/composite/nodes/node_composite_image.c
29  *  \ingroup cmpnodes
30  */
31
32
33 #include "node_composite_util.h"
34
35
36 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
37
38 static bNodeSocketTemplate cmp_node_rlayers_out[]= {
39         {       SOCK_RGBA, 0, "Image",                                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
40         {       SOCK_FLOAT, 0, "Alpha",                                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
41         {       SOCK_FLOAT, 0, "Z",                                             1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
42         {       SOCK_VECTOR, 0, "Normal",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
43         {       SOCK_VECTOR, 0, "UV",                                   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
44         {       SOCK_VECTOR, 0, "Speed",                                1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
45         {       SOCK_RGBA, 0, "Color",                                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
46         {       SOCK_RGBA, 0, "Diffuse",                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
47         {       SOCK_RGBA, 0, "Specular",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
48         {       SOCK_RGBA, 0, "Shadow",                                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
49         {       SOCK_RGBA, 0, "AO",                                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
50         {       SOCK_RGBA, 0, "Reflect",                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
51         {       SOCK_RGBA, 0, "Refract",                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
52         {       SOCK_RGBA, 0, "Indirect",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
53         {       SOCK_FLOAT, 0, "IndexOB",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
54         {       SOCK_FLOAT, 0, "IndexMA",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
55         {       SOCK_FLOAT, 0, "Mist",                                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
56         {       SOCK_RGBA, 0, "Emit",                                   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
57         {       SOCK_RGBA, 0, "Environment",                    0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
58         {       SOCK_RGBA, 0, "Diffuse Direct",                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
59         {       SOCK_RGBA, 0, "Diffuse Indirect",               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
60         {       SOCK_RGBA, 0, "Diffuse Color",                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
61         {       SOCK_RGBA, 0, "Glossy Direct",                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
62         {       SOCK_RGBA, 0, "Glossy Indirect",                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
63         {       SOCK_RGBA, 0, "Glossy Color",                   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
64         {       SOCK_RGBA, 0, "Transmission Direct",    0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
65         {       SOCK_RGBA, 0, "Transmission Indirect",  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
66         {       SOCK_RGBA, 0, "Transmission Color",             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
67         {       -1, 0, ""       }
68 };
69
70 /* float buffer from the image with matching color management */
71 float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
72 {
73         float *rect;
74         int predivide= (ibuf->flags & IB_cm_predivide);
75
76         *alloc= FALSE;
77
78         if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
79                 if (ibuf->profile != IB_PROFILE_NONE) {
80                         rect= ibuf->rect_float;
81                 }
82                 else {
83                         rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
84
85                         IMB_buffer_float_from_float(rect, ibuf->rect_float,
86                                 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
87                                 ibuf->x, ibuf->y, ibuf->x, ibuf->x);
88
89                         *alloc= TRUE;
90                 }
91         }
92         else {
93                 if (ibuf->profile == IB_PROFILE_NONE) {
94                         rect= ibuf->rect_float;
95                 }
96                 else {
97                         rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
98
99                         IMB_buffer_float_from_float(rect, ibuf->rect_float,
100                                 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
101                                 ibuf->x, ibuf->y, ibuf->x, ibuf->x);
102
103                         *alloc= TRUE;
104                 }
105         }
106
107         return rect;
108 }
109
110 /* note: this function is used for multilayer too, to ensure uniform 
111    handling with BKE_image_get_ibuf() */
112 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
113 {
114         ImBuf *ibuf;
115         CompBuf *stackbuf;
116         int type;
117
118         float *rect;
119         int alloc= FALSE;
120
121         ibuf= BKE_image_get_ibuf(ima, iuser);
122         if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
123                 return NULL;
124         }
125
126         if (ibuf->rect_float == NULL) {
127                 IMB_float_from_rect(ibuf);
128         }
129
130         /* now we need a float buffer from the image with matching color management */
131         /* XXX weak code, multilayer is excluded from this */
132         if (ibuf->channels == 4 && ima->rr==NULL) {
133                 rect= node_composit_get_float_buffer(rd, ibuf, &alloc);
134         }
135         else {
136                 /* non-rgba passes can't use color profiles */
137                 rect= ibuf->rect_float;
138         }
139         /* done coercing into the correct color management */
140
141
142         type= ibuf->channels;
143         
144         if (rd->scemode & R_COMP_CROP) {
145                 stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
146                 if (alloc)
147                         MEM_freeN(rect);
148         }
149         else {
150                 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
151                 stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
152                 stackbuf->rect= rect;
153                 stackbuf->malloc= alloc;
154         }
155         
156         /*code to respect the premul flag of images; I'm
157           not sure if this is a good idea for multilayer images,
158           since it never worked before for them.
159         if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
160                 //premul the image
161                 int i;
162                 float *pixel = stackbuf->rect;
163                 
164                 for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
165                         pixel[0] *= pixel[3];
166                         pixel[1] *= pixel[3];
167                         pixel[2] *= pixel[3];
168                 }
169         }
170         */
171         return stackbuf;
172 }
173
174 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
175 {
176         ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
177         CompBuf *zbuf= NULL;
178         
179         if (ibuf && ibuf->zbuf_float) {
180                 if (rd->scemode & R_COMP_CROP) {
181                         zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
182                 }
183                 else {
184                         zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
185                         zbuf->rect= ibuf->zbuf_float;
186                 }
187         }
188         return zbuf;
189 }
190
191 /* check if layer is available, returns pass buffer */
192 static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype)
193 {
194         RenderPass *rpass;
195         short index;
196         
197         for (index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++)
198                 if (rpass->passtype==passtype)
199                         break;
200         
201         if (rpass) {
202                 CompBuf *cbuf;
203                 
204                 iuser->pass= index;
205                 BKE_image_multilayer_index(ima->rr, iuser);
206                 cbuf= node_composit_get_image(rd, ima, iuser);
207                 
208                 return cbuf;
209         }
210         return NULL;
211 }
212
213 static void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser)
214 {
215         if (out[RRES_OUT_Z]->hasoutput)
216                 out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z);
217         if (out[RRES_OUT_VEC]->hasoutput)
218                 out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR);
219         if (out[RRES_OUT_NORMAL]->hasoutput)
220                 out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL);
221         if (out[RRES_OUT_UV]->hasoutput)
222                 out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV);
223         
224         if (out[RRES_OUT_RGBA]->hasoutput)
225                 out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA);
226         if (out[RRES_OUT_DIFF]->hasoutput)
227                 out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE);
228         if (out[RRES_OUT_SPEC]->hasoutput)
229                 out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC);
230         if (out[RRES_OUT_SHADOW]->hasoutput)
231                 out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW);
232         if (out[RRES_OUT_AO]->hasoutput)
233                 out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO);
234         if (out[RRES_OUT_REFLECT]->hasoutput)
235                 out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT);
236         if (out[RRES_OUT_REFRACT]->hasoutput)
237                 out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT);
238         if (out[RRES_OUT_INDIRECT]->hasoutput)
239                 out[RRES_OUT_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDIRECT);
240         if (out[RRES_OUT_INDEXOB]->hasoutput)
241                 out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
242         if (out[RRES_OUT_INDEXMA]->hasoutput)
243                 out[RRES_OUT_INDEXMA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXMA);
244         if (out[RRES_OUT_MIST]->hasoutput)
245                 out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST);
246         if (out[RRES_OUT_EMIT]->hasoutput)
247                 out[RRES_OUT_EMIT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_EMIT);
248         if (out[RRES_OUT_ENV]->hasoutput)
249                 out[RRES_OUT_ENV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_ENVIRONMENT);
250         if (out[RRES_OUT_DIFF_DIRECT]->hasoutput)
251                 out[RRES_OUT_DIFF_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_DIRECT);
252         if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput)
253                 out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_INDIRECT);
254         if (out[RRES_OUT_DIFF_COLOR]->hasoutput)
255                 out[RRES_OUT_DIFF_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_COLOR);
256         if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput)
257                 out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_DIRECT);
258         if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput)
259                 out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_INDIRECT);
260         if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput)
261                 out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_COLOR);
262         if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput)
263                 out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_DIRECT);
264         if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput)
265                 out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_INDIRECT);
266         if (out[RRES_OUT_TRANSM_COLOR]->hasoutput)
267                 out[RRES_OUT_TRANSM_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_COLOR);
268 }
269
270
271 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
272 {
273         
274         /* image assigned to output */
275         /* stack order input sockets: col, alpha */
276         if (node->id) {
277                 RenderData *rd= data;
278                 Image *ima= (Image *)node->id;
279                 ImageUser *iuser= (ImageUser *)node->storage;
280                 CompBuf *stackbuf= NULL;
281                 
282                 /* first set the right frame number in iuser */
283                 BKE_image_user_calc_frame(iuser, rd->cfra, 0);
284                 
285                 /* force a load, we assume iuser index will be set OK anyway */
286                 if (ima->type==IMA_TYPE_MULTILAYER)
287                         BKE_image_get_ibuf(ima, iuser);
288                 
289                 if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
290                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
291                         
292                         if (rl) {
293                                 out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED);
294                                 
295                                 /* go over all layers */
296                                 outputs_multilayer_get(rd, rl, out, ima, iuser);
297                         }
298                 }
299                 else {
300                         stackbuf= node_composit_get_image(rd, ima, iuser);
301
302                         if (stackbuf) {
303                                 /*respect image premul option*/
304                                 if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
305                                         int i;
306                                         float *pixel;
307                         
308                                         /*first duplicate stackbuf->rect, since it's just a pointer
309                                           to the source imbuf, and we don't want to change that.*/
310                                         stackbuf->rect = MEM_dupallocN(stackbuf->rect);
311                                         
312                                         /* since stackbuf now has allocated memory, rather than just a pointer,
313                                          * mark it as allocated so it can be freed properly */
314                                         stackbuf->malloc=1;
315                                         
316                                         /*premul the image*/
317                                         pixel = stackbuf->rect;
318                                         for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
319                                                 pixel[0] *= pixel[3];
320                                                 pixel[1] *= pixel[3];
321                                                 pixel[2] *= pixel[3];
322                                         }
323                                 }
324                         
325                                 /* put image on stack */        
326                                 out[0]->data= stackbuf;
327                         
328                                 if (out[2]->hasoutput)
329                                         out[2]->data= node_composit_get_zimage(node, rd);
330                         }
331                 }
332                 
333                 /* alpha and preview for both types */
334                 if (stackbuf) {
335                         if (out[1]->hasoutput)
336                                 out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
337
338                         generate_preview(data, node, stackbuf);
339                 }
340         }       
341 }
342
343 static void node_composit_init_image(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
344 {
345         ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
346         node->storage= iuser;
347         iuser->frames= 1;
348         iuser->sfra= 1;
349         iuser->fie_ima= 2;
350         iuser->ok= 1;
351 }
352
353 void register_node_type_cmp_image(bNodeTreeType *ttype)
354 {
355         static bNodeType ntype;
356
357         node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
358         node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
359         node_type_size(&ntype, 120, 80, 300);
360         node_type_init(&ntype, node_composit_init_image);
361         node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
362         node_type_exec(&ntype, node_composit_exec_image);
363
364         nodeRegisterType(ttype, &ntype);
365 }
366
367
368 /* **************** RENDER RESULT ******************** */
369
370 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
371 {
372         float *fp= RE_RenderLayerGetPass(rl, passcode);
373         if (fp) {
374                 CompBuf *buf;
375                 int buftype= CB_VEC3;
376
377                 if (ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA))
378                         buftype= CB_VAL;
379                 else if (passcode==SCE_PASS_VECTOR)
380                         buftype= CB_VEC4;
381                 else if (ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
382                         buftype= CB_RGBA;
383
384                 if (rd->scemode & R_COMP_CROP)
385                         buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
386                 else {
387                         buf= alloc_compbuf(rectx, recty, buftype, 0);
388                         buf->rect= fp;
389                 }
390                 return buf;
391         }
392         return NULL;
393 }
394
395 static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
396 {
397         if (out[RRES_OUT_Z]->hasoutput)
398                 out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
399         if (out[RRES_OUT_VEC]->hasoutput)
400                 out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
401         if (out[RRES_OUT_NORMAL]->hasoutput)
402                 out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
403         if (out[RRES_OUT_UV]->hasoutput)
404                 out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
405
406         if (out[RRES_OUT_RGBA]->hasoutput)
407                 out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
408         if (out[RRES_OUT_DIFF]->hasoutput)
409                 out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
410         if (out[RRES_OUT_SPEC]->hasoutput)
411                 out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
412         if (out[RRES_OUT_SHADOW]->hasoutput)
413                 out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
414         if (out[RRES_OUT_AO]->hasoutput)
415                 out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
416         if (out[RRES_OUT_REFLECT]->hasoutput)
417                 out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
418         if (out[RRES_OUT_REFRACT]->hasoutput)
419                 out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
420         if (out[RRES_OUT_INDIRECT]->hasoutput)
421                 out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT);
422         if (out[RRES_OUT_INDEXOB]->hasoutput)
423                 out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
424         if (out[RRES_OUT_INDEXMA]->hasoutput)
425                 out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA);
426         if (out[RRES_OUT_MIST]->hasoutput)
427                 out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
428         if (out[RRES_OUT_EMIT]->hasoutput)
429                 out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT);
430         if (out[RRES_OUT_ENV]->hasoutput)
431                 out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT);
432         if (out[RRES_OUT_DIFF_DIRECT]->hasoutput)
433                 out[RRES_OUT_DIFF_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_DIRECT);
434         if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput)
435                 out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_INDIRECT);
436         if (out[RRES_OUT_DIFF_COLOR]->hasoutput)
437                 out[RRES_OUT_DIFF_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_COLOR);
438         if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput)
439                 out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_DIRECT);
440         if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput)
441                 out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_INDIRECT);
442         if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput)
443                 out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_COLOR);
444         if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput)
445                 out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_DIRECT);
446         if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput)
447                 out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_INDIRECT);
448         if (out[RRES_OUT_TRANSM_COLOR]->hasoutput)
449                 out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR);
450 }
451
452 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
453 {
454         Scene *sce= (Scene *)node->id;
455         Render *re= (sce)? RE_GetRender(sce->id.name): NULL;
456         RenderData *rd= data;
457         RenderResult *rr= NULL;
458
459         if (re)
460                 rr= RE_AcquireResultRead(re);
461
462         if (rr) {
463                 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
464                 if (srl) {
465                         RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
466                         if (rl && rl->rectf) {
467                                 CompBuf *stackbuf;
468
469                                 /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
470                                 if (rd->scemode & R_COMP_CROP)
471                                         stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
472                                 else {
473                                         stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
474                                         stackbuf->rect= rl->rectf;
475                                 }
476                                 if (stackbuf==NULL) {
477                                         printf("Error; Preview Panel in UV Window returns zero sized image\n");
478                                 }
479                                 else {
480                                         stackbuf->xof= rr->xof;
481                                         stackbuf->yof= rr->yof;
482
483                                         /* put on stack */
484                                         out[RRES_OUT_IMAGE]->data= stackbuf;
485
486                                         if (out[RRES_OUT_ALPHA]->hasoutput)
487                                                 out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
488
489                                         node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
490
491                                         generate_preview(data, node, stackbuf);
492                                 }
493                         }
494                 }
495         }
496
497         if (re)
498                 RE_ReleaseResult(re);
499 }
500
501
502 void register_node_type_cmp_rlayers(bNodeTreeType *ttype)
503 {
504         static bNodeType ntype;
505
506         node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
507         node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
508         node_type_size(&ntype, 150, 100, 300);
509         node_type_exec(&ntype, node_composit_exec_rlayers);
510
511         nodeRegisterType(ttype, &ntype);
512 }