4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2006 Blender Foundation.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
30 #include "../CMP_util.h"
33 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
35 static bNodeSocketType cmp_node_rlayers_out[]= {
36 { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
37 { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
38 { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
39 { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
40 { SOCK_VECTOR, 0, "UV", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
41 { SOCK_VECTOR, 0, "Speed", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
42 { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
43 { SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
44 { SOCK_RGBA, 0, "Specular", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
45 { SOCK_RGBA, 0, "Shadow", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
46 { SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
47 { SOCK_RGBA, 0, "Reflect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
48 { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
49 { SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
50 { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
51 { SOCK_VALUE, 0, "Mist", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
56 /* note: this function is used for multilayer too, to ensure uniform
57 handling with BKE_image_get_ibuf() */
58 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
64 ibuf= BKE_image_get_ibuf(ima, iuser);
68 if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
69 if (ibuf->profile == IB_PROFILE_NONE) {
70 if (ibuf->rect_float != NULL) {
71 imb_freerectfloatImBuf(ibuf);
73 ibuf->profile = IB_PROFILE_SRGB;
74 IMB_float_from_rect(ibuf);
77 if (ibuf->profile == IB_PROFILE_SRGB) {
78 if (ibuf->rect_float != NULL) {
79 imb_freerectfloatImBuf(ibuf);
81 ibuf->profile = IB_PROFILE_NONE;
82 IMB_float_from_rect(ibuf);
86 if (ibuf->rect_float == NULL) {
87 IMB_float_from_rect(ibuf);
92 if(rd->scemode & R_COMP_CROP) {
93 stackbuf= get_cropped_compbuf(&rd->disprect, ibuf->rect_float, ibuf->x, ibuf->y, type);
96 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
97 stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, 0);
98 stackbuf->rect= ibuf->rect_float;
101 /*code to respect the premul flag of images; I'm
102 not sure if this is a good idea for multilayer images,
103 since it never worked before for them.
104 if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
107 float *pixel = stackbuf->rect;
109 for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
110 pixel[0] *= pixel[3];
111 pixel[1] *= pixel[3];
112 pixel[2] *= pixel[3];
119 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
121 ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
124 if(ibuf && ibuf->zbuf_float) {
125 if(rd->scemode & R_COMP_CROP) {
126 zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
129 zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
130 zbuf->rect= ibuf->zbuf_float;
136 /* check if layer is available, returns pass buffer */
137 static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype)
142 for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++)
143 if(rpass->passtype==passtype)
150 BKE_image_multilayer_index(ima->rr, iuser);
151 cbuf= node_composit_get_image(rd, ima, iuser);
158 void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser)
160 if(out[RRES_OUT_Z]->hasoutput)
161 out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z);
162 if(out[RRES_OUT_VEC]->hasoutput)
163 out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR);
164 if(out[RRES_OUT_NORMAL]->hasoutput)
165 out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL);
166 if(out[RRES_OUT_UV]->hasoutput)
167 out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV);
169 if(out[RRES_OUT_RGBA]->hasoutput)
170 out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA);
171 if(out[RRES_OUT_DIFF]->hasoutput)
172 out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE);
173 if(out[RRES_OUT_SPEC]->hasoutput)
174 out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC);
175 if(out[RRES_OUT_SHADOW]->hasoutput)
176 out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW);
177 if(out[RRES_OUT_AO]->hasoutput)
178 out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO);
179 if(out[RRES_OUT_REFLECT]->hasoutput)
180 out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT);
181 if(out[RRES_OUT_REFRACT]->hasoutput)
182 out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT);
183 if(out[RRES_OUT_RADIO]->hasoutput)
184 out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO);
185 if(out[RRES_OUT_INDEXOB]->hasoutput)
186 out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
187 if(out[RRES_OUT_MIST]->hasoutput)
188 out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST);
193 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
196 /* image assigned to output */
197 /* stack order input sockets: col, alpha */
199 RenderData *rd= data;
200 Image *ima= (Image *)node->id;
201 ImageUser *iuser= (ImageUser *)node->storage;
202 CompBuf *stackbuf= NULL;
204 /* first set the right frame number in iuser */
205 BKE_image_user_calc_imanr(iuser, rd->cfra, 0);
207 /* force a load, we assume iuser index will be set OK anyway */
208 if(ima->type==IMA_TYPE_MULTILAYER)
209 BKE_image_get_ibuf(ima, iuser);
211 if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
212 RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
215 out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED);
217 /* go over all layers */
218 outputs_multilayer_get(rd, rl, out, ima, iuser);
222 stackbuf= node_composit_get_image(rd, ima, iuser);
225 /*respect image premul option*/
226 if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
230 /*first duplicate stackbuf->rect, since it's just a pointer
231 to the source imbuf, and we don't want to change that.*/
232 stackbuf->rect = MEM_dupallocN(stackbuf->rect);
236 pixel = stackbuf->rect;
237 for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
238 pixel[0] *= pixel[3];
239 pixel[1] *= pixel[3];
240 pixel[2] *= pixel[3];
244 /* put image on stack */
245 out[0]->data= stackbuf;
247 if(out[2]->hasoutput)
248 out[2]->data= node_composit_get_zimage(node, rd);
252 /* alpha and preview for both types */
254 if(out[1]->hasoutput)
255 out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
257 generate_preview(node, stackbuf);
262 static void node_composit_init_image(bNode* node)
264 ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
265 node->storage= iuser;
272 bNodeType cmp_node_image= {
273 /* *next,*prev */ NULL, NULL,
274 /* type code */ CMP_NODE_IMAGE,
276 /* width+range */ 120, 80, 300,
277 /* class+opts */ NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
278 /* input sock */ NULL,
279 /* output sock */ cmp_node_rlayers_out,
280 /* storage */ "ImageUser",
281 /* execfunc */ node_composit_exec_image,
283 /* initfunc */ node_composit_init_image,
284 /* freestoragefunc */ node_free_standard_storage,
285 /* copystoragefunc */ node_copy_standard_storage,
289 /* **************** RENDER RESULT ******************** */
291 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
293 float *fp= RE_RenderLayerGetPass(rl, passcode);
296 int buftype= CB_VEC3;
298 if(ELEM3(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST))
300 else if(passcode==SCE_PASS_VECTOR)
302 else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
305 if(rd->scemode & R_COMP_CROP)
306 buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
308 buf= alloc_compbuf(rectx, recty, buftype, 0);
316 void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
318 if(out[RRES_OUT_Z]->hasoutput)
319 out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
320 if(out[RRES_OUT_VEC]->hasoutput)
321 out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
322 if(out[RRES_OUT_NORMAL]->hasoutput)
323 out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
324 if(out[RRES_OUT_UV]->hasoutput)
325 out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
327 if(out[RRES_OUT_RGBA]->hasoutput)
328 out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
329 if(out[RRES_OUT_DIFF]->hasoutput)
330 out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
331 if(out[RRES_OUT_SPEC]->hasoutput)
332 out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
333 if(out[RRES_OUT_SHADOW]->hasoutput)
334 out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
335 if(out[RRES_OUT_AO]->hasoutput)
336 out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
337 if(out[RRES_OUT_REFLECT]->hasoutput)
338 out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
339 if(out[RRES_OUT_REFRACT]->hasoutput)
340 out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
341 if(out[RRES_OUT_RADIO]->hasoutput)
342 out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO);
343 if(out[RRES_OUT_INDEXOB]->hasoutput)
344 out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
345 if(out[RRES_OUT_MIST]->hasoutput)
346 out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
350 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
352 Scene *sce= (Scene *)node->id;
353 RenderData *rd= data;
354 RenderResult *rr= NULL;
357 rr= RE_GetResult(RE_GetRender(sce->id.name));
360 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
362 RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
363 if(rl && rl->rectf) {
366 /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
367 if(rd->scemode & R_COMP_CROP)
368 stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
370 stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
371 stackbuf->rect= rl->rectf;
374 printf("Error; Preview Panel in UV Window returns zero sized image\n");
377 stackbuf->xof= rr->xof;
378 stackbuf->yof= rr->yof;
381 out[RRES_OUT_IMAGE]->data= stackbuf;
383 if(out[RRES_OUT_ALPHA]->hasoutput)
384 out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
386 node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
388 generate_preview(node, stackbuf);
396 bNodeType cmp_node_rlayers= {
397 /* *next,*prev */ NULL, NULL,
398 /* type code */ CMP_NODE_R_LAYERS,
399 /* name */ "Render Layers",
400 /* width+range */ 150, 100, 300,
401 /* class+opts */ NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
402 /* input sock */ NULL,
403 /* output sock */ cmp_node_rlayers_out,
405 /* execfunc */ node_composit_exec_rlayers,
408 /* freestoragefunc */ NULL,
409 /* copystoragefunc */ NULL,