features & fixes:
- Enabled Groups to execute in Compositor. They were ignored still. Note; inside of groups nothing is cached, so a change of a group input will recalculate it fully. This is needed because groups are linked data (instances use same internal nodes). - Made Composit node "Viewer" display correctly input for images with 1/2/3/4 channels. - Added pass rendering, tested now with only regular Materials. For Material nodes this is quite more complex... since they cannot be easily separated in passes (each Material does a full shade) In this commit all pass render is disabled though, will continue work on that later. Sneak preview: http://www.blender.org/bf/rt.jpg (temporal image) - What did remain is the 'Normal' pass output. Normal works very nice for relighting effects. Use the "Normal Node" to define where more or less light should be. (Use "Value Map" node to tweak influence of the Normal node 'dot' output.) - EVIL bug fix: I've spend almost a day finding it... when combining AO and mirror render, the event queue was totally screwing up... two things not related at all! Found out error was in ray-mirror code, which was using partially uninitialized 'ShadeInput' data to pass on to render code. - Another fix; made sure that while thread render, the threads don't get events, only the main program will do. Might fix issues reported by people on linux/windows.
This commit is contained in:
@@ -1243,7 +1243,7 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
if(ntree->type==NTREE_COMPOSIT) {
|
||||
bNodeSocket *sock;
|
||||
|
||||
|
||||
for(sock= node->outputs.first; sock; sock= sock->next) {
|
||||
if(sock->ns.data) {
|
||||
free_compbuf(sock->ns.data);
|
||||
@@ -1447,14 +1447,35 @@ static void composit_end_exec(bNodeTree *ntree)
|
||||
}
|
||||
node->need_exec= 0;
|
||||
}
|
||||
|
||||
|
||||
/* internally, group buffers are not stored */
|
||||
for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) {
|
||||
if(ns->data) {
|
||||
print_compbuf("error: buf hanging in stack", ns->data);
|
||||
if(ns->data)
|
||||
free_compbuf(ns->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack)
|
||||
{
|
||||
bNodeTree *ntree= (bNodeTree *)gnode->id;
|
||||
bNode *node;
|
||||
|
||||
stack+= gnode->stack_index;
|
||||
|
||||
for(node= ntree->nodes.first; node; node= node->next) {
|
||||
if(node->typeinfo->execfunc) {
|
||||
bNodeSocket *sock;
|
||||
|
||||
for(sock= node->inputs.first; sock; sock= sock->next) {
|
||||
if(sock->intern) {
|
||||
if(sock->link) {
|
||||
bNodeStack *ns= stack + sock->link->fromsock->stack_index;
|
||||
ns->hasoutput= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* stack indices make sure all nodes only write in allocated data, for making it thread safe */
|
||||
@@ -1481,7 +1502,6 @@ void ntreeBeginExecTree(bNodeTree *ntree)
|
||||
for(a=0; a<ntree->stacksize; a++, ns++) ns->hasinput= 1;
|
||||
|
||||
/* tag used outputs, so we know when we can skip operations */
|
||||
/* hrms... groups... */
|
||||
for(node= ntree->nodes.first; node; node= node->next) {
|
||||
bNodeSocket *sock;
|
||||
for(sock= node->inputs.first; sock; sock= sock->next) {
|
||||
@@ -1490,6 +1510,8 @@ void ntreeBeginExecTree(bNodeTree *ntree)
|
||||
ns->hasoutput= 1;
|
||||
}
|
||||
}
|
||||
if(node->type==NODE_GROUP && node->id)
|
||||
group_tag_used_outputs(node, ntree->stack);
|
||||
}
|
||||
if(ntree->type==NTREE_COMPOSIT)
|
||||
composit_begin_exec(ntree);
|
||||
@@ -1610,48 +1632,46 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd)
|
||||
int totnode= 0;
|
||||
|
||||
for(node= ntree->nodes.first; node; node= node->next) {
|
||||
if(node->typeinfo->execfunc) {
|
||||
int a;
|
||||
|
||||
node_get_stack(node, thd->stack, nsin, nsout);
|
||||
|
||||
/* test the inputs */
|
||||
for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
|
||||
/* is sock in use? */
|
||||
if(sock->link) {
|
||||
if(nsin[a]->data==NULL || sock->link->fromnode->need_exec) {
|
||||
node->need_exec= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* test the outputs */
|
||||
for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
|
||||
if(nsout[a]->data==NULL && nsout[a]->hasoutput) {
|
||||
int a;
|
||||
|
||||
node_get_stack(node, thd->stack, nsin, nsout);
|
||||
|
||||
/* test the inputs */
|
||||
for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
|
||||
/* is sock in use? */
|
||||
if(sock->link) {
|
||||
if(nsin[a]->data==NULL || sock->link->fromnode->need_exec) {
|
||||
node->need_exec= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(node->need_exec) {
|
||||
|
||||
/* free output buffers */
|
||||
for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
|
||||
if(nsout[a]->data) {
|
||||
free_compbuf(nsout[a]->data);
|
||||
nsout[a]->data= NULL;
|
||||
}
|
||||
}
|
||||
totnode++;
|
||||
//printf("node needs exec %s\n", node->name);
|
||||
|
||||
/* tag for getExecutableNode() */
|
||||
node->exec= 0;
|
||||
}
|
||||
else
|
||||
/* tag for getExecutableNode() */
|
||||
node->exec= NODE_READY|NODE_FINISHED;
|
||||
}
|
||||
|
||||
/* test the outputs */
|
||||
for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
|
||||
if(nsout[a]->data==NULL && nsout[a]->hasoutput) {
|
||||
node->need_exec= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(node->need_exec) {
|
||||
|
||||
/* free output buffers */
|
||||
for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
|
||||
if(nsout[a]->data) {
|
||||
free_compbuf(nsout[a]->data);
|
||||
nsout[a]->data= NULL;
|
||||
}
|
||||
}
|
||||
totnode++;
|
||||
//printf("node needs exec %s\n", node->name);
|
||||
|
||||
/* tag for getExecutableNode() */
|
||||
node->exec= 0;
|
||||
}
|
||||
else
|
||||
/* tag for getExecutableNode() */
|
||||
node->exec= NODE_READY|NODE_FINISHED;
|
||||
}
|
||||
return totnode;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user