2
* ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18
* The Original Code is Copyright (C) 2006 Blender Foundation.
19
* All rights reserved.
21
* The Original Code is: all of this file.
23
* Contributor(s): none yet.
25
* ***** END GPL LICENSE BLOCK *****
28
/** \file blender/nodes/composite/nodes/node_composite_image.c
33
#include "node_composite_util.h"
35
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
37
static bNodeSocketTemplate cmp_node_rlayers_out[]= {
38
{ SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
39
{ SOCK_FLOAT, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
40
{ SOCK_FLOAT, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
41
{ SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
42
{ SOCK_VECTOR, 0, "UV", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
43
{ SOCK_VECTOR, 0, "Speed", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
44
{ SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
45
{ SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
46
{ SOCK_RGBA, 0, "Specular", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
47
{ SOCK_RGBA, 0, "Shadow", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
48
{ SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
49
{ SOCK_RGBA, 0, "Reflect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
50
{ SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
51
{ SOCK_RGBA, 0, "Indirect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
52
{ SOCK_FLOAT, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
53
{ SOCK_FLOAT, 0, "IndexMA", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
54
{ SOCK_FLOAT, 0, "Mist", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
55
{ SOCK_RGBA, 0, "Emit", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
56
{ SOCK_RGBA, 0, "Environment", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
57
{ SOCK_RGBA, 0, "Diffuse Direct", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
58
{ SOCK_RGBA, 0, "Diffuse Indirect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
59
{ SOCK_RGBA, 0, "Diffuse Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
60
{ SOCK_RGBA, 0, "Glossy Direct", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
61
{ SOCK_RGBA, 0, "Glossy Indirect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
62
{ SOCK_RGBA, 0, "Glossy Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
63
{ SOCK_RGBA, 0, "Transmission Direct", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
64
{ SOCK_RGBA, 0, "Transmission Indirect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
65
{ SOCK_RGBA, 0, "Transmission Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
69
static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int UNUSED(pass), int rres_index)
73
sock = node_add_output_from_template(ntree, node, &cmp_node_rlayers_out[rres_index]);
74
/* for render pass outputs store the pass type index as a lookup key */
75
sock->storage = SET_INT_IN_POINTER(rres_index);
80
static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag)
82
if (passflag & SCE_PASS_COMBINED) {
83
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE);
84
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA);
87
if (passflag & SCE_PASS_Z)
88
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z);
89
if (passflag & SCE_PASS_NORMAL)
90
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL);
91
if (passflag & SCE_PASS_VECTOR)
92
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC);
93
if (passflag & SCE_PASS_UV)
94
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV);
95
if (passflag & SCE_PASS_RGBA)
96
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA);
97
if (passflag & SCE_PASS_DIFFUSE)
98
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF);
99
if (passflag & SCE_PASS_SPEC)
100
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC);
101
if (passflag & SCE_PASS_SHADOW)
102
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW);
103
if (passflag & SCE_PASS_AO)
104
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO);
105
if (passflag & SCE_PASS_REFLECT)
106
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT);
107
if (passflag & SCE_PASS_REFRACT)
108
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT);
109
if (passflag & SCE_PASS_INDIRECT)
110
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT);
111
if (passflag & SCE_PASS_INDEXOB)
112
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB);
113
if (passflag & SCE_PASS_INDEXMA)
114
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA);
115
if (passflag & SCE_PASS_MIST)
116
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST);
117
if (passflag & SCE_PASS_EMIT)
118
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT);
119
if (passflag & SCE_PASS_ENVIRONMENT)
120
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV);
122
if (passflag & SCE_PASS_DIFFUSE_DIRECT)
123
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT);
124
if (passflag & SCE_PASS_DIFFUSE_INDIRECT)
125
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT);
126
if (passflag & SCE_PASS_DIFFUSE_COLOR)
127
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR);
129
if (passflag & SCE_PASS_GLOSSY_DIRECT)
130
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT);
131
if (passflag & SCE_PASS_GLOSSY_INDIRECT)
132
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT);
133
if (passflag & SCE_PASS_GLOSSY_COLOR)
134
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR);
136
if (passflag & SCE_PASS_TRANSM_DIRECT)
137
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT);
138
if (passflag & SCE_PASS_TRANSM_INDIRECT)
139
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
140
if (passflag & SCE_PASS_TRANSM_COLOR)
141
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
144
static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
149
for (rpass=rl->passes.first, index=0; rpass; rpass=rpass->next, ++index) {
151
if (rpass->channels == 1)
156
sock = nodeAddSocket(ntree, node, SOCK_OUT, rpass->name, type);
157
/* for multilayer image use pass index directly as key */
158
sock->storage = SET_INT_IN_POINTER(index);
162
static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
164
Image *ima= (Image *)node->id;
166
ImageUser *iuser= node->storage;
168
/* make sure ima->type is correct */
169
BKE_image_get_ibuf(ima, iuser);
172
RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
175
if (ima->type!=IMA_TYPE_MULTILAYER)
176
cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag);
178
cmp_node_image_add_multilayer_outputs(ntree, node, rl);
181
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
184
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z);
187
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
190
static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
194
for (sock=oldsocklist->first; sock; sock=sock->next)
195
if (strcmp(sock->name, newsock->name)==0)
200
static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
204
/* first try to find matching socket name */
205
for (sock=node->outputs.first; sock; sock=sock->next)
206
if (strcmp(sock->name, oldsock->name)==0)
209
/* no matching name, simply link to same index */
210
return BLI_findlink(&node->outputs, oldindex);
213
static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
218
/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
219
static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
221
bNodeSocket *newsock, *oldsock, *oldsock_next;
222
ListBase oldsocklist;
226
/* store current nodes in oldsocklist, then clear socket list */
227
oldsocklist = node->outputs;
228
node->outputs.first = node->outputs.last = NULL;
230
/* XXX make callback */
231
cmp_node_image_create_outputs(ntree, node);
232
/* flag all new sockets as dynamic, to prevent removal by socket verification function */
233
for (newsock=node->outputs.first; newsock; newsock=newsock->next)
234
newsock->flag |= SOCK_DYNAMIC;
236
for (newsock=node->outputs.first; newsock; newsock=newsock->next) {
237
/* XXX make callback */
238
oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
240
/* XXX make callback */
241
cmp_node_image_sync_output(node, newsock, oldsock);
245
/* move links to new socket */
246
for (oldsock=oldsocklist.first, oldindex=0; oldsock; oldsock=oldsock->next, ++oldindex) {
247
newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
250
for (link=ntree->links.first; link; link=link->next) {
251
if (link->fromsock == oldsock)
252
link->fromsock = newsock;
257
/* delete old sockets
258
* XXX oldsock is not actually in the node->outputs list any more,
259
* but the nodeRemoveSocket function works anyway. In future this
260
* should become part of the core code, so can take care of this behavior.
262
for (oldsock=oldsocklist.first; oldsock; oldsock=oldsock_next) {
263
oldsock_next = oldsock->next;
264
nodeRemoveSocket(ntree, node, oldsock);
268
static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
270
/* avoid unnecessary updates, only changes to the image/image user data are of interest */
271
if (node->update & NODE_UPDATE_ID)
272
cmp_node_image_verify_outputs(ntree, node);
275
/* float buffer from the image with matching color management */
276
float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
279
int predivide= (ibuf->flags & IB_cm_predivide);
283
if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
284
if (ibuf->profile != IB_PROFILE_NONE) {
285
rect= ibuf->rect_float;
288
rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
290
IMB_buffer_float_from_float(rect, ibuf->rect_float,
291
4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
292
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
298
if (ibuf->profile == IB_PROFILE_NONE) {
299
rect= ibuf->rect_float;
302
rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
304
IMB_buffer_float_from_float(rect, ibuf->rect_float,
305
4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
306
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
315
/* note: this function is used for multilayer too, to ensure uniform
316
handling with BKE_image_get_ibuf() */
317
static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
326
ibuf= BKE_image_get_ibuf(ima, iuser);
327
if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
331
if (ibuf->rect_float == NULL) {
332
IMB_float_from_rect(ibuf);
335
/* now we need a float buffer from the image with matching color management */
336
/* XXX weak code, multilayer is excluded from this */
337
if (ibuf->channels == 4 && ima->rr==NULL) {
338
rect= node_composit_get_float_buffer(rd, ibuf, &alloc);
341
/* non-rgba passes can't use color profiles */
342
rect= ibuf->rect_float;
344
/* done coercing into the correct color management */
347
type= ibuf->channels;
349
if (rd->scemode & R_COMP_CROP) {
350
stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
355
/* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
356
stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
357
stackbuf->rect= rect;
358
stackbuf->malloc= alloc;
361
/*code to respect the premul flag of images; I'm
362
not sure if this is a good idea for multilayer images,
363
since it never worked before for them.
364
if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
367
float *pixel = stackbuf->rect;
369
for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
370
pixel[0] *= pixel[3];
371
pixel[1] *= pixel[3];
372
pixel[2] *= pixel[3];
379
static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
381
ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
384
if (ibuf && ibuf->zbuf_float) {
385
if (rd->scemode & R_COMP_CROP) {
386
zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
389
zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
390
zbuf->rect= ibuf->zbuf_float;
396
/* check if layer is available, returns pass buffer */
397
static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passindex)
399
RenderPass *rpass = BLI_findlink(&rl->passes, passindex);
403
iuser->pass = passindex;
404
BKE_image_multilayer_index(ima->rr, iuser);
405
cbuf = node_composit_get_image(rd, ima, iuser);
412
static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
415
/* image assigned to output */
416
/* stack order input sockets: col, alpha */
418
RenderData *rd= data;
419
Image *ima= (Image *)node->id;
420
ImageUser *iuser= (ImageUser *)node->storage;
422
/* first set the right frame number in iuser */
423
BKE_image_user_calc_frame(iuser, rd->cfra, 0);
425
/* force a load, we assume iuser index will be set OK anyway */
426
if (ima->type==IMA_TYPE_MULTILAYER)
427
BKE_image_get_ibuf(ima, iuser);
429
if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
430
RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
435
CompBuf *combinedbuf= NULL, *firstbuf= NULL;
437
for (sock=node->outputs.first, out_index=0; sock; sock=sock->next, ++out_index) {
438
int passindex = GET_INT_FROM_POINTER(sock->storage);
439
if (out[out_index]->hasoutput) {
440
CompBuf *stackbuf = out[out_index]->data = compbuf_multilayer_get(rd, rl, ima, iuser, passindex);
442
/* preview policy: take first 'Combined' pass if available,
443
* otherwise just use the first layer.
448
(strcmp(sock->name, "Combined")==0 || strcmp(sock->name, "Image")==0))
449
combinedbuf = stackbuf;
456
generate_preview(data, node, combinedbuf);
458
generate_preview(data, node, firstbuf);
462
CompBuf *stackbuf = node_composit_get_image(rd, ima, iuser);
464
int num_outputs = BLI_countlist(&node->outputs);
466
/*respect image premul option*/
467
if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
471
/*first duplicate stackbuf->rect, since it's just a pointer
472
to the source imbuf, and we don't want to change that.*/
473
stackbuf->rect = MEM_dupallocN(stackbuf->rect);
475
/* since stackbuf now has allocated memory, rather than just a pointer,
476
* mark it as allocated so it can be freed properly */
480
pixel = stackbuf->rect;
481
for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
482
pixel[0] *= pixel[3];
483
pixel[1] *= pixel[3];
484
pixel[2] *= pixel[3];
488
/* put image on stack */
490
out[0]->data= stackbuf;
493
if (num_outputs > 1 && out[1]->hasoutput)
494
out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
497
if (num_outputs > 2 && out[2]->hasoutput)
498
out[2]->data= node_composit_get_zimage(node, rd);
501
generate_preview(data, node, stackbuf);
507
static void node_composit_init_image(bNodeTree *ntree, bNode* node, bNodeTemplate *UNUSED(ntemp))
509
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
510
node->storage= iuser;
516
/* setup initial outputs */
517
cmp_node_image_verify_outputs(ntree, node);
520
void register_node_type_cmp_image(bNodeTreeType *ttype)
522
static bNodeType ntype;
524
node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
525
node_type_size(&ntype, 120, 80, 300);
526
node_type_init(&ntype, node_composit_init_image);
527
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
528
node_type_update(&ntype, cmp_node_image_update, NULL);
529
node_type_exec(&ntype, node_composit_exec_image);
531
nodeRegisterType(ttype, &ntype);
535
/* **************** RENDER RESULT ******************** */
537
static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
539
float *fp= RE_RenderLayerGetPass(rl, passcode);
542
int buftype= CB_VEC3;
544
if (ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA))
546
else if (passcode==SCE_PASS_VECTOR)
548
else if (ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
551
if (rd->scemode & R_COMP_CROP)
552
buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
554
buf= alloc_compbuf(rectx, recty, buftype, 0);
562
static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
564
if (out[RRES_OUT_Z]->hasoutput)
565
out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
566
if (out[RRES_OUT_VEC]->hasoutput)
567
out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
568
if (out[RRES_OUT_NORMAL]->hasoutput)
569
out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
570
if (out[RRES_OUT_UV]->hasoutput)
571
out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
573
if (out[RRES_OUT_RGBA]->hasoutput)
574
out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
575
if (out[RRES_OUT_DIFF]->hasoutput)
576
out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
577
if (out[RRES_OUT_SPEC]->hasoutput)
578
out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
579
if (out[RRES_OUT_SHADOW]->hasoutput)
580
out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
581
if (out[RRES_OUT_AO]->hasoutput)
582
out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
583
if (out[RRES_OUT_REFLECT]->hasoutput)
584
out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
585
if (out[RRES_OUT_REFRACT]->hasoutput)
586
out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
587
if (out[RRES_OUT_INDIRECT]->hasoutput)
588
out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT);
589
if (out[RRES_OUT_INDEXOB]->hasoutput)
590
out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
591
if (out[RRES_OUT_INDEXMA]->hasoutput)
592
out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA);
593
if (out[RRES_OUT_MIST]->hasoutput)
594
out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
595
if (out[RRES_OUT_EMIT]->hasoutput)
596
out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT);
597
if (out[RRES_OUT_ENV]->hasoutput)
598
out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT);
599
if (out[RRES_OUT_DIFF_DIRECT]->hasoutput)
600
out[RRES_OUT_DIFF_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_DIRECT);
601
if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput)
602
out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_INDIRECT);
603
if (out[RRES_OUT_DIFF_COLOR]->hasoutput)
604
out[RRES_OUT_DIFF_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_COLOR);
605
if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput)
606
out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_DIRECT);
607
if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput)
608
out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_INDIRECT);
609
if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput)
610
out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_COLOR);
611
if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput)
612
out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_DIRECT);
613
if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput)
614
out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_INDIRECT);
615
if (out[RRES_OUT_TRANSM_COLOR]->hasoutput)
616
out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR);
621
static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
623
Scene *sce= (Scene *)node->id;
624
Render *re= (sce)? RE_GetRender(sce->id.name): NULL;
625
RenderData *rd= data;
626
RenderResult *rr= NULL;
629
rr= RE_AcquireResultRead(re);
632
SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
634
RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
635
if (rl && rl->rectf) {
638
/* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
639
if (rd->scemode & R_COMP_CROP)
640
stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
642
stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
643
stackbuf->rect= rl->rectf;
645
if (stackbuf==NULL) {
646
printf("Error; Preview Panel in UV Window returns zero sized image\n");
649
stackbuf->xof= rr->xof;
650
stackbuf->yof= rr->yof;
653
out[RRES_OUT_IMAGE]->data= stackbuf;
655
if (out[RRES_OUT_ALPHA]->hasoutput)
656
out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
658
node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
660
generate_preview(data, node, stackbuf);
667
RE_ReleaseResult(re);
671
void register_node_type_cmp_rlayers(bNodeTreeType *ttype)
673
static bNodeType ntype;
675
node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
676
node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
677
node_type_size(&ntype, 150, 100, 300);
678
node_type_exec(&ntype, node_composit_exec_rlayers);
680
nodeRegisterType(ttype, &ntype);