Blender V2.61 - r43446

node_shader_tree.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2007 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s):
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <string.h>
00034 
00035 #include "DNA_lamp_types.h"
00036 #include "DNA_material_types.h"
00037 #include "DNA_node_types.h"
00038 #include "DNA_scene_types.h"
00039 #include "DNA_world_types.h"
00040 
00041 #include "BLI_listbase.h"
00042 #include "BLI_math.h"
00043 #include "BLI_threads.h"
00044 #include "BLI_utildefines.h"
00045 
00046 #include "BLF_translation.h"
00047 
00048 #include "BKE_global.h"
00049 #include "BKE_main.h"
00050 #include "BKE_node.h"
00051 #include "BKE_scene.h"
00052 #include "BKE_utildefines.h"
00053 
00054 #include "GPU_material.h"
00055 
00056 #include "RE_shader_ext.h"
00057 
00058 #include "node_exec.h"
00059 #include "node_util.h"
00060 #include "node_shader_util.h"
00061 
00062 static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
00063 {
00064     Material *ma;
00065     Lamp *la;
00066     World *wo;
00067 
00068     for(ma= main->mat.first; ma; ma= ma->id.next)
00069         if(ma->nodetree)
00070             func(calldata, &ma->id, ma->nodetree);
00071 
00072     for(la= main->lamp.first; la; la= la->id.next)
00073         if(la->nodetree)
00074             func(calldata, &la->id, la->nodetree);
00075 
00076     for(wo= main->world.first; wo; wo= wo->id.next)
00077         if(wo->nodetree)
00078             func(calldata, &wo->id, wo->nodetree);
00079 }
00080 
00081 static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func)
00082 {
00083     func(calldata, NODE_CLASS_INPUT, IFACE_("Input"));
00084     func(calldata, NODE_CLASS_OUTPUT, IFACE_("Output"));
00085 
00086     if(scene_use_new_shading_nodes(scene)) {
00087         func(calldata, NODE_CLASS_SHADER, IFACE_("Shader"));
00088         func(calldata, NODE_CLASS_TEXTURE, IFACE_("Texture"));
00089     }
00090 
00091     func(calldata, NODE_CLASS_OP_COLOR, IFACE_("Color"));
00092     func(calldata, NODE_CLASS_OP_VECTOR, IFACE_("Vector"));
00093     func(calldata, NODE_CLASS_CONVERTOR, IFACE_("Convertor"));
00094     func(calldata, NODE_CLASS_GROUP, IFACE_("Group"));
00095     func(calldata, NODE_CLASS_LAYOUT, IFACE_("Layout"));
00096 }
00097 
00098 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
00099 {
00100     bNode *lnode;
00101     
00102     /* copy over contents of previews */
00103     for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
00104         if(ntreeNodeExists(ntree, lnode->new_node)) {
00105             bNode *node= lnode->new_node;
00106             
00107             if(node->preview && node->preview->rect) {
00108                 if(lnode->preview && lnode->preview->rect) {
00109                     int xsize= node->preview->xsize;
00110                     int ysize= node->preview->ysize;
00111                     memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4);
00112                 }
00113             }
00114         }
00115     }
00116 }
00117 
00118 static void update(bNodeTree *ntree)
00119 {
00120     ntreeSetOutput(ntree);
00121 }
00122 
00123 bNodeTreeType ntreeType_Shader = {
00124     /* type */              NTREE_SHADER,
00125     /* id_name */           "NTShader Nodetree",
00126     
00127     /* node_types */        { NULL, NULL },
00128     
00129     /* free_cache */        NULL,
00130     /* free_node_cache */   NULL,
00131     /* foreach_nodetree */  foreach_nodetree,
00132     /* foreach_nodeclass */ foreach_nodeclass,
00133     /* localize */          NULL,
00134     /* local_sync */        local_sync,
00135     /* local_merge */       NULL,
00136     /* update */            update,
00137     /* update_node */       NULL,
00138     /* validate_link */     NULL,
00139     /* mute node */         node_shader_pass_on,
00140     /* mute links node */   node_mute_get_links,
00141     /* gpu mute node */     gpu_shader_pass_on
00142 };
00143 
00144 /* GPU material from shader nodes */
00145 
00146 void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
00147 {
00148     bNodeTreeExec *exec;
00149 
00150     exec = ntreeShaderBeginExecTree(ntree, 1);
00151 
00152     ntreeExecGPUNodes(exec, mat, 1);
00153 
00154     ntreeShaderEndExecTree(exec, 1);
00155 }
00156 
00157 /* **************** call to switch lamploop for material node ************ */
00158 
00159 void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
00160 
00161 void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *))
00162 {
00163     node_shader_lamp_loop= lamp_loop_func;
00164 }
00165 
00166 
00167 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
00168  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
00169  */
00170 bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
00171 {
00172     bNodeTreeExec *exec;
00173     bNode *node;
00174     
00175     if (use_tree_data) {
00176         /* XXX hack: prevent exec data from being generated twice.
00177          * this should be handled by the renderer!
00178          */
00179         if (ntree->execdata)
00180             return ntree->execdata;
00181     }
00182     
00183     /* ensures only a single output node is enabled */
00184     ntreeSetOutput(ntree);
00185     
00186     /* common base initialization */
00187     exec = ntree_exec_begin(ntree);
00188     
00189     /* allocate the thread stack listbase array */
00190     exec->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array");
00191     
00192     for(node= exec->nodetree->nodes.first; node; node= node->next)
00193         node->need_exec= 1;
00194     
00195     if (use_tree_data) {
00196         /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
00197          * which only store the ntree pointer. Should be fixed at some point!
00198          */
00199         ntree->execdata = exec;
00200     }
00201     
00202     return exec;
00203 }
00204 
00205 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
00206  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
00207  */
00208 void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data)
00209 {
00210     if(exec) {
00211         bNodeTree *ntree= exec->nodetree;
00212         bNodeThreadStack *nts;
00213         int a;
00214         
00215         if(exec->threadstack) {
00216             for(a=0; a<BLENDER_MAX_THREADS; a++) {
00217                 for(nts=exec->threadstack[a].first; nts; nts=nts->next)
00218                     if (nts->stack) MEM_freeN(nts->stack);
00219                 BLI_freelistN(&exec->threadstack[a]);
00220             }
00221             
00222             MEM_freeN(exec->threadstack);
00223             exec->threadstack= NULL;
00224         }
00225         
00226         ntree_exec_end(exec);
00227         
00228         if (use_tree_data) {
00229             /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
00230             ntree->execdata = NULL;
00231         }
00232     }
00233 }
00234 
00235 void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
00236 {
00237     ShaderCallData scd;
00238     /*
00239     @note: preserve material from ShadeInput for material id, nodetree execs change it
00240     fix for bug "[#28012] Mat ID messy with shader nodes"
00241     */
00242     Material *mat = shi->mat;
00243     bNodeThreadStack *nts = NULL;
00244     bNodeTreeExec *exec = ntree->execdata;
00245     
00246     /* convert caller data to struct */
00247     scd.shi= shi;
00248     scd.shr= shr;
00249     
00250     /* each material node has own local shaderesult, with optional copying */
00251     memset(shr, 0, sizeof(ShadeResult));
00252     
00253     /* ensure execdata is only initialized once */
00254     if (!exec) {
00255         BLI_lock_thread(LOCK_NODES);
00256         if(!ntree->execdata)
00257             ntree->execdata = ntreeShaderBeginExecTree(ntree, 1);
00258         BLI_unlock_thread(LOCK_NODES);
00259 
00260         exec = ntree->execdata;
00261     }
00262     
00263     nts= ntreeGetThreadStack(exec, shi->thread);
00264     ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
00265     ntreeReleaseThreadStack(nts);
00266     
00267     // @note: set material back to preserved material
00268     shi->mat = mat;
00269     /* better not allow negative for now */
00270     if(shr->combined[0]<0.0f) shr->combined[0]= 0.0f;
00271     if(shr->combined[1]<0.0f) shr->combined[1]= 0.0f;
00272     if(shr->combined[2]<0.0f) shr->combined[2]= 0.0f;
00273 }