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) 2005 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include "DNA_node_types.h" 00034 00035 #include "node_shader_util.h" 00036 00037 #include "node_exec.h" 00038 00039 /* ****** */ 00040 00041 void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) 00042 { 00043 float *from= ns->vec; 00044 00045 if(type_in==SOCK_FLOAT) { 00046 if(ns->sockettype==SOCK_FLOAT) 00047 *in= *from; 00048 else 00049 *in= 0.333333f*(from[0]+from[1]+from[2]); 00050 } 00051 else if(type_in==SOCK_VECTOR) { 00052 if(ns->sockettype==SOCK_FLOAT) { 00053 in[0]= from[0]; 00054 in[1]= from[0]; 00055 in[2]= from[0]; 00056 } 00057 else { 00058 copy_v3_v3(in, from); 00059 } 00060 } 00061 else { /* type_in==SOCK_RGBA */ 00062 if(ns->sockettype==SOCK_RGBA) { 00063 copy_v4_v4(in, from); 00064 } 00065 else if(ns->sockettype==SOCK_FLOAT) { 00066 in[0]= from[0]; 00067 in[1]= from[0]; 00068 in[2]= from[0]; 00069 in[3]= 1.0f; 00070 } 00071 else { 00072 copy_v3_v3(in, from); 00073 in[3]= 1.0f; 00074 } 00075 } 00076 } 00077 00078 00079 /* ******************* execute and parse ************ */ 00080 00081 /* Used for muted nodes, just copy the vec data from input to output… */ 00082 void node_shader_pass_on(void *UNUSED(data), int UNUSED(thread), struct bNode *node, void *UNUSED(nodedata), 00083 struct bNodeStack **in, struct bNodeStack **out) 00084 { 00085 ListBase links; 00086 LinkInOutsMuteNode *lnk; 00087 int i; 00088 00089 if(node->typeinfo->mutelinksfunc == NULL) 00090 return; 00091 00092 /* Get default muting links (as bNodeStack pointers). */ 00093 links = node->typeinfo->mutelinksfunc(NULL, node, in, out, NULL, NULL); 00094 00095 for(lnk = links.first; lnk; lnk = lnk->next) { 00096 for(i = 0; i < lnk->num_outs; i++) { 00097 copy_v4_v4((((bNodeStack*)(lnk->outs))+i)->vec, ((bNodeStack*)(lnk->in))->vec); 00098 } 00099 /* If num_outs > 1, lnk->outs was an allocated table of pointers... */ 00100 if(i > 1) 00101 MEM_freeN(lnk->outs); 00102 } 00103 BLI_freelistN(&links); 00104 } 00105 00106 int gpu_shader_pass_on(struct GPUMaterial *mat, struct bNode *node, void *UNUSED(nodedata), 00107 struct GPUNodeStack *in, struct GPUNodeStack *out) 00108 { 00109 ListBase links; 00110 LinkInOutsMuteNode *lnk; 00111 00112 if(node->typeinfo->mutelinksfunc == NULL) 00113 return 0; 00114 00115 /* Get default muting links (as GPUNodeStack pointers). */ 00116 links = node->typeinfo->mutelinksfunc(NULL, node, NULL, NULL, in, out); 00117 00118 for(lnk = links.first; lnk; lnk = lnk->next) { 00119 GPU_stack_link_mute(mat, "copy_raw", lnk); 00120 /* If num_outs > 1, lnk->outs was an allocated table of pointers... */ 00121 if(lnk->num_outs > 1) 00122 MEM_freeN(lnk->outs); 00123 } 00124 00125 BLI_freelistN(&links); 00126 return 1; 00127 } 00128 00129 /* go over all used Geometry and Texture nodes, and return a texco flag */ 00130 /* no group inside needed, this function is called for groups too */ 00131 void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mode) 00132 { 00133 bNode *node; 00134 bNodeSocket *sock; 00135 int a; 00136 00137 for(node= ntree->nodes.first; node; node= node->next) { 00138 if(node->type==SH_NODE_TEXTURE) { 00139 if((r_mode & R_OSA) && node->id) { 00140 Tex *tex= (Tex *)node->id; 00141 if ELEM3(tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) 00142 *texco |= TEXCO_OSA|NEED_UV; 00143 } 00144 /* usability exception... without input we still give the node orcos */ 00145 sock= node->inputs.first; 00146 if(sock==NULL || sock->link==NULL) 00147 *texco |= TEXCO_ORCO|NEED_UV; 00148 } 00149 else if(node->type==SH_NODE_GEOMETRY) { 00150 /* note; sockets always exist for the given type! */ 00151 for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { 00152 if(sock->flag & SOCK_IN_USE) { 00153 switch(a) { 00154 case GEOM_OUT_GLOB: 00155 *texco |= TEXCO_GLOB|NEED_UV; break; 00156 case GEOM_OUT_VIEW: 00157 *texco |= TEXCO_VIEW|NEED_UV; break; 00158 case GEOM_OUT_ORCO: 00159 *texco |= TEXCO_ORCO|NEED_UV; break; 00160 case GEOM_OUT_UV: 00161 *texco |= TEXCO_UV|NEED_UV; break; 00162 case GEOM_OUT_NORMAL: 00163 *texco |= TEXCO_NORM|NEED_UV; break; 00164 case GEOM_OUT_VCOL: 00165 *texco |= NEED_UV; *mode |= MA_VERTEXCOL; break; 00166 case GEOM_OUT_VCOL_ALPHA: 00167 *texco |= NEED_UV; *mode |= MA_VERTEXCOL; break; 00168 } 00169 } 00170 } 00171 } 00172 } 00173 } 00174 00175 /* nodes that use ID data get synced with local data */ 00176 void nodeShaderSynchronizeID(bNode *node, int copyto) 00177 { 00178 if(node->id==NULL) return; 00179 00180 if(ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) { 00181 bNodeSocket *sock; 00182 Material *ma= (Material *)node->id; 00183 int a; 00184 00185 /* hrmf, case in loop isnt super fast, but we dont edit 100s of material at same time either! */ 00186 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { 00187 if(!nodeSocketIsHidden(sock)) { 00188 if(copyto) { 00189 switch(a) { 00190 case MAT_IN_COLOR: 00191 copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA*)sock->default_value)->value); break; 00192 case MAT_IN_SPEC: 00193 copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break; 00194 case MAT_IN_REFL: 00195 ma->ref= ((bNodeSocketValueFloat*)sock->default_value)->value; break; 00196 case MAT_IN_MIR: 00197 copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break; 00198 case MAT_IN_AMB: 00199 ma->amb= ((bNodeSocketValueFloat*)sock->default_value)->value; break; 00200 case MAT_IN_EMIT: 00201 ma->emit= ((bNodeSocketValueFloat*)sock->default_value)->value; break; 00202 case MAT_IN_SPECTRA: 00203 ma->spectra= ((bNodeSocketValueFloat*)sock->default_value)->value; break; 00204 case MAT_IN_RAY_MIRROR: 00205 ma->ray_mirror= ((bNodeSocketValueFloat*)sock->default_value)->value; break; 00206 case MAT_IN_ALPHA: 00207 ma->alpha= ((bNodeSocketValueFloat*)sock->default_value)->value; break; 00208 case MAT_IN_TRANSLUCENCY: 00209 ma->translucency= ((bNodeSocketValueFloat*)sock->default_value)->value; break; 00210 } 00211 } 00212 else { 00213 switch(a) { 00214 case MAT_IN_COLOR: 00215 copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->r); break; 00216 case MAT_IN_SPEC: 00217 copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->specr); break; 00218 case MAT_IN_REFL: 00219 ((bNodeSocketValueFloat*)sock->default_value)->value= ma->ref; break; 00220 case MAT_IN_MIR: 00221 copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->mirr); break; 00222 case MAT_IN_AMB: 00223 ((bNodeSocketValueFloat*)sock->default_value)->value= ma->amb; break; 00224 case MAT_IN_EMIT: 00225 ((bNodeSocketValueFloat*)sock->default_value)->value= ma->emit; break; 00226 case MAT_IN_SPECTRA: 00227 ((bNodeSocketValueFloat*)sock->default_value)->value= ma->spectra; break; 00228 case MAT_IN_RAY_MIRROR: 00229 ((bNodeSocketValueFloat*)sock->default_value)->value= ma->ray_mirror; break; 00230 case MAT_IN_ALPHA: 00231 ((bNodeSocketValueFloat*)sock->default_value)->value= ma->alpha; break; 00232 case MAT_IN_TRANSLUCENCY: 00233 ((bNodeSocketValueFloat*)sock->default_value)->value= ma->translucency; break; 00234 } 00235 } 00236 } 00237 } 00238 } 00239 00240 } 00241 00242 00243 void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns) 00244 { 00245 memset(gs, 0, sizeof(*gs)); 00246 00247 copy_v4_v4(gs->vec, ns->vec); 00248 gs->link= ns->data; 00249 00250 if (type == SOCK_FLOAT) 00251 gs->type= GPU_FLOAT; 00252 else if (type == SOCK_VECTOR) 00253 gs->type= GPU_VEC3; 00254 else if (type == SOCK_RGBA) 00255 gs->type= GPU_VEC4; 00256 else if (type == SOCK_SHADER) 00257 gs->type= GPU_VEC4; 00258 else 00259 gs->type= GPU_NONE; 00260 00261 gs->name = ""; 00262 gs->hasinput= ns->hasinput && ns->data; 00263 /* XXX Commented out the ns->data check here, as it seems it’s not alwas set, 00264 * even though there *is* a valid connection/output... But that might need 00265 * further investigation. 00266 */ 00267 gs->hasoutput= ns->hasoutput /*&& ns->data*/; 00268 gs->sockettype= ns->sockettype; 00269 } 00270 00271 void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs) 00272 { 00273 ns->data= gs->link; 00274 ns->sockettype= gs->sockettype; 00275 } 00276 00277 static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeStack **ns) 00278 { 00279 bNodeSocket *sock; 00280 int i; 00281 00282 for (sock=sockets->first, i=0; sock; sock=sock->next, i++) 00283 node_gpu_stack_from_data(&gs[i], sock->type, ns[i]); 00284 00285 gs[i].type= GPU_NONE; 00286 } 00287 00288 static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) 00289 { 00290 bNodeSocket *sock; 00291 int i; 00292 00293 for (sock=sockets->first, i=0; sock; sock=sock->next, i++) 00294 node_data_from_gpu_stack(ns[i], &gs[i]); 00295 } 00296 00297 bNode *nodeGetActiveTexture(bNodeTree *ntree) 00298 { 00299 /* this is the node we texture paint and draw in textured draw */ 00300 bNode *node; 00301 00302 if(!ntree) 00303 return NULL; 00304 00305 /* check for group edit */ 00306 for(node= ntree->nodes.first; node; node= node->next) 00307 if(node->flag & NODE_GROUP_EDIT) 00308 break; 00309 00310 if(node) 00311 ntree= (bNodeTree*)node->id; 00312 00313 for(node= ntree->nodes.first; node; node= node->next) 00314 if(node->flag & NODE_ACTIVE_TEXTURE) 00315 return node; 00316 00317 return NULL; 00318 } 00319 00320 void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs) 00321 { 00322 bNodeExec *nodeexec; 00323 bNode *node; 00324 int n; 00325 bNodeStack *stack; 00326 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 00327 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ 00328 GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; 00329 int doit; 00330 00331 stack= exec->stack; 00332 00333 for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { 00334 node = nodeexec->node; 00335 00336 doit = 0; 00337 /* for groups, only execute outputs for edited group */ 00338 if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { 00339 if(do_outputs && (node->flag & NODE_DO_OUTPUT)) 00340 doit = 1; 00341 } 00342 else 00343 doit = 1; 00344 00345 if (doit) { 00346 if((node->flag & NODE_MUTED) && node->typeinfo->gpumutefunc) { 00347 node_get_stack(node, stack, nsin, nsout); 00348 gpu_stack_from_data_list(gpuin, &node->inputs, nsin); 00349 gpu_stack_from_data_list(gpuout, &node->outputs, nsout); 00350 if(node->typeinfo->gpumutefunc(mat, node, nodeexec->data, gpuin, gpuout)) 00351 data_from_gpu_stack_list(&node->outputs, nsout, gpuout); 00352 } 00353 else if(node->typeinfo->gpufunc) { 00354 node_get_stack(node, stack, nsin, nsout); 00355 gpu_stack_from_data_list(gpuin, &node->inputs, nsin); 00356 gpu_stack_from_data_list(gpuout, &node->outputs, nsout); 00357 if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) 00358 data_from_gpu_stack_list(&node->outputs, nsout, gpuout); 00359 } 00360 else if(node->typeinfo->gpuextfunc) { 00361 node_get_stack(node, stack, nsin, nsout); 00362 gpu_stack_from_data_list(gpuin, &node->inputs, nsin); 00363 gpu_stack_from_data_list(gpuout, &node->outputs, nsout); 00364 if(node->typeinfo->gpuextfunc(mat, node, nodeexec->data, gpuin, gpuout)) 00365 data_from_gpu_stack_list(&node->outputs, nsout, gpuout); 00366 } 00367 } 00368 } 00369 } 00370 00371 void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *UNUSED(out)) 00372 { 00373 NodeTexBase *base= node->storage; 00374 TexMapping *texmap= &base->tex_mapping; 00375 float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0; 00376 float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0; 00377 00378 if(domin || domax || !(texmap->flag & TEXMAP_UNIT_MATRIX)) { 00379 GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat); 00380 GPUNodeLink *tmin = GPU_uniform(texmap->min); 00381 GPUNodeLink *tmax = GPU_uniform(texmap->max); 00382 GPUNodeLink *tdomin = GPU_uniform(&domin); 00383 GPUNodeLink *tdomax = GPU_uniform(&domax); 00384 00385 GPU_link(mat, "mapping", in[0].link, tmat, tmin, tmax, tdomin, tdomax, &in[0].link); 00386 } 00387 } 00388