|
|
|
|
@@ -32,7 +32,6 @@
|
|
|
|
|
|
|
|
|
|
#include "node_composite_util.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
|
|
|
|
|
|
|
|
|
|
static bNodeSocketTemplate cmp_node_rlayers_out[]= {
|
|
|
|
|
@@ -67,6 +66,212 @@ static bNodeSocketTemplate cmp_node_rlayers_out[]= {
|
|
|
|
|
{ -1, 0, "" }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int UNUSED(pass), int rres_index)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
|
|
|
|
|
sock = node_add_output_from_template(ntree, node, &cmp_node_rlayers_out[rres_index]);
|
|
|
|
|
/* for render pass outputs store the pass type index as a lookup key */
|
|
|
|
|
sock->storage = SET_INT_IN_POINTER(rres_index);
|
|
|
|
|
|
|
|
|
|
return sock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag)
|
|
|
|
|
{
|
|
|
|
|
if (passflag & SCE_PASS_COMBINED) {
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE);
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (passflag & SCE_PASS_Z)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z);
|
|
|
|
|
if (passflag & SCE_PASS_NORMAL)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL);
|
|
|
|
|
if (passflag & SCE_PASS_VECTOR)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC);
|
|
|
|
|
if (passflag & SCE_PASS_UV)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV);
|
|
|
|
|
if (passflag & SCE_PASS_RGBA)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA);
|
|
|
|
|
if (passflag & SCE_PASS_DIFFUSE)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF);
|
|
|
|
|
if (passflag & SCE_PASS_SPEC)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC);
|
|
|
|
|
if (passflag & SCE_PASS_SHADOW)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW);
|
|
|
|
|
if (passflag & SCE_PASS_AO)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO);
|
|
|
|
|
if (passflag & SCE_PASS_REFLECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT);
|
|
|
|
|
if (passflag & SCE_PASS_REFRACT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT);
|
|
|
|
|
if (passflag & SCE_PASS_INDIRECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT);
|
|
|
|
|
if (passflag & SCE_PASS_INDEXOB)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB);
|
|
|
|
|
if (passflag & SCE_PASS_INDEXMA)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA);
|
|
|
|
|
if (passflag & SCE_PASS_MIST)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST);
|
|
|
|
|
if (passflag & SCE_PASS_EMIT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT);
|
|
|
|
|
if (passflag & SCE_PASS_ENVIRONMENT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV);
|
|
|
|
|
|
|
|
|
|
if (passflag & SCE_PASS_DIFFUSE_DIRECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT);
|
|
|
|
|
if (passflag & SCE_PASS_DIFFUSE_INDIRECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT);
|
|
|
|
|
if (passflag & SCE_PASS_DIFFUSE_COLOR)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR);
|
|
|
|
|
|
|
|
|
|
if (passflag & SCE_PASS_GLOSSY_DIRECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT);
|
|
|
|
|
if (passflag & SCE_PASS_GLOSSY_INDIRECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT);
|
|
|
|
|
if (passflag & SCE_PASS_GLOSSY_COLOR)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR);
|
|
|
|
|
|
|
|
|
|
if (passflag & SCE_PASS_TRANSM_DIRECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT);
|
|
|
|
|
if (passflag & SCE_PASS_TRANSM_INDIRECT)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
|
|
|
|
|
if (passflag & SCE_PASS_TRANSM_COLOR)
|
|
|
|
|
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
RenderPass *rpass;
|
|
|
|
|
int index;
|
|
|
|
|
for (rpass=rl->passes.first, index=0; rpass; rpass=rpass->next, ++index) {
|
|
|
|
|
int type;
|
|
|
|
|
if (rpass->channels == 1)
|
|
|
|
|
type = SOCK_FLOAT;
|
|
|
|
|
else
|
|
|
|
|
type = SOCK_RGBA;
|
|
|
|
|
|
|
|
|
|
sock = nodeAddSocket(ntree, node, SOCK_OUT, rpass->name, type);
|
|
|
|
|
/* for multilayer image use pass index directly as key */
|
|
|
|
|
sock->storage = SET_INT_IN_POINTER(index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
Image *ima= (Image *)node->id;
|
|
|
|
|
if (ima) {
|
|
|
|
|
ImageUser *iuser= node->storage;
|
|
|
|
|
|
|
|
|
|
/* make sure ima->type is correct */
|
|
|
|
|
BKE_image_get_ibuf(ima, iuser);
|
|
|
|
|
|
|
|
|
|
if (ima->rr) {
|
|
|
|
|
RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
|
|
|
|
|
|
|
|
|
|
if (rl) {
|
|
|
|
|
if (ima->type!=IMA_TYPE_MULTILAYER)
|
|
|
|
|
cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag);
|
|
|
|
|
else
|
|
|
|
|
cmp_node_image_add_multilayer_outputs(ntree, node, rl);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
|
|
|
|
|
for (sock=oldsocklist->first; sock; sock=sock->next)
|
|
|
|
|
if (strcmp(sock->name, newsock->name)==0)
|
|
|
|
|
return sock;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
|
|
|
|
|
/* first try to find matching socket name */
|
|
|
|
|
for (sock=node->outputs.first; sock; sock=sock->next)
|
|
|
|
|
if (strcmp(sock->name, oldsock->name)==0)
|
|
|
|
|
return sock;
|
|
|
|
|
|
|
|
|
|
/* no matching name, simply link to same index */
|
|
|
|
|
return BLI_findlink(&node->outputs, oldindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
|
|
|
|
|
{
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
|
|
|
|
|
static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *newsock, *oldsock, *oldsock_next;
|
|
|
|
|
ListBase oldsocklist;
|
|
|
|
|
int oldindex;
|
|
|
|
|
bNodeLink *link;
|
|
|
|
|
|
|
|
|
|
/* store current nodes in oldsocklist, then clear socket list */
|
|
|
|
|
oldsocklist = node->outputs;
|
|
|
|
|
node->outputs.first = node->outputs.last = NULL;
|
|
|
|
|
|
|
|
|
|
/* XXX make callback */
|
|
|
|
|
cmp_node_image_create_outputs(ntree, node);
|
|
|
|
|
/* flag all new sockets as dynamic, to prevent removal by socket verification function */
|
|
|
|
|
for (newsock=node->outputs.first; newsock; newsock=newsock->next)
|
|
|
|
|
newsock->flag |= SOCK_DYNAMIC;
|
|
|
|
|
|
|
|
|
|
for (newsock=node->outputs.first; newsock; newsock=newsock->next) {
|
|
|
|
|
/* XXX make callback */
|
|
|
|
|
oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
|
|
|
|
|
if (oldsock) {
|
|
|
|
|
/* XXX make callback */
|
|
|
|
|
cmp_node_image_sync_output(node, newsock, oldsock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* move links to new socket */
|
|
|
|
|
for (oldsock=oldsocklist.first, oldindex=0; oldsock; oldsock=oldsock->next, ++oldindex) {
|
|
|
|
|
newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
|
|
|
|
|
|
|
|
|
|
if (newsock) {
|
|
|
|
|
for (link=ntree->links.first; link; link=link->next) {
|
|
|
|
|
if (link->fromsock == oldsock)
|
|
|
|
|
link->fromsock = newsock;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* delete old sockets
|
|
|
|
|
* XXX oldsock is not actually in the node->outputs list any more,
|
|
|
|
|
* but the nodeRemoveSocket function works anyway. In future this
|
|
|
|
|
* should become part of the core code, so can take care of this behavior.
|
|
|
|
|
*/
|
|
|
|
|
for (oldsock=oldsocklist.first; oldsock; oldsock=oldsock_next) {
|
|
|
|
|
oldsock_next = oldsock->next;
|
|
|
|
|
nodeRemoveSocket(ntree, node, oldsock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
/* avoid unnecessary updates, only changes to the image/image user data are of interest */
|
|
|
|
|
if (node->update & NODE_UPDATE_ID)
|
|
|
|
|
cmp_node_image_verify_outputs(ntree, node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* float buffer from the image with matching color management */
|
|
|
|
|
float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
|
|
|
|
|
{
|
|
|
|
|
@@ -189,85 +394,21 @@ static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check if layer is available, returns pass buffer */
|
|
|
|
|
static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype)
|
|
|
|
|
static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passindex)
|
|
|
|
|
{
|
|
|
|
|
RenderPass *rpass;
|
|
|
|
|
short index;
|
|
|
|
|
|
|
|
|
|
for (index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++)
|
|
|
|
|
if (rpass->passtype==passtype)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
RenderPass *rpass = BLI_findlink(&rl->passes, passindex);
|
|
|
|
|
if (rpass) {
|
|
|
|
|
CompBuf *cbuf;
|
|
|
|
|
|
|
|
|
|
iuser->pass= index;
|
|
|
|
|
iuser->pass = passindex;
|
|
|
|
|
BKE_image_multilayer_index(ima->rr, iuser);
|
|
|
|
|
cbuf= node_composit_get_image(rd, ima, iuser);
|
|
|
|
|
cbuf = node_composit_get_image(rd, ima, iuser);
|
|
|
|
|
|
|
|
|
|
return cbuf;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser)
|
|
|
|
|
{
|
|
|
|
|
if (out[RRES_OUT_Z]->hasoutput)
|
|
|
|
|
out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z);
|
|
|
|
|
if (out[RRES_OUT_VEC]->hasoutput)
|
|
|
|
|
out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR);
|
|
|
|
|
if (out[RRES_OUT_NORMAL]->hasoutput)
|
|
|
|
|
out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL);
|
|
|
|
|
if (out[RRES_OUT_UV]->hasoutput)
|
|
|
|
|
out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV);
|
|
|
|
|
|
|
|
|
|
if (out[RRES_OUT_RGBA]->hasoutput)
|
|
|
|
|
out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA);
|
|
|
|
|
if (out[RRES_OUT_DIFF]->hasoutput)
|
|
|
|
|
out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE);
|
|
|
|
|
if (out[RRES_OUT_SPEC]->hasoutput)
|
|
|
|
|
out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC);
|
|
|
|
|
if (out[RRES_OUT_SHADOW]->hasoutput)
|
|
|
|
|
out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW);
|
|
|
|
|
if (out[RRES_OUT_AO]->hasoutput)
|
|
|
|
|
out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO);
|
|
|
|
|
if (out[RRES_OUT_REFLECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT);
|
|
|
|
|
if (out[RRES_OUT_REFRACT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT);
|
|
|
|
|
if (out[RRES_OUT_INDIRECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDIRECT);
|
|
|
|
|
if (out[RRES_OUT_INDEXOB]->hasoutput)
|
|
|
|
|
out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
|
|
|
|
|
if (out[RRES_OUT_INDEXMA]->hasoutput)
|
|
|
|
|
out[RRES_OUT_INDEXMA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXMA);
|
|
|
|
|
if (out[RRES_OUT_MIST]->hasoutput)
|
|
|
|
|
out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST);
|
|
|
|
|
if (out[RRES_OUT_EMIT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_EMIT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_EMIT);
|
|
|
|
|
if (out[RRES_OUT_ENV]->hasoutput)
|
|
|
|
|
out[RRES_OUT_ENV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_ENVIRONMENT);
|
|
|
|
|
if (out[RRES_OUT_DIFF_DIRECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_DIFF_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_DIRECT);
|
|
|
|
|
if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_INDIRECT);
|
|
|
|
|
if (out[RRES_OUT_DIFF_COLOR]->hasoutput)
|
|
|
|
|
out[RRES_OUT_DIFF_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_COLOR);
|
|
|
|
|
if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_DIRECT);
|
|
|
|
|
if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_INDIRECT);
|
|
|
|
|
if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput)
|
|
|
|
|
out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_COLOR);
|
|
|
|
|
if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_DIRECT);
|
|
|
|
|
if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput)
|
|
|
|
|
out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_INDIRECT);
|
|
|
|
|
if (out[RRES_OUT_TRANSM_COLOR]->hasoutput)
|
|
|
|
|
out[RRES_OUT_TRANSM_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_COLOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
@@ -277,7 +418,6 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE
|
|
|
|
|
RenderData *rd= data;
|
|
|
|
|
Image *ima= (Image *)node->id;
|
|
|
|
|
ImageUser *iuser= (ImageUser *)node->storage;
|
|
|
|
|
CompBuf *stackbuf= NULL;
|
|
|
|
|
|
|
|
|
|
/* first set the right frame number in iuser */
|
|
|
|
|
BKE_image_user_calc_frame(iuser, rd->cfra, 0);
|
|
|
|
|
@@ -290,15 +430,36 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE
|
|
|
|
|
RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
|
|
|
|
|
|
|
|
|
|
if (rl) {
|
|
|
|
|
out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED);
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
int out_index;
|
|
|
|
|
CompBuf *combinedbuf= NULL, *firstbuf= NULL;
|
|
|
|
|
|
|
|
|
|
/* go over all layers */
|
|
|
|
|
outputs_multilayer_get(rd, rl, out, ima, iuser);
|
|
|
|
|
for (sock=node->outputs.first, out_index=0; sock; sock=sock->next, ++out_index) {
|
|
|
|
|
int passindex = GET_INT_FROM_POINTER(sock->storage);
|
|
|
|
|
if (out[out_index]->hasoutput) {
|
|
|
|
|
CompBuf *stackbuf = out[out_index]->data = compbuf_multilayer_get(rd, rl, ima, iuser, passindex);
|
|
|
|
|
if (stackbuf) {
|
|
|
|
|
/* preview policy: take first 'Combined' pass if available,
|
|
|
|
|
* otherwise just use the first layer.
|
|
|
|
|
*/
|
|
|
|
|
if (!firstbuf)
|
|
|
|
|
firstbuf = stackbuf;
|
|
|
|
|
if (!combinedbuf &&
|
|
|
|
|
(strcmp(sock->name, "Combined")==0 || strcmp(sock->name, "Image")==0))
|
|
|
|
|
combinedbuf = stackbuf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* preview */
|
|
|
|
|
if (combinedbuf)
|
|
|
|
|
generate_preview(data, node, combinedbuf);
|
|
|
|
|
else if (firstbuf)
|
|
|
|
|
generate_preview(data, node, firstbuf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
stackbuf= node_composit_get_image(rd, ima, iuser);
|
|
|
|
|
|
|
|
|
|
CompBuf *stackbuf = node_composit_get_image(rd, ima, iuser);
|
|
|
|
|
if (stackbuf) {
|
|
|
|
|
/*respect image premul option*/
|
|
|
|
|
if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
|
|
|
|
|
@@ -324,23 +485,23 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE
|
|
|
|
|
|
|
|
|
|
/* put image on stack */
|
|
|
|
|
out[0]->data= stackbuf;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* alpha output */
|
|
|
|
|
if (out[1]->hasoutput)
|
|
|
|
|
out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
|
|
|
|
|
|
|
|
|
|
/* Z output */
|
|
|
|
|
if (out[2]->hasoutput)
|
|
|
|
|
out[2]->data= node_composit_get_zimage(node, rd);
|
|
|
|
|
|
|
|
|
|
/* preview */
|
|
|
|
|
generate_preview(data, node, stackbuf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* alpha and preview for both types */
|
|
|
|
|
if (stackbuf) {
|
|
|
|
|
if (out[1]->hasoutput)
|
|
|
|
|
out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
|
|
|
|
|
|
|
|
|
|
generate_preview(data, node, stackbuf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void node_composit_init_image(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
|
|
|
|
|
static void node_composit_init_image(bNodeTree *ntree, bNode* node, bNodeTemplate *UNUSED(ntemp))
|
|
|
|
|
{
|
|
|
|
|
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
|
|
|
|
|
node->storage= iuser;
|
|
|
|
|
@@ -348,6 +509,9 @@ static void node_composit_init_image(bNodeTree *UNUSED(ntree), bNode* node, bNod
|
|
|
|
|
iuser->sfra= 1;
|
|
|
|
|
iuser->fie_ima= 2;
|
|
|
|
|
iuser->ok= 1;
|
|
|
|
|
|
|
|
|
|
/* setup initial outputs */
|
|
|
|
|
cmp_node_image_verify_outputs(ntree, node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void register_node_type_cmp_image(bNodeTreeType *ttype)
|
|
|
|
|
@@ -355,10 +519,10 @@ void register_node_type_cmp_image(bNodeTreeType *ttype)
|
|
|
|
|
static bNodeType ntype;
|
|
|
|
|
|
|
|
|
|
node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
|
|
|
|
|
node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
|
|
|
|
|
node_type_size(&ntype, 120, 80, 300);
|
|
|
|
|
node_type_init(&ntype, node_composit_init_image);
|
|
|
|
|
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
|
|
|
|
|
node_type_update(&ntype, cmp_node_image_update, NULL);
|
|
|
|
|
node_type_exec(&ntype, node_composit_exec_image);
|
|
|
|
|
|
|
|
|
|
nodeRegisterType(ttype, &ntype);
|
|
|
|
|
@@ -449,6 +613,8 @@ static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStac
|
|
|
|
|
out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
|
|
|
|
|
{
|
|
|
|
|
Scene *sce= (Scene *)node->id;
|
|
|
|
|
|