Blender V2.61 - r43446
|
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 }