Blender V2.61 - r43446

node_shader_util.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) 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