diff options
author | Lukas Toenne <lukas.toenne@googlemail.com> | 2011-09-06 01:01:50 +0400 |
---|---|---|
committer | Lukas Toenne <lukas.toenne@googlemail.com> | 2011-09-06 01:01:50 +0400 |
commit | 8e0fe8bff72e2dc2926618577eaffdd3417a8304 (patch) | |
tree | 43b933c88cac451518dc68846c1119acacffca4f /source/blender/nodes/shader | |
parent | 6e9ff495eb082aeb49e6a1da23a7827d3fcd0fde (diff) |
Merged the particles-2010 branch with node improvements into trunk.
This branch adds mostly organizational improvements to the node system by renaming the node folders and files. A couple of internal features have been added too.
Detailed information can be found on the wiki page:
http://wiki.blender.org/index.php/User:Phonybone/Particles2010
Diffstat (limited to 'source/blender/nodes/shader')
23 files changed, 4073 insertions, 0 deletions
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c new file mode 100644 index 00000000000..620da7553b3 --- /dev/null +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -0,0 +1,212 @@ +/** + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2007 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/node_shader_tree.c + * \ingroup nodes + */ + + +#include <string.h> + +#include "DNA_material_types.h" +#include "DNA_node_types.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_utildefines.h" + +#include "GPU_material.h" + +#include "RE_shader_ext.h" + +#include "node_exec.h" +#include "node_util.h" +#include "node_shader_util.h" + +static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func) +{ + Material *ma; + for(ma= main->mat.first; ma; ma= ma->id.next) { + if(ma->nodetree) { + func(calldata, &ma->id, ma->nodetree); + } + } +} + +static void local_sync(bNodeTree *localtree, bNodeTree *ntree) +{ + bNode *lnode; + + /* copy over contents of previews */ + for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { + if(ntreeNodeExists(ntree, lnode->new_node)) { + bNode *node= lnode->new_node; + + if(node->preview && node->preview->rect) { + if(lnode->preview && lnode->preview->rect) { + int xsize= node->preview->xsize; + int ysize= node->preview->ysize; + memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4); + } + } + } + } +} + +bNodeTreeType ntreeType_Shader = { + /* type */ NTREE_SHADER, + /* id_name */ "NTShader Nodetree", + + /* node_types */ { NULL, NULL }, + + /* free_cache */ NULL, + /* free_node_cache */ NULL, + /* foreach_nodetree */ foreach_nodetree, + /* localize */ NULL, + /* local_sync */ local_sync, + /* local_merge */ NULL, + /* update */ NULL, + /* update_node */ NULL +}; + +/* GPU material from shader nodes */ + +void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) +{ + bNodeTreeExec *exec; + + if(!ntree->execdata) + exec = ntreeShaderBeginExecTree(ntree); + + ntreeExecGPUNodes(exec, mat, 1); + + ntreeShaderEndExecTree(exec); +} + +/* **************** call to switch lamploop for material node ************ */ + +void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); + +void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *)) +{ + node_shader_lamp_loop= lamp_loop_func; +} + + +bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree) +{ + bNodeTreeExec *exec; + bNode *node; + + /* XXX hack: prevent exec data from being generated twice. + * this should be handled by the renderer! + */ + if (ntree->execdata) + return ntree->execdata; + + /* ensures only a single output node is enabled */ + ntreeSetOutput(ntree); + + /* common base initialization */ + exec = ntree_exec_begin(ntree); + + /* allocate the thread stack listbase array */ + exec->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array"); + + for(node= exec->nodetree->nodes.first; node; node= node->next) + node->need_exec= 1; + + /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, + * which only store the ntree pointer. Should be fixed at some point! + */ + ntree->execdata = exec; + + return exec; +} + +void ntreeShaderEndExecTree(bNodeTreeExec *exec) +{ + if(exec) { + bNodeTree *ntree= exec->nodetree; + bNodeThreadStack *nts; + int a; + + if(exec->threadstack) { + for(a=0; a<BLENDER_MAX_THREADS; a++) { + for(nts=exec->threadstack[a].first; nts; nts=nts->next) + if (nts->stack) MEM_freeN(nts->stack); + BLI_freelistN(&exec->threadstack[a]); + } + + MEM_freeN(exec->threadstack); + exec->threadstack= NULL; + } + + ntree_exec_end(exec); + + /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ + ntree->execdata = NULL; + } +} + +void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) +{ + ShaderCallData scd; + /* + @note: preserve material from ShadeInput for material id, nodetree execs change it + fix for bug "[#28012] Mat ID messy with shader nodes" + */ + Material *mat = shi->mat; bNodeThreadStack *nts = NULL; + bNodeTreeExec *exec = ntree->execdata; + + /* convert caller data to struct */ + scd.shi= shi; + scd.shr= shr; + + /* each material node has own local shaderesult, with optional copying */ + memset(shr, 0, sizeof(ShadeResult)); + + if (!exec) + exec = ntree->execdata = ntreeShaderBeginExecTree(exec->nodetree); + + nts= ntreeGetThreadStack(exec, shi->thread); + ntreeExecThreadNodes(exec, nts, &scd, shi->thread); + ntreeReleaseThreadStack(nts); + + // @note: set material back to preserved material + shi->mat = mat; + /* better not allow negative for now */ + if(shr->combined[0]<0.0f) shr->combined[0]= 0.0f; + if(shr->combined[1]<0.0f) shr->combined[1]= 0.0f; + if(shr->combined[2]<0.0f) shr->combined[2]= 0.0f; +} diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c new file mode 100644 index 00000000000..cf910ba3f64 --- /dev/null +++ b/source/blender/nodes/shader/node_shader_util.c @@ -0,0 +1,287 @@ +/* + * $Id: SHD_util.c 36549 2011-05-08 14:23:38Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/node_shader_util.c + * \ingroup nodes + */ + + +#include "DNA_node_types.h" + +#include "node_shader_util.h" + +#include "node_exec.h" + +/* ****** */ + +void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) +{ + float *from= ns->vec; + + if(type_in==SOCK_FLOAT) { + if(ns->sockettype==SOCK_FLOAT) + *in= *from; + else + *in= 0.333333f*(from[0]+from[1]+from[2]); + } + else if(type_in==SOCK_VECTOR) { + if(ns->sockettype==SOCK_FLOAT) { + in[0]= from[0]; + in[1]= from[0]; + in[2]= from[0]; + } + else { + VECCOPY(in, from); + } + } + else { /* type_in==SOCK_RGBA */ + if(ns->sockettype==SOCK_RGBA) { + QUATCOPY(in, from); + } + else if(ns->sockettype==SOCK_FLOAT) { + in[0]= from[0]; + in[1]= from[0]; + in[2]= from[0]; + in[3]= 1.0f; + } + else { + VECCOPY(in, from); + in[3]= 1.0f; + } + } +} + + +/* ******************* execute and parse ************ */ + +/* go over all used Geometry and Texture nodes, and return a texco flag */ +/* no group inside needed, this function is called for groups too */ +void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mode) +{ + bNode *node; + bNodeSocket *sock; + int a; + + ntreeSocketUseFlags(ntree); + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->type==SH_NODE_TEXTURE) { + if((r_mode & R_OSA) && node->id) { + Tex *tex= (Tex *)node->id; + if ELEM3(tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) + *texco |= TEXCO_OSA|NEED_UV; + } + /* usability exception... without input we still give the node orcos */ + sock= node->inputs.first; + if(sock==NULL || sock->link==NULL) + *texco |= TEXCO_ORCO|NEED_UV; + } + else if(node->type==SH_NODE_GEOMETRY) { + /* note; sockets always exist for the given type! */ + for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { + if(sock->flag & SOCK_IN_USE) { + switch(a) { + case GEOM_OUT_GLOB: + *texco |= TEXCO_GLOB|NEED_UV; break; + case GEOM_OUT_VIEW: + *texco |= TEXCO_VIEW|NEED_UV; break; + case GEOM_OUT_ORCO: + *texco |= TEXCO_ORCO|NEED_UV; break; + case GEOM_OUT_UV: + *texco |= TEXCO_UV|NEED_UV; break; + case GEOM_OUT_NORMAL: + *texco |= TEXCO_NORM|NEED_UV; break; + case GEOM_OUT_VCOL: + *texco |= NEED_UV; *mode |= MA_VERTEXCOL; break; + } + } + } + } + } +} + +/* nodes that use ID data get synced with local data */ +void nodeShaderSynchronizeID(bNode *node, int copyto) +{ + if(node->id==NULL) return; + + if(ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) { + bNodeSocket *sock; + Material *ma= (Material *)node->id; + int a; + + /* hrmf, case in loop isnt super fast, but we dont edit 100s of material at same time either! */ + for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { + if(!(sock->flag & SOCK_HIDDEN)) { + if(copyto) { + switch(a) { + case MAT_IN_COLOR: + VECCOPY(&ma->r, ((bNodeSocketValueRGBA*)sock->default_value)->value); break; + case MAT_IN_SPEC: + VECCOPY(&ma->specr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break; + case MAT_IN_REFL: + ma->ref= ((bNodeSocketValueFloat*)sock->default_value)->value; break; + case MAT_IN_MIR: + VECCOPY(&ma->mirr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break; + case MAT_IN_AMB: + ma->amb= ((bNodeSocketValueFloat*)sock->default_value)->value; break; + case MAT_IN_EMIT: + ma->emit= ((bNodeSocketValueFloat*)sock->default_value)->value; break; + case MAT_IN_SPECTRA: + ma->spectra= ((bNodeSocketValueFloat*)sock->default_value)->value; break; + case MAT_IN_RAY_MIRROR: + ma->ray_mirror= ((bNodeSocketValueFloat*)sock->default_value)->value; break; + case MAT_IN_ALPHA: + ma->alpha= ((bNodeSocketValueFloat*)sock->default_value)->value; break; + case MAT_IN_TRANSLUCENCY: + ma->translucency= ((bNodeSocketValueFloat*)sock->default_value)->value; break; + } + } + else { + switch(a) { + case MAT_IN_COLOR: + VECCOPY(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->r); break; + case MAT_IN_SPEC: + VECCOPY(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->specr); break; + case MAT_IN_REFL: + ((bNodeSocketValueFloat*)sock->default_value)->value= ma->ref; break; + case MAT_IN_MIR: + VECCOPY(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->mirr); break; + case MAT_IN_AMB: + ((bNodeSocketValueFloat*)sock->default_value)->value= ma->amb; break; + case MAT_IN_EMIT: + ((bNodeSocketValueFloat*)sock->default_value)->value= ma->emit; break; + case MAT_IN_SPECTRA: + ((bNodeSocketValueFloat*)sock->default_value)->value= ma->spectra; break; + case MAT_IN_RAY_MIRROR: + ((bNodeSocketValueFloat*)sock->default_value)->value= ma->ray_mirror; break; + case MAT_IN_ALPHA: + ((bNodeSocketValueFloat*)sock->default_value)->value= ma->alpha; break; + case MAT_IN_TRANSLUCENCY: + ((bNodeSocketValueFloat*)sock->default_value)->value= ma->translucency; break; + } + } + } + } + } + +} + + +void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns) +{ + memset(gs, 0, sizeof(*gs)); + + QUATCOPY(gs->vec, ns->vec); + gs->link= ns->data; + + if (type == SOCK_FLOAT) + gs->type= GPU_FLOAT; + else if (type == SOCK_VECTOR) + gs->type= GPU_VEC3; + else if (type == SOCK_RGBA) + gs->type= GPU_VEC4; + else + gs->type= GPU_NONE; + + gs->name = ""; + gs->hasinput= ns->hasinput && ns->data; + gs->hasoutput= ns->hasoutput && ns->data; + gs->sockettype= ns->sockettype; +} + +void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs) +{ + ns->data= gs->link; + ns->sockettype= gs->sockettype; +} + +static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeStack **ns) +{ + bNodeSocket *sock; + int i; + + for (sock=sockets->first, i=0; sock; sock=sock->next, i++) + node_gpu_stack_from_data(&gs[i], sock->type, ns[i]); + + gs[i].type= GPU_NONE; +} + +static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) +{ + bNodeSocket *sock; + int i; + + for (sock=sockets->first, i=0; sock; sock=sock->next, i++) + node_data_from_gpu_stack(ns[i], &gs[i]); +} + +void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs) +{ + bNodeExec *nodeexec; + bNode *node; + int n; + bNodeStack *stack; + bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ + bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ + GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; + int doit; + + stack= exec->stack; + + for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { + node = nodeexec->node; + + doit = 0; + /* for groups, only execute outputs for edited group */ + if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { + if(do_outputs && (node->flag & NODE_DO_OUTPUT)) + doit = 1; + } + else + doit = 1; + + if (doit) { + if(node->typeinfo->gpufunc) { + node_get_stack(node, stack, nsin, nsout); + gpu_stack_from_data_list(gpuin, &node->inputs, nsin); + gpu_stack_from_data_list(gpuout, &node->outputs, nsout); + if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) + data_from_gpu_stack_list(&node->outputs, nsout, gpuout); + } + else if(node->typeinfo->gpuextfunc) { + node_get_stack(node, stack, nsin, nsout); + gpu_stack_from_data_list(gpuin, &node->inputs, nsin); + gpu_stack_from_data_list(gpuout, &node->outputs, nsout); + if(node->typeinfo->gpuextfunc(mat, node, nodeexec->data, gpuin, gpuout)) + data_from_gpu_stack_list(&node->outputs, nsout, gpuout); + } + } + } +} diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h new file mode 100644 index 00000000000..1cc04d95d6f --- /dev/null +++ b/source/blender/nodes/shader/node_shader_util.h @@ -0,0 +1,130 @@ +/* + * $Id: SHD_util.h 36549 2011-05-08 14:23:38Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/node_shader_util.h + * \ingroup nodes + */ + + +#ifndef NODE_SHADER_UTIL_H_ +#define NODE_SHADER_UTIL_H_ + +#include <math.h> +#include <float.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_color_types.h" +#include "DNA_ID.h" +#include "DNA_image_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" + +#include "BKE_blender.h" +#include "BKE_colortools.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_node.h" +#include "BKE_texture.h" + +#include "BKE_library.h" + +#include "NOD_shader.h" +#include "node_util.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "RE_pipeline.h" +#include "RE_shader_ext.h" + +#include "GPU_material.h" + +/* ********* exec data struct, remains internal *********** */ + +typedef struct ShaderCallData { + ShadeInput *shi; /* from render pipe */ + ShadeResult *shr; /* from render pipe */ +} ShaderCallData; + +/* output socket defines */ +#define GEOM_OUT_GLOB 0 +#define GEOM_OUT_LOCAL 1 +#define GEOM_OUT_VIEW 2 +#define GEOM_OUT_ORCO 3 +#define GEOM_OUT_UV 4 +#define GEOM_OUT_NORMAL 5 +#define GEOM_OUT_VCOL 6 +#define GEOM_OUT_FRONTBACK 7 + + +/* input socket defines */ +#define MAT_IN_COLOR 0 +#define MAT_IN_SPEC 1 +#define MAT_IN_REFL 2 +#define MAT_IN_NORMAL 3 +#define MAT_IN_MIR 4 +#define MAT_IN_AMB 5 +#define MAT_IN_EMIT 6 +#define MAT_IN_SPECTRA 7 +#define MAT_IN_RAY_MIRROR 8 +#define MAT_IN_ALPHA 9 +#define MAT_IN_TRANSLUCENCY 10 +#define NUM_MAT_IN 11 /* for array size */ + +/* output socket defines */ +#define MAT_OUT_COLOR 0 +#define MAT_OUT_ALPHA 1 +#define MAT_OUT_NORMAL 2 +#define MAT_OUT_DIFFUSE 3 +#define MAT_OUT_SPEC 4 +#define MAT_OUT_AO 5 + + +extern void node_ID_title_cb(void *node_v, void *unused_v); +void nodestack_get_vec(float *in, short type_in, bNodeStack *ns); + +void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, struct bNodeStack *ns); +void node_data_from_gpu_stack(struct bNodeStack *ns, struct GPUNodeStack *gs); + +void ntreeExecGPUNodes(struct bNodeTreeExec *exec, struct GPUMaterial *mat, int do_outputs); + +#endif diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c new file mode 100644 index 00000000000..ecb7c486dc4 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_camera.c @@ -0,0 +1,76 @@ +/* + * $Id: SHD_camera.c 36536 2011-05-07 13:27:27Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_camera.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** CAMERA INFO ******************** */ +static bNodeSocketTemplate sh_node_camera_out[]= { + { SOCK_VECTOR, 0, "View Vector"}, + { SOCK_FLOAT, 0, "View Z Depth"}, + { SOCK_FLOAT, 0, "View Distance"}, + { -1, 0, "" } +}; + + +static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **out) +{ + if(data) { + ShadeInput *shi= ((ShaderCallData *)data)->shi; /* Data we need for shading. */ + + VECCOPY(out[0]->vec, shi->co); /* get view vector */ + out[1]->vec[0]= fabs(shi->co[2]); /* get view z-depth */ + out[2]->vec[0]= normalize_v3(out[0]->vec); /* get view distance */ + } +} + +static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION)); +} + +void register_node_type_sh_camera(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0); + node_type_socket_templates(&ntype, NULL, sh_node_camera_out); + node_type_size(&ntype, 95, 95, 120); + node_type_storage(&ntype, "node_camera", NULL, NULL); + node_type_exec(&ntype, node_shader_exec_camera); + node_type_gpu(&ntype, gpu_shader_camera); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c new file mode 100644 index 00000000000..ab3638436f1 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_common.c @@ -0,0 +1,327 @@ +/* + * $Id: CMP_blur.c 35562 2011-03-15 20:10:32Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva, + * Juho Vepsäläinen + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_common.c + * \ingroup shdnodes + */ + + +#include "DNA_node_types.h" + +#include "BKE_node.h" + +#include "node_shader_util.h" +#include "node_common.h" +#include "node_exec.h" + +static void copy_stack(bNodeStack *to, bNodeStack *from) +{ + if (to != from) { + copy_v4_v4(to->vec, from->vec); + to->data = from->data; + to->datatype = from->datatype; + + /* tag as copy to prevent freeing */ + to->is_copy = 1; + } +} + +static void move_stack(bNodeStack *to, bNodeStack *from) +{ + if (to != from) { + copy_v4_v4(to->vec, from->vec); + to->data = from->data; + to->datatype = from->datatype; + to->is_copy = from->is_copy; + + zero_v4(from->vec); + from->data = NULL; + from->datatype = 0; + from->is_copy = 0; + } +} + +/**** GROUP ****/ + +static void *group_initexec(bNode *node) +{ + bNodeTree *ngroup= (bNodeTree*)node->id; + bNodeTreeExec *exec; + + /* initialize the internal node tree execution */ + exec = ntreeShaderBeginExecTree(ngroup); + + return exec; +} + +static void group_freeexec(bNode *UNUSED(node), void *nodedata) +{ + bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata; + + ntreeShaderEndExecTree(gexec); +} + +/* Copy inputs to the internal stack. + */ +static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack) +{ + bNodeSocket *sock; + bNodeStack *ns; + int a; + for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { + if (sock->groupsock) { + ns = node_get_socket_stack(gstack, sock->groupsock); + copy_stack(ns, in[a]); + } + } +} + +/* Copy internal results to the external outputs. + */ +static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack) +{ + bNodeSocket *sock; + bNodeStack *ns; + int a; + for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { + if (sock->groupsock) { + ns = node_get_socket_stack(gstack, sock->groupsock); + move_stack(out[a], ns); + } + } +} + +static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) +{ + bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; + bNodeThreadStack *nts; + + /* XXX same behavior as trunk: all nodes inside group are executed. + * it's stupid, but just makes it work. compo redesign will do this better. + */ + { + bNode *inode; + for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) + inode->need_exec = 1; + } + + nts = ntreeGetThreadStack(exec, thread); + + group_copy_inputs(node, in, nts->stack); + ntreeExecThreadNodes(exec, nts, data, thread); + group_move_outputs(node, out, nts->stack); + + ntreeReleaseThreadStack(nts); +} + +static void group_gpu_copy_inputs(bNode *node, GPUNodeStack *in, bNodeStack *gstack) +{ + bNodeSocket *sock; + bNodeStack *ns; + int a; + for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { + if (sock->groupsock) { + ns = node_get_socket_stack(gstack, sock->groupsock); + /* convert the external gpu stack back to internal node stack data */ + node_data_from_gpu_stack(ns, &in[a]); + } + } +} + +/* Copy internal results to the external outputs. + */ +static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *gstack) +{ + bNodeSocket *sock; + bNodeStack *ns; + int a; + for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { + if (sock->groupsock) { + ns = node_get_socket_stack(gstack, sock->groupsock); + /* convert the node stack data result back to gpu stack */ + node_gpu_stack_from_data(&out[a], sock->type, ns); + } + } +} + +static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; + + group_gpu_copy_inputs(node, in, exec->stack); + ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT)); + group_gpu_move_outputs(node, out, exec->stack); + + return 1; +} + +void register_node_type_sh_group(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT); + node_type_socket_templates(&ntype, NULL, NULL); + node_type_size(&ntype, 120, 60, 200); + node_type_label(&ntype, node_group_label); + node_type_init(&ntype, node_group_init); + node_type_valid(&ntype, node_group_valid); + node_type_template(&ntype, node_group_template); + node_type_update(&ntype, NULL, node_group_verify); + node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); + node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute); + node_type_gpu_ext(&ntype, gpu_group_execute); + + nodeRegisterType(lb, &ntype); +} + + +/**** FOR LOOP ****/ + +#if 0 /* XXX loop nodes don't work nicely with current trees */ +static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) +{ + bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; + bNodeThreadStack *nts; + int iterations= (int)in[0]->vec[0]; + bNodeSocket *sock; + bNodeStack *ns; + int iteration; + + /* XXX same behavior as trunk: all nodes inside group are executed. + * it's stupid, but just makes it work. compo redesign will do this better. + */ + { + bNode *inode; + for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) + inode->need_exec = 1; + } + + nts = ntreeGetThreadStack(exec, thread); + + /* "Iteration" socket */ + sock = exec->nodetree->inputs.first; + ns = node_get_socket_stack(nts->stack, sock); + +// group_copy_inputs(node, in, nts->stack); + for (iteration=0; iteration < iterations; ++iteration) { + /* first input contains current iteration counter */ + ns->vec[0] = (float)iteration; + ns->vec[1]=ns->vec[2]=ns->vec[3] = 0.0f; + +// if (iteration > 0) +// loop_init_iteration(exec->nodetree, nts->stack); +// ntreeExecThreadNodes(exec, nts, data, thread); + } +// loop_copy_outputs(node, in, out, exec->stack); + + ntreeReleaseThreadStack(nts); +} + +void register_node_type_sh_forloop(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS); + node_type_socket_templates(&ntype, NULL, NULL); + node_type_size(&ntype, 120, 60, 200); + node_type_label(&ntype, node_group_label); + node_type_init(&ntype, node_forloop_init); + node_type_valid(&ntype, node_group_valid); + node_type_template(&ntype, node_forloop_template); + node_type_update(&ntype, NULL, node_group_verify); + node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree); + node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); + node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute); + + nodeRegisterType(lb, &ntype); +} +#endif + +/**** WHILE LOOP ****/ + +#if 0 /* XXX loop nodes don't work nicely with current trees */ +static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) +{ + bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; + bNodeThreadStack *nts; + int condition= (in[0]->vec[0] > 0.0f); + bNodeSocket *sock; + bNodeStack *ns; + int iteration; + + /* XXX same behavior as trunk: all nodes inside group are executed. + * it's stupid, but just makes it work. compo redesign will do this better. + */ + { + bNode *inode; + for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) + inode->need_exec = 1; + } + + nts = ntreeGetThreadStack(exec, thread); + + /* "Condition" socket */ + sock = exec->nodetree->outputs.first; + ns = node_get_socket_stack(nts->stack, sock); + + iteration = 0; +// group_copy_inputs(node, in, nts->stack); + while (condition && iteration < node->custom1) { +// if (iteration > 0) +// loop_init_iteration(exec->nodetree, nts->stack); +// ntreeExecThreadNodes(exec, nts, data, thread); + + condition = (ns->vec[0] > 0.0f); + ++iteration; + } +// loop_copy_outputs(node, in, out, exec->stack); + + ntreeReleaseThreadStack(nts); +} + +void register_node_type_sh_whileloop(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS); + node_type_socket_templates(&ntype, NULL, NULL); + node_type_size(&ntype, 120, 60, 200); + node_type_label(&ntype, node_group_label); + node_type_init(&ntype, node_whileloop_init); + node_type_valid(&ntype, node_group_valid); + node_type_template(&ntype, node_whileloop_template); + node_type_update(&ntype, NULL, node_group_verify); + node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree); + node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); + node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute); + + nodeRegisterType(lb, &ntype); +} +#endif diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c new file mode 100644 index 00000000000..ded867ec441 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -0,0 +1,142 @@ +/* + * $Id: SHD_curves.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_curves.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + + +/* **************** CURVE VEC ******************** */ +static bNodeSocketTemplate sh_node_curve_vec_in[]= { + { SOCK_FLOAT, 0, "Fac", 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_curve_vec_out[]= { + { SOCK_VECTOR, 0, "Vector"}, + { -1, 0, "" } +}; + +static void node_shader_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + float vec[3]; + + /* stack order input: vec */ + /* stack order output: vec */ + nodestack_get_vec(vec, SOCK_VECTOR, in[1]); + curvemapping_evaluate3F(node->storage, out[0]->vec, vec); +} + +static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); +} + +static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array)); +} + +void register_node_type_sh_curve_vec(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_curve_vec_in, sh_node_curve_vec_out); + node_type_size(&ntype, 200, 140, 320); + node_type_init(&ntype, node_shader_init_curve_vec); + node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); + node_type_exec(&ntype, node_shader_exec_curve_vec); + node_type_gpu(&ntype, gpu_shader_curve_vec); + + nodeRegisterType(lb, &ntype); +} + + +/* **************** CURVE RGB ******************** */ +static bNodeSocketTemplate sh_node_curve_rgb_in[]= { + { SOCK_FLOAT, 1, "Fac", 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_curve_rgb_out[]= { + { SOCK_RGBA, 0, "Color"}, + { -1, 0, "" } +}; + +static void node_shader_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + float vec[3]; + + /* stack order input: vec */ + /* stack order output: vec */ + nodestack_get_vec(vec, SOCK_VECTOR, in[1]); + curvemapping_evaluateRGBF(node->storage, out[0]->vec, vec); + if(in[0]->vec[0] != 1.0f) { + interp_v3_v3v3(out[0]->vec, vec, out[0]->vec, *in[0]->vec); + } +} + +static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); +} + +static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array)); +} + +void register_node_type_sh_curve_rgb(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_curve_rgb_in, sh_node_curve_rgb_out); + node_type_size(&ntype, 200, 140, 320); + node_type_init(&ntype, node_shader_init_curve_rgb); + node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); + node_type_exec(&ntype, node_shader_exec_curve_rgb); + node_type_gpu(&ntype, gpu_shader_curve_rgb); + + nodeRegisterType(lb, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_dynamic.c b/source/blender/nodes/shader/nodes/node_shader_dynamic.c new file mode 100644 index 00000000000..6490ee00787 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_dynamic.c @@ -0,0 +1,792 @@ +/* + * $Id: SHD_dynamic.c 35927 2011-03-31 20:59:55Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2007 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Nathan Letwory + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_dynamic.c + * \ingroup shdnodes + */ + + +/* TODO, support python3.x */ +#undef WITH_PYTHON + +#ifdef WITH_PYTHON +#include <Python.h> +#include <compile.h> +#include <eval.h> +#endif + +#include "DNA_text_types.h" +#include "BKE_text.h" + + +// XXX +#if 0 +#ifdef WITH_PYTHON +#include "api2_2x/Node.h" +#include "api2_2x/gen_utils.h" +#include "BPY_extern.h" +#endif +#endif + +#include "node_shader_util.h" + +// XXX +#if 0 +static void node_dynamic_setup(bNode *node); +static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out); +static void node_dynamic_free_storage_cb(bNode *node); + +#ifdef WITH_PYTHON +static PyObject *init_dynamicdict(void) { + PyObject *newscriptdict, *item; + PyGILState_STATE gilstate = PyGILState_Ensure(); + + newscriptdict= PyDict_New(); + + PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins()); + item= PyString_FromString("__main__"); + PyDict_SetItemString(newscriptdict, "__name__", item); + Py_DECREF(item); + + PyGILState_Release(gilstate); + + return newscriptdict; +} +#endif + +static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id) +{ + bNodeType *ntype = list->first; + + while(ntype) { + if (ntype->type == NODE_DYNAMIC && ntype->id == id) + break; + ntype = ntype->next; + } + + return ntype; /* NULL if doesn't exist */ +} + +static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo) +{ + bNodeSocketTemplate *sock; + + if (!tinfo) return; + + if (tinfo->inputs) { + sock = tinfo->inputs; + while (sock->type != -1) { + MEM_freeN(sock->name); + sock++; + } + MEM_freeN(tinfo->inputs); + tinfo->inputs = NULL; + } + if (tinfo->outputs) { + sock = tinfo->outputs; + while (sock->type != -1) { + MEM_freeN(sock->name); + sock++; + } + MEM_freeN(tinfo->outputs); + tinfo->outputs = NULL; + } +} + +static void node_dynamic_free_typeinfo(bNodeType *tinfo) +{ + if (!tinfo) return; + + node_dynamic_free_typeinfo_sockets(tinfo); + + if (tinfo->name) { MEM_freeN(tinfo->name); } + + MEM_freeN(tinfo); +} + +static void node_dynamic_free_sockets(bNode *node) +{ + BLI_freelistN(&node->inputs); + BLI_freelistN(&node->outputs); +} + +/* For now we just remove the socket links. It's the safest + * route, since an update in the script may change completely the + * inputs and outputs. Trying to recreate the node links would be + * nicer for pynode authors, though. */ +static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree) +{ + if (ntree) { + nodeVerifyType(ntree, node); + } + else { + Material *ma; + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if (nd == node) nodeVerifyType(ma->nodetree, node); + } + } + } + } +} + +static void node_dynamic_free_storage_cb(bNode *node) +{ +#ifdef WITH_PYTHON + NodeScriptDict *nsd; + PyObject *pydict; + BPy_Node *pynode; + + if (!node->storage) return; + nsd = (NodeScriptDict *)(node->storage); + pydict = nsd->dict; + if (pydict) { + Py_DECREF(pydict); + } + pynode = nsd->node; + if (pynode) { + Py_DECREF(pynode); + } +#endif + MEM_freeN(node->storage); + node->storage = NULL; +} + +/* Disable pynode when its script fails */ +static void node_dynamic_disable(bNode *node) +{ + node->custom1 = 0; + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR); +} + +/* Disable all pynodes using the given text (script) id */ +static void node_dynamic_disable_all_by_id(ID *id) +{ +#ifdef WITH_PYTHON + Material *ma; /* XXX hardcoded for shaders */ + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + bNodeTree *ntree = ma->nodetree; + for (nd= ntree->nodes.first; nd; nd= nd->next) { + if (nd->id == id) { + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR); + } + } + } + } +#endif +} + +static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb) +{ + bNodeLink *link, *next; + bNodeSocket *sock; + + if (!lb) return; + + for (sock= lb->first; sock; sock= sock->next) { + for (link= ntree->links.first; link; link= next) { + next= link->next; + if (link->fromsock==sock || link->tosock==sock) { + nodeRemLink(ntree, link); + } + } + } +} + +/* XXX hardcoded for shaders */ +static void node_dynamic_rem_all_links(bNodeType *tinfo) +{ + Material *ma; + int in, out; + + in = tinfo->inputs ? 1 : 0; + out = tinfo->outputs ? 1 : 0; + + if (!in && !out) return; + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + bNodeTree *ntree = ma->nodetree; + for (nd= ntree->nodes.first; nd; nd= nd->next) { + if (nd->typeinfo == tinfo) { + if (in) + node_rem_socklist_links(ntree, &nd->inputs); + if (out) + node_rem_socklist_links(ntree, &nd->outputs); + } + } + } + } +} + +/* node_dynamic_reset: clean a pynode, getting rid of all + * data dynamically created for it. */ +static void node_dynamic_reset(bNode *node, int unlink_text) +{ + bNodeType *tinfo, *tinfo_default; + Material *ma; + + tinfo = node->typeinfo; + tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL); + + if ((tinfo == tinfo_default) && unlink_text) { + ID *textID = node->id; + /* already at default (empty) state, which happens if this node's + * script failed to parse at the first stage: definition. We're here + * because its text was removed from Blender. */ + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if (nd->id == textID) { + nd->id = NULL; + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); + BLI_strncpy(nd->name, "Dynamic", 8); + return; + } + } + } + } + } + + node_dynamic_rem_all_links(tinfo); + node_dynamic_free_typeinfo_sockets(tinfo); + + /* reset all other XXX shader nodes sharing this typeinfo */ + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if (nd->typeinfo == tinfo) { + node_dynamic_free_storage_cb(nd); + node_dynamic_free_sockets(nd); + //node_dynamic_update_socket_links(nd, ma->nodetree); + nd->typeinfo = tinfo_default; + if (unlink_text) { + nd->id = NULL; + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); + BLI_strncpy(nd->name, "Dynamic", 8); + } + } + } + } + } + + /* XXX hardcoded for shaders: */ + if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } + node_dynamic_free_typeinfo(tinfo); +} + +/* Special case of the above function: for working pynodes + * that were saved on a .blend but fail for some reason when + * the file is opened. We need this because pynodes are initialized + * before G.main. */ +static void node_dynamic_reset_loaded(bNode *node) +{ + bNodeType *tinfo = node->typeinfo; + + node_dynamic_rem_all_links(tinfo); + node_dynamic_free_typeinfo_sockets(tinfo); + node_dynamic_free_storage_cb(node); + /* XXX hardcoded for shaders: */ + if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } + + node_dynamic_free_typeinfo(tinfo); + node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL); +} + +int nodeDynamicUnlinkText(ID *txtid) { + Material *ma; + bNode *nd; + + /* find one node that uses this text */ + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if ((nd->type == NODE_DYNAMIC) && (nd->id == txtid)) { + node_dynamic_reset(nd, 1); /* found, reset all */ + return 1; + } + } + } + } + return 0; /* no pynodes used this text */ +} + +static void node_dynamic_pyerror_print(bNode *node) +{ +#ifdef WITH_PYTHON + PyGILState_STATE gilstate = PyGILState_Ensure(); + + fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name); + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + PySys_SetObject("last_traceback", NULL); + } + else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); } + + PyGILState_Release(gilstate); +#endif +} + +static void node_dynamic_register_type(bNode *node) +{ + nodeRegisterType(&node_all_shaders, node->typeinfo); + /* nodeRegisterType copied it to a new one, so we + * free the typeinfo itself, but not what it + * points to: */ + MEM_freeN(node->typeinfo); + node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id); + MEM_freeN(node->typeinfo->name); + node->typeinfo->name = BLI_strdup(node->name); +} + +#ifdef WITH_PYTHON +/* node_dynamic_get_pynode: + * Find the pynode definition from the script */ +static PyObject *node_dynamic_get_pynode(PyObject *dict) +{ + PyObject *key= NULL; + Py_ssize_t pos = 0; + PyObject *value = NULL; + + /* script writer specified a node? */ + value = PyDict_GetItemString(dict, "__node__"); + + if (value) { + if (PyObject_TypeCheck(value, &PyType_Type)) { + Py_INCREF(value); + return value; + } + else { + PyErr_SetString(PyExc_TypeError, + "expected class object derived from Scripted node"); + return NULL; + } + } + + /* case not, search for it in the script's global dictionary */ + while (PyDict_Next(dict, &pos, &key, &value)) { + /* skip names we know belong to other available objects */ + if (strcmp("Socket", PyString_AsString(key)) == 0) + continue; + else if (strcmp("Scripted", PyString_AsString(key)) == 0) + continue; + /* naive: we grab the first ob of type 'type': */ + else if (PyObject_TypeCheck(value, &PyType_Type)) { + Py_INCREF(value); + return value; + } + } + + PyErr_SetString(PyExc_TypeError, + "no PyNode definition found in the script!"); + return NULL; +} +#endif /* WITH_PYTHON */ + +static int node_dynamic_parse(struct bNode *node) +{ +#ifndef WITH_PYTHON + return -1; +#else + PyObject *dict= NULL; + PyObject *pynode_data= NULL; + PyObject *pynode= NULL; + PyObject *args= NULL; + NodeScriptDict *nsd = NULL; + PyObject *pyresult = NULL; + char *buf = NULL; + int is_valid_script = 0; + PyGILState_STATE gilstate; + + if (!node->id || !node->storage) + return 0; + + /* READY, no need to be here */ + if (BTST(node->custom1, NODE_DYNAMIC_READY)) + return 0; + + /* for threading */ + gilstate = PyGILState_Ensure(); + + nsd = (NodeScriptDict *)node->storage; + + dict = (PyObject *)(nsd->dict); + buf = txt_to_buf((Text *)node->id); + + pyresult = PyRun_String(buf, Py_file_input, dict, dict); + + MEM_freeN(buf); + + if (!pyresult) { + if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) { + node_dynamic_disable(node); + } else { + node_dynamic_disable_all_by_id(node->id); + } + node_dynamic_pyerror_print(node); + PyGILState_Release(gilstate); + return -1; + } + + Py_DECREF(pyresult); + + pynode_data = node_dynamic_get_pynode(dict); + + if (pynode_data) { + BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node); + + args = Py_BuildValue("(O)", socklists); + + /* init it to get the input and output sockets */ + pynode = PyObject_Call(pynode_data, args, NULL); + + Py_DECREF(pynode_data); + Py_DECREF(socklists); + Py_DECREF(args); + + if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) { + InitNode((BPy_Node *)(pynode), node); + nsd->node = pynode; + node->typeinfo->execfunc = node_dynamic_exec_cb; + is_valid_script = 1; + + /* for NEW, LOADED, REPARSE */ + if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { + node->typeinfo->pydict = dict; + node->typeinfo->pynode = pynode; + node->typeinfo->id = node->id; + if (BNTST(node->custom1, NODE_DYNAMIC_LOADED)) + nodeAddSockets(node, node->typeinfo); + if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE)) + node_dynamic_register_type(node); + } + + node->custom1 = 0; + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); + } + } + + PyGILState_Release(gilstate); + + if (!is_valid_script) { /* not a valid pynode script */ + node_dynamic_disable_all_by_id(node->id); + node_dynamic_pyerror_print(node); + return -1; + } + + return 0; +#endif +} + +/* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY) + * pynodes already linked to a script (node->id != NULL). */ +static void node_dynamic_setup(bNode *node) +{ +#ifdef WITH_PYTHON + NodeScriptDict *nsd = NULL; + bNodeTree *nodetree = NULL; + bNodeType *ntype = NULL; + PyGILState_STATE gilstate; + + /* Possible cases: + * NEW + * ADDEXIST + * LOADED + * REPARSE + * ERROR + * READY + */ + + /* NEW, but not linked to a script: link default (empty) typeinfo */ + if (!node->id) { + node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, + NULL); + return; + } + + /* READY, no need to be here */ + if (BTST(node->custom1, NODE_DYNAMIC_READY)) + return; + + gilstate = PyGILState_Ensure(); + + /* ERROR, reset to (empty) defaults */ + if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) { + node_dynamic_reset(node, 0); + PyGILState_Release(gilstate); + return; + } + + /* User asked to update this pynode, prepare it for reparsing */ + if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) { + int needs_parsing = 1; + + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW); + + if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE); + ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id); + + if (ntype) { + node->typeinfo = ntype; + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR); + needs_parsing = 0; + } + else { nodeMakeDynamicType(node); } + + } else { + node_dynamic_rem_all_links(node->typeinfo); + node_dynamic_free_typeinfo_sockets(node->typeinfo); + node_dynamic_update_socket_links(node, NULL); + node_dynamic_free_storage_cb(node); + } + + if (needs_parsing) { + nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary"); + nsd->dict = init_dynamicdict(); + node->storage = nsd; + /* prepared, now reparse: */ + node_dynamic_parse(node); + PyGILState_Release(gilstate); + return; + } + } + else if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) { + /* when loading from a .blend we don't have G.main yet, so we + * quickly abuse node->storage in ntreeInitTypes (node.c) to have + * our nodetree ptr (needed if a pynode script that worked before + * saving the .blend for some reason fails upon loading): */ + nodetree = (bNodeTree *)node->storage; + node->storage = NULL; + } + + if (node->storage) + fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n"); + + nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary"); + node->storage = nsd; + + /* NEW, LOADED or REPARSE */ + if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { + /* check if there's already a bNodeType linked to this script */ + /* (XXX hardcoded for shader nodes for now) */ + ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id); + + if (ntype) { /* if so, reuse it */ + node->typeinfo = ntype; + /* so this is actually an ADDEXIST type */ + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); + } + else { /* create bNodeType for this pynode */ + nodeMakeDynamicType(node); + nsd->dict = init_dynamicdict(); + if ((node_dynamic_parse(node) == -1) && nodetree) { + node_dynamic_reset_loaded(node); + } + PyGILState_Release(gilstate); + return; + } + } + + /* ADDEXIST: new pynode linked to an already registered dynamic type, + * we just reuse existing py dict and pynode */ + nsd->dict = node->typeinfo->pydict; + nsd->node = node->typeinfo->pynode; + + Py_INCREF((PyObject *)(nsd->dict)); + Py_INCREF((PyObject *)(nsd->node)); + + if (BTST(node->custom1, NODE_DYNAMIC_NEW)) { + nodeAddSockets(node, node->typeinfo); + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW); + } + + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST); + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); + + PyGILState_Release(gilstate); +#endif /* WITH_PYTHON */ + return; +} + +/* node_dynamic_init_cb callback: called when a pynode is created. + * The pynode type is passed via node->custom2. It can be: + * 0: for loaded empty nodes + * NODE_DYNAMIC_MENU: for the default Dynamic node type + * > NODE_DYNAMIC_MENU: for the new types defined by scripts +*/ +static void node_dynamic_init_cb(bNode *node) { + int type = node->custom2; + + node->custom2 = 0; + + if (type >= NODE_DYNAMIC_MENU) { + node->custom1 = 0; + + if (type == NODE_DYNAMIC_MENU) { + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW); + return; + } + + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); + node->id = node->typeinfo->id; + } + + node_dynamic_setup(node); +} + +/* node_dynamic_copy_cb: pynode copy callback */ +static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node) +{ +#ifndef WITH_PYTHON + return; +#else + NodeScriptDict *nsd; + PyGILState_STATE gilstate; + + if (!orig_node->storage) return; + + nsd = (NodeScriptDict *)(orig_node->storage); + new_node->storage = MEM_dupallocN(orig_node->storage); + + gilstate = PyGILState_Ensure(); + + if (nsd->node) + Py_INCREF((PyObject *)(nsd->node)); + if (nsd->dict) + Py_INCREF((PyObject *)(nsd->dict)); + + PyGILState_Release(gilstate); +#endif +} + +/* node_dynamic_exec_cb: the execution callback called per pixel + * during rendering. */ +static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { +#ifndef WITH_PYTHON + return; +#else + BPy_Node *mynode = NULL; + NodeScriptDict *nsd = NULL; + PyObject *pyresult = NULL; + PyObject *args = NULL; + ShadeInput *shi; + PyGILState_STATE gilstate; + + if (!node->id) + return; + + /*if (G.scene->r.threads > 1) + return;*/ + + if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) { + node_dynamic_setup(node); + return; + } + + if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { + if (node->storage) node_dynamic_setup(node); + return; + } + + if (BTST(node->custom1, NODE_DYNAMIC_READY)) { + nsd = (NodeScriptDict *)node->storage; + mynode = (BPy_Node *)(nsd->node); + + + if (mynode && PyCallable_Check((PyObject *)mynode)) { + + gilstate = PyGILState_Ensure(); + + mynode->node = node; + shi = ((ShaderCallData *)data)->shi; + + Node_SetStack(mynode, in, NODE_INPUTSTACK); + Node_SetStack(mynode, out, NODE_OUTPUTSTACK); + Node_SetShi(mynode, shi); + + args=Py_BuildValue("()"); + pyresult= PyObject_Call((PyObject *)mynode, args, NULL); + Py_DECREF(args); + + if (!pyresult) { + PyGILState_Release(gilstate); + node_dynamic_disable_all_by_id(node->id); + node_dynamic_pyerror_print(node); + node_dynamic_setup(node); + return; + } + Py_DECREF(pyresult); + PyGILState_Release(gilstate); + } + } +#endif +} + +void register_node_type_sh_dynamic(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS, NULL, NULL); + node_type_size(&ntype, 150, 60, 300); + node_type_init(&ntype, node_dynamic_init_cb); + node_type_storage(&ntype, "NodeScriptDict", node_dynamic_free_storage_cb, node_dynamic_copy_cb); + node_type_exec(&ntype, node_dynamic_exec_cb); + + nodeRegisterType(lb, &ntype); +} + +#else + +void register_node_type_sh_dynamic(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, 0); + + nodeRegisterType(lb, &ntype); +} + +#endif + + diff --git a/source/blender/nodes/shader/nodes/node_shader_geom.c b/source/blender/nodes/shader/nodes/node_shader_geom.c new file mode 100644 index 00000000000..b88c5979b54 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_geom.c @@ -0,0 +1,153 @@ +/* + * $Id: SHD_geom.c 36536 2011-05-07 13:27:27Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_geom.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +#include "DNA_customdata_types.h" + +/* **************** GEOMETRY ******************** */ + +/* output socket type definition */ +static bNodeSocketTemplate sh_node_geom_out[]= { + { SOCK_VECTOR, 0, "Global"}, + { SOCK_VECTOR, 0, "Local"}, + { SOCK_VECTOR, 0, "View"}, + { SOCK_VECTOR, 0, "Orco"}, + { SOCK_VECTOR, 0, "UV"}, + { SOCK_VECTOR, 0, "Normal"}, + { SOCK_RGBA, 0, "Vertex Color"}, + { SOCK_FLOAT, 0, "Front/Back"}, + { -1, 0, "" } +}; + +/* node execute callback */ +static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) +{ + if(data) { + ShadeInput *shi= ((ShaderCallData *)data)->shi; + NodeGeometry *ngeo= (NodeGeometry*)node->storage; + ShadeInputUV *suv= &shi->uv[shi->actuv]; + static float defaultvcol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + int i; + + if(ngeo->uvname[0]) { + /* find uv layer by name */ + for(i = 0; i < shi->totuv; i++) { + if(strcmp(shi->uv[i].name, ngeo->uvname)==0) { + suv= &shi->uv[i]; + break; + } + } + } + + /* out: global, local, view, orco, uv, normal, vertex color */ + VECCOPY(out[GEOM_OUT_GLOB]->vec, shi->gl); + VECCOPY(out[GEOM_OUT_LOCAL]->vec, shi->co); + VECCOPY(out[GEOM_OUT_VIEW]->vec, shi->view); + VECCOPY(out[GEOM_OUT_ORCO]->vec, shi->lo); + VECCOPY(out[GEOM_OUT_UV]->vec, suv->uv); + VECCOPY(out[GEOM_OUT_NORMAL]->vec, shi->vno); + + if (shi->totcol) { + /* find vertex color layer by name */ + ShadeInputCol *scol= &shi->col[0]; + + if(ngeo->colname[0]) { + for(i = 0; i < shi->totcol; i++) { + if(strcmp(shi->col[i].name, ngeo->colname)==0) { + scol= &shi->col[i]; + break; + } + } + } + + VECCOPY(out[GEOM_OUT_VCOL]->vec, scol->col); + out[GEOM_OUT_VCOL]->vec[3]= 1.0f; + } + else + memcpy(out[GEOM_OUT_VCOL]->vec, defaultvcol, sizeof(defaultvcol)); + + if(shi->osatex) { + out[GEOM_OUT_GLOB]->data= shi->dxgl; + out[GEOM_OUT_GLOB]->datatype= NS_OSA_VECTORS; + out[GEOM_OUT_LOCAL]->data= shi->dxco; + out[GEOM_OUT_LOCAL]->datatype= NS_OSA_VECTORS; + out[GEOM_OUT_VIEW]->data= &shi->dxview; + out[GEOM_OUT_VIEW]->datatype= NS_OSA_VALUES; + out[GEOM_OUT_ORCO]->data= shi->dxlo; + out[GEOM_OUT_ORCO]->datatype= NS_OSA_VECTORS; + out[GEOM_OUT_UV]->data= suv->dxuv; + out[GEOM_OUT_UV]->datatype= NS_OSA_VECTORS; + out[GEOM_OUT_NORMAL]->data= shi->dxno; + out[GEOM_OUT_NORMAL]->datatype= NS_OSA_VECTORS; + } + + /* front/back, normal flipping was stored */ + out[GEOM_OUT_FRONTBACK]->vec[0]= (shi->flippednor)? 0.0f: 1.0f; + } +} + +static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); +} + +static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + NodeGeometry *ngeo= (NodeGeometry*)node->storage; + GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); + GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ngeo->uvname); + GPUNodeLink *mcol = GPU_attribute(CD_MCOL, ngeo->colname); + + return GPU_stack_link(mat, "geom", in, out, + GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), + GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface, mcol); +} + +/* node type definition */ +void register_node_type_sh_geom(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, NODE_OPTIONS); + node_type_socket_templates(&ntype, NULL, sh_node_geom_out); + node_type_size(&ntype, 120, 80, 160); + node_type_init(&ntype, node_shader_init_geometry); + node_type_storage(&ntype, "NodeGeometry", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, node_shader_exec_geom); + node_type_gpu(&ntype, gpu_shader_geom); + + nodeRegisterType(lb, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c new file mode 100644 index 00000000000..ef1434b82ca --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c @@ -0,0 +1,99 @@ +/* + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Juho Vepsäläinen + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_hueSatVal.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + + +/* **************** Hue Saturation ******************** */ +static bNodeSocketTemplate sh_node_hue_sat_in[]= { + { SOCK_FLOAT, 1, "Hue", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_FLOAT, 1, "Saturation", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, "Value", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, "Fac", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, "Color", 0.8f, 0.8f, 0.8f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketTemplate sh_node_hue_sat_out[]= { + { SOCK_RGBA, 0, "Color"}, + { -1, 0, "" } +}; + +/* note: it would be possible to use CMP version for both nodes */ +static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *sat, float *val, float *in, float *fac) +{ + if(*fac!=0.0f && (*hue!=0.5f || *sat!=1.0f || *val!=1.0f)) { + float col[3], hsv[3], mfac= 1.0f - *fac; + + rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2); + hsv[0]+= (*hue - 0.5f); + if(hsv[0]>1.0f) hsv[0]-=1.0f; else if(hsv[0]<0.0f) hsv[0]+= 1.0f; + hsv[1]*= *sat; + hsv[2]*= *val; + hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); + + out[0]= mfac*in[0] + *fac*col[0]; + out[1]= mfac*in[1] + *fac*col[1]; + out[2]= mfac*in[2] + *fac*col[2]; + } + else { + QUATCOPY(out, in); + } +} + +static void node_shader_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec); +} + + +static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "hue_sat", in, out); +} + +void register_node_type_sh_hue_sat(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out); + node_type_size(&ntype, 150, 80, 250); + node_type_exec(&ntype, node_shader_exec_hue_sat); + node_type_gpu(&ntype, gpu_shader_hue_sat); + + nodeRegisterType(lb, &ntype); +} + + + diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c new file mode 100644 index 00000000000..bd7e571f073 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_invert.c @@ -0,0 +1,90 @@ +/* + * $Id: SHD_invert.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_invert.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + + + +/* **************** INVERT ******************** */ +static bNodeSocketTemplate sh_node_invert_in[]= { + { SOCK_FLOAT, 1, "Fac", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_invert_out[]= { + { SOCK_RGBA, 0, "Color"}, + { -1, 0, "" } +}; + +static void node_shader_exec_invert(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, +bNodeStack **out) +{ + float col[3], facm; + + col[0] = 1.0f - in[1]->vec[0]; + col[1] = 1.0f - in[1]->vec[1]; + col[2] = 1.0f - in[1]->vec[2]; + + /* if fac, blend result against original input */ + if (in[0]->vec[0] < 1.0f) { + facm = 1.0f - in[0]->vec[0]; + + col[0] = in[0]->vec[0]*col[0] + (facm*in[1]->vec[0]); + col[1] = in[0]->vec[0]*col[1] + (facm*in[1]->vec[1]); + col[2] = in[0]->vec[0]*col[2] + (facm*in[1]->vec[2]); + } + + VECCOPY(out[0]->vec, col); +} + +static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "invert", in, out); +} + +void register_node_type_sh_invert(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out); + node_type_size(&ntype, 90, 80, 100); + node_type_exec(&ntype, node_shader_exec_invert); + node_type_gpu(&ntype, gpu_shader_invert); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c new file mode 100644 index 00000000000..21cea4853ad --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -0,0 +1,104 @@ +/* + * $Id: SHD_mapping.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_mapping.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** MAPPING ******************** */ +static bNodeSocketTemplate sh_node_mapping_in[]= { + { SOCK_VECTOR, 1, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_mapping_out[]= { + { SOCK_VECTOR, 0, "Vector"}, + { -1, 0, "" } +}; + +/* do the regular mapping options for blender textures */ +static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + TexMapping *texmap= node->storage; + float *vec= out[0]->vec; + + /* stack order input: vector */ + /* stack order output: vector */ + nodestack_get_vec(vec, SOCK_VECTOR, in[0]); + mul_m4_v3(texmap->mat, vec); + + if(texmap->flag & TEXMAP_CLIP_MIN) { + if(vec[0]<texmap->min[0]) vec[0]= texmap->min[0]; + if(vec[1]<texmap->min[1]) vec[1]= texmap->min[1]; + if(vec[2]<texmap->min[2]) vec[2]= texmap->min[2]; + } + if(texmap->flag & TEXMAP_CLIP_MAX) { + if(vec[0]>texmap->max[0]) vec[0]= texmap->max[0]; + if(vec[1]>texmap->max[1]) vec[1]= texmap->max[1]; + if(vec[2]>texmap->max[2]) vec[2]= texmap->max[2]; + } +} + + +static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + node->storage= add_mapping(); +} + +static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + TexMapping *texmap= node->storage; + float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0; + float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0; + GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat); + GPUNodeLink *tmin = GPU_uniform(texmap->min); + GPUNodeLink *tmax = GPU_uniform(texmap->max); + GPUNodeLink *tdomin = GPU_uniform(&domin); + GPUNodeLink *tdomax = GPU_uniform(&domax); + + return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax); +} + +void register_node_type_sh_mapping(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_mapping_in, sh_node_mapping_out); + node_type_size(&ntype, 240, 160, 320); + node_type_init(&ntype, node_shader_init_mapping); + node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, node_shader_exec_mapping); + node_type_gpu(&ntype, gpu_shader_mapping); + + nodeRegisterType(lb, &ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c new file mode 100644 index 00000000000..a0bfd430506 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_material.c @@ -0,0 +1,336 @@ +/* + * $Id: SHD_material.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_material.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** MATERIAL ******************** */ + +static bNodeSocketTemplate sh_node_material_in[]= { + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Spec", 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_material_out[]= { + { SOCK_RGBA, 0, "Color"}, + { SOCK_FLOAT, 0, "Alpha"}, + { SOCK_VECTOR, 0, "Normal"}, + { -1, 0, "" } +}; + +/* **************** EXTENDED MATERIAL ******************** */ + +static bNodeSocketTemplate sh_node_material_ext_in[]= { + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Spec", 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, + { SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, "Emit", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, + { SOCK_FLOAT, 1, "SpecTra", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, "Ray Mirror", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, "Alpha", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, + { SOCK_FLOAT, 1, "Translucency", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_material_ext_out[]= { + { SOCK_RGBA, 0, "Color"}, + { SOCK_FLOAT, 0, "Alpha"}, + { SOCK_VECTOR, 0, "Normal"}, + { SOCK_RGBA, 0, "Diffuse"}, + { SOCK_RGBA, 0, "Spec"}, + { SOCK_RGBA, 0, "AO"}, + { -1, 0, "" } +}; + +static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + if(data && node->id) { + ShadeResult shrnode; + ShadeInput *shi; + ShaderCallData *shcd= data; + float col[4]; + bNodeSocket *sock; + char hasinput[NUM_MAT_IN]= {'\0'}; + int i; + + /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily + * the constant input stack values (e.g. in case material node is inside a group). + * we just want to know if a node input uses external data or the material setting. + * this is an ugly hack, but so is this node as a whole. + */ + for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) + hasinput[i] = (sock->link != NULL); + + shi= shcd->shi; + shi->mat= (Material *)node->id; + + /* copy all relevant material vars, note, keep this synced with render_types.h */ + memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); + shi->har= shi->mat->har; + + /* write values */ + if(hasinput[MAT_IN_COLOR]) + nodestack_get_vec(&shi->r, SOCK_VECTOR, in[MAT_IN_COLOR]); + + if(hasinput[MAT_IN_SPEC]) + nodestack_get_vec(&shi->specr, SOCK_VECTOR, in[MAT_IN_SPEC]); + + if(hasinput[MAT_IN_REFL]) + nodestack_get_vec(&shi->refl, SOCK_FLOAT, in[MAT_IN_REFL]); + + /* retrieve normal */ + if(hasinput[MAT_IN_NORMAL]) { + nodestack_get_vec(shi->vn, SOCK_VECTOR, in[MAT_IN_NORMAL]); + normalize_v3(shi->vn); + } + else + VECCOPY(shi->vn, shi->vno); + + /* custom option to flip normal */ + if(node->custom1 & SH_NODE_MAT_NEG) { + shi->vn[0]= -shi->vn[0]; + shi->vn[1]= -shi->vn[1]; + shi->vn[2]= -shi->vn[2]; + } + + if (node->type == SH_NODE_MATERIAL_EXT) { + if(hasinput[MAT_IN_MIR]) + nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]); + if(hasinput[MAT_IN_AMB]) + nodestack_get_vec(&shi->amb, SOCK_FLOAT, in[MAT_IN_AMB]); + if(hasinput[MAT_IN_EMIT]) + nodestack_get_vec(&shi->emit, SOCK_FLOAT, in[MAT_IN_EMIT]); + if(hasinput[MAT_IN_SPECTRA]) + nodestack_get_vec(&shi->spectra, SOCK_FLOAT, in[MAT_IN_SPECTRA]); + if(hasinput[MAT_IN_RAY_MIRROR]) + nodestack_get_vec(&shi->ray_mirror, SOCK_FLOAT, in[MAT_IN_RAY_MIRROR]); + if(hasinput[MAT_IN_ALPHA]) + nodestack_get_vec(&shi->alpha, SOCK_FLOAT, in[MAT_IN_ALPHA]); + if(hasinput[MAT_IN_TRANSLUCENCY]) + nodestack_get_vec(&shi->translucency, SOCK_FLOAT, in[MAT_IN_TRANSLUCENCY]); + } + + shi->nodes= 1; /* temp hack to prevent trashadow recursion */ + node_shader_lamp_loop(shi, &shrnode); /* clears shrnode */ + shi->nodes= 0; + + /* write to outputs */ + if(node->custom1 & SH_NODE_MAT_DIFF) { + VECCOPY(col, shrnode.combined); + if(!(node->custom1 & SH_NODE_MAT_SPEC)) { + sub_v3_v3(col, shrnode.spec); + } + } + else if(node->custom1 & SH_NODE_MAT_SPEC) { + VECCOPY(col, shrnode.spec); + } + else + col[0]= col[1]= col[2]= 0.0f; + + col[3]= shrnode.alpha; + + if(shi->do_preview) + nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage); + + VECCOPY(out[MAT_OUT_COLOR]->vec, col); + out[MAT_OUT_ALPHA]->vec[0]= shrnode.alpha; + + if(node->custom1 & SH_NODE_MAT_NEG) { + shi->vn[0]= -shi->vn[0]; + shi->vn[1]= -shi->vn[1]; + shi->vn[2]= -shi->vn[2]; + } + + VECCOPY(out[MAT_OUT_NORMAL]->vec, shi->vn); + + /* Extended material options */ + if (node->type == SH_NODE_MATERIAL_EXT) { + /* Shadow, Reflect, Refract, Radiosity, Speed seem to cause problems inside + * a node tree :( */ + VECCOPY(out[MAT_OUT_DIFFUSE]->vec, shrnode.diff); + VECCOPY(out[MAT_OUT_SPEC]->vec, shrnode.spec); + VECCOPY(out[MAT_OUT_AO]->vec, shrnode.ao); + } + + /* copy passes, now just active node */ + if(node->flag & NODE_ACTIVE_ID) { + float combined[4], alpha; + + copy_v4_v4(combined, shcd->shr->combined); + alpha= shcd->shr->alpha; + + *(shcd->shr)= shrnode; + + copy_v4_v4(shcd->shr->combined, combined); + shcd->shr->alpha= alpha; + } + } +} + + +static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; +} + +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) +{ + if (in->link) + return in->link; + else + return GPU_uniform(in->vec); +} + +static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + if(node->id) { + GPUShadeInput shi; + GPUShadeResult shr; + bNodeSocket *sock; + char hasinput[NUM_MAT_IN]= {'\0'}; + int i; + + /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily + * the constant input stack values (e.g. in case material node is inside a group). + * we just want to know if a node input uses external data or the material setting. + */ + for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) + hasinput[i] = (sock->link != NULL); + + GPU_shadeinput_set(mat, (Material*)node->id, &shi); + + /* write values */ + if(hasinput[MAT_IN_COLOR]) + shi.rgb = gpu_get_input_link(&in[MAT_IN_COLOR]); + + if(hasinput[MAT_IN_SPEC]) + shi.specrgb = gpu_get_input_link(&in[MAT_IN_SPEC]); + + if(hasinput[MAT_IN_REFL]) + shi.refl = gpu_get_input_link(&in[MAT_IN_REFL]); + + /* retrieve normal */ + if(hasinput[MAT_IN_NORMAL]) { + GPUNodeLink *tmp; + shi.vn = gpu_get_input_link(&in[MAT_IN_NORMAL]); + GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); + } + + /* custom option to flip normal */ + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + + if (node->type == SH_NODE_MATERIAL_EXT) { + if(hasinput[MAT_IN_AMB]) + shi.amb= gpu_get_input_link(&in[MAT_IN_AMB]); + if(hasinput[MAT_IN_EMIT]) + shi.emit= gpu_get_input_link(&in[MAT_IN_EMIT]); + if(hasinput[MAT_IN_ALPHA]) + shi.alpha= gpu_get_input_link(&in[MAT_IN_ALPHA]); + } + + GPU_shaderesult_set(&shi, &shr); /* clears shr */ + + /* write to outputs */ + if(node->custom1 & SH_NODE_MAT_DIFF) { + out[MAT_OUT_COLOR].link= shr.combined; + + if(!(node->custom1 & SH_NODE_MAT_SPEC)) { + GPUNodeLink *link; + GPU_link(mat, "vec_math_sub", shr.combined, shr.spec, &out[MAT_OUT_COLOR].link, &link); + } + } + else if(node->custom1 & SH_NODE_MAT_SPEC) { + out[MAT_OUT_COLOR].link= shr.spec; + } + else + GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); + + GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); + + out[MAT_OUT_ALPHA].link = shr.alpha; // + + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + out[MAT_OUT_NORMAL].link = shi.vn; + + if (node->type == SH_NODE_MATERIAL_EXT) { + out[MAT_OUT_DIFFUSE].link = shr.diff; + out[MAT_OUT_SPEC].link = shr.spec; + } + + return 1; + } + + return 0; +} + +void register_node_type_sh_material(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); + node_type_socket_templates(&ntype, sh_node_material_in, sh_node_material_out); + node_type_size(&ntype, 120, 80, 240); + node_type_init(&ntype, node_shader_init_material); + node_type_exec(&ntype, node_shader_exec_material); + node_type_gpu(&ntype, gpu_shader_material); + + nodeRegisterType(lb, &ntype); +} + + +void register_node_type_sh_material_ext(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); + node_type_socket_templates(&ntype, sh_node_material_ext_in, sh_node_material_ext_out); + node_type_size(&ntype, 120, 80, 240); + node_type_init(&ntype, node_shader_init_material); + node_type_exec(&ntype, node_shader_exec_material); + node_type_gpu(&ntype, gpu_shader_material); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c new file mode 100644 index 00000000000..0618598379f --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -0,0 +1,256 @@ +/* + * $Id: SHD_math.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_math.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + + +/* **************** SCALAR MATH ******************** */ +static bNodeSocketTemplate sh_node_math_in[]= { + { SOCK_FLOAT, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, + { SOCK_FLOAT, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_math_out[]= { + { SOCK_FLOAT, 0, "Value"}, + { -1, 0, "" } +}; + +static void node_shader_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in, +bNodeStack **out) +{ + switch(node->custom1){ + + case 0: /* Add */ + out[0]->vec[0]= in[0]->vec[0] + in[1]->vec[0]; + break; + case 1: /* Subtract */ + out[0]->vec[0]= in[0]->vec[0] - in[1]->vec[0]; + break; + case 2: /* Multiply */ + out[0]->vec[0]= in[0]->vec[0] * in[1]->vec[0]; + break; + case 3: /* Divide */ + { + if(in[1]->vec[0]==0) /* We don't want to divide by zero. */ + out[0]->vec[0]= 0.0; + else + out[0]->vec[0]= in[0]->vec[0] / in[1]->vec[0]; + } + break; + case 4: /* Sine */ + { + if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0]= sin(in[0]->vec[0]); + else + out[0]->vec[0]= sin(in[1]->vec[0]); + } + break; + case 5: /* Cosine */ + { + if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0]= cos(in[0]->vec[0]); + else + out[0]->vec[0]= cos(in[1]->vec[0]); + } + break; + case 6: /* Tangent */ + { + if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0]= tan(in[0]->vec[0]); + else + out[0]->vec[0]= tan(in[1]->vec[0]); + } + break; + case 7: /* Arc-Sine */ + { + if(in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ + /* Can't do the impossible... */ + if( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 ) + out[0]->vec[0]= asin(in[0]->vec[0]); + else + out[0]->vec[0]= 0.0; + } + else { + /* Can't do the impossible... */ + if( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 ) + out[0]->vec[0]= asin(in[1]->vec[0]); + else + out[0]->vec[0]= 0.0; + } + } + break; + case 8: /* Arc-Cosine */ + { + if(in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ + /* Can't do the impossible... */ + if( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 ) + out[0]->vec[0]= acos(in[0]->vec[0]); + else + out[0]->vec[0]= 0.0; + } + else { + /* Can't do the impossible... */ + if( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 ) + out[0]->vec[0]= acos(in[1]->vec[0]); + else + out[0]->vec[0]= 0.0; + } + } + break; + case 9: /* Arc-Tangent */ + { + if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0]= atan(in[0]->vec[0]); + else + out[0]->vec[0]= atan(in[1]->vec[0]); + } + break; + case 10: /* Power */ + { + /* Don't want any imaginary numbers... */ + if( in[0]->vec[0] >= 0 ) + out[0]->vec[0]= pow(in[0]->vec[0], in[1]->vec[0]); + else + out[0]->vec[0]= 0.0; + } + break; + case 11: /* Logarithm */ + { + /* Don't want any imaginary numbers... */ + if( in[0]->vec[0] > 0 && in[1]->vec[0] > 0 ) + out[0]->vec[0]= log(in[0]->vec[0]) / log(in[1]->vec[0]); + else + out[0]->vec[0]= 0.0; + } + break; + case 12: /* Minimum */ + { + if( in[0]->vec[0] < in[1]->vec[0] ) + out[0]->vec[0]= in[0]->vec[0]; + else + out[0]->vec[0]= in[1]->vec[0]; + } + break; + case 13: /* Maximum */ + { + if( in[0]->vec[0] > in[1]->vec[0] ) + out[0]->vec[0]= in[0]->vec[0]; + else + out[0]->vec[0]= in[1]->vec[0]; + } + break; + case 14: /* Round */ + { + if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0]= (in[0]->vec[0]<0)?(int)(in[0]->vec[0] - 0.5f):(int)(in[0]->vec[0] + 0.5f); + else + out[0]->vec[0]= (in[1]->vec[0]<0)?(int)(in[1]->vec[0] - 0.5f):(int)(in[1]->vec[0] + 0.5f); + } + break; + case 15: /* Less Than */ + { + if( in[0]->vec[0] < in[1]->vec[0] ) + out[0]->vec[0]= 1.0f; + else + out[0]->vec[0]= 0.0f; + } + break; + case 16: /* Greater Than */ + { + if( in[0]->vec[0] > in[1]->vec[0] ) + out[0]->vec[0]= 1.0f; + else + out[0]->vec[0]= 0.0f; + } + break; + } +} + +static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static const char *names[] = {"math_add", "math_subtract", "math_multiply", + "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin", + "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max", + "math_round", "math_less_than", "math_greater_than"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 10: + case 11: + case 12: + case 13: + case 15: + case 16: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 14: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + +void register_node_type_sh_math(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out); + node_type_size(&ntype, 120, 110, 160); + node_type_label(&ntype, node_math_label); + node_type_storage(&ntype, "node_math", NULL, NULL); + node_type_exec(&ntype, node_shader_exec_math); + node_type_gpu(&ntype, gpu_shader_math); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c new file mode 100644 index 00000000000..a89faa66fc0 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c @@ -0,0 +1,91 @@ +/* + * $Id: SHD_mixRgb.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_mixRgb.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** MIX RGB ******************** */ +static bNodeSocketTemplate sh_node_mix_rgb_in[]= { + { SOCK_FLOAT, 1, "Fac", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, "Color1", 0.5f, 0.5f, 0.5f, 1.0f}, + { SOCK_RGBA, 1, "Color2", 0.5f, 0.5f, 0.5f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketTemplate sh_node_mix_rgb_out[]= { + { SOCK_RGBA, 0, "Color"}, + { -1, 0, "" } +}; + +static void node_shader_exec_mix_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order in: fac, col1, col2 */ + /* stack order out: col */ + float col[3]; + float fac; + float vec[3]; + + nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); + CLAMP(fac, 0.0f, 1.0f); + + nodestack_get_vec(col, SOCK_VECTOR, in[1]); + nodestack_get_vec(vec, SOCK_VECTOR, in[2]); + + ramp_blend(node->custom1, col, col+1, col+2, fac, vec); + VECCOPY(out[0]->vec, col); +} + +static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", + "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", + "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", + "mix_val", "mix_color", "mix_soft", "mix_linear"}; + + return GPU_stack_link(mat, names[node->custom1], in, out); +} + + +void register_node_type_sh_mix_rgb(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_mix_rgb_in, sh_node_mix_rgb_out); + node_type_size(&ntype, 100, 60, 150); + node_type_label(&ntype, node_blend_label); + node_type_exec(&ntype, node_shader_exec_mix_rgb); + node_type_gpu(&ntype, gpu_shader_mix_rgb); + + nodeRegisterType(lb, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c new file mode 100644 index 00000000000..099a9bed10d --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_normal.c @@ -0,0 +1,95 @@ +/* + * $Id: SHD_normal.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_normal.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** NORMAL ******************** */ +static bNodeSocketTemplate sh_node_normal_in[]= { + { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_normal_out[]= { + { SOCK_VECTOR, 0, "Normal"}, + { SOCK_FLOAT, 0, "Dot"}, + { -1, 0, "" } +}; + +static void node_shader_init_normal(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + bNodeSocket *sock= node->outputs.first; + bNodeSocketValueVector *dval= (bNodeSocketValueVector*)sock->default_value; + + /* output value is used for normal vector */ + dval->value[0] = 0.0f; + dval->value[1] = 0.0f; + dval->value[2] = 1.0f; +} + +/* generates normal, does dot product */ +static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + bNodeSocket *sock= node->outputs.first; + float vec[3]; + + /* stack order input: normal */ + /* stack order output: normal, value */ + + nodestack_get_vec(vec, SOCK_VECTOR, in[0]); + + VECCOPY(out[0]->vec, ((bNodeSocketValueVector*)sock->default_value)->value); + /* render normals point inside... the widget points outside */ + out[1]->vec[0]= -INPR(out[0]->vec, vec); +} + +static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(((bNodeSocketValueVector*)sock->default_value)->value); + + return GPU_stack_link(mat, "normal", in, out, vec); +} + +void register_node_type_sh_normal(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_normal_in, sh_node_normal_out); + node_type_init(&ntype, node_shader_init_normal); + node_type_exec(&ntype, node_shader_exec_normal); + node_type_gpu(&ntype, gpu_shader_normal); + + nodeRegisterType(lb, &ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_output.c b/source/blender/nodes/shader/nodes/node_shader_output.c new file mode 100644 index 00000000000..638af7d4eb3 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_output.c @@ -0,0 +1,96 @@ +/* + * $Id: SHD_output.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_output.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** OUTPUT ******************** */ +static bNodeSocketTemplate sh_node_output_in[]= { + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { -1, 0, "" } +}; + +static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) +{ + if(data) { + ShadeInput *shi= ((ShaderCallData *)data)->shi; + float col[4]; + + /* stack order input sockets: col, alpha, normal */ + nodestack_get_vec(col, SOCK_VECTOR, in[0]); + nodestack_get_vec(col+3, SOCK_FLOAT, in[1]); + + if(shi->do_preview) { + nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage); + node->lasty= shi->ys; + } + + if(node->flag & NODE_DO_OUTPUT) { + ShadeResult *shr= ((ShaderCallData *)data)->shr; + + QUATCOPY(shr->combined, col); + shr->alpha= col[3]; + + // VECCOPY(shr->nor, in[3]->vec); + } + } +} + +static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + GPUNodeLink *outlink; + + /*if(in[1].hasinput) + GPU_material_enable_alpha(mat);*/ + + GPU_stack_link(mat, "output_node", in, out, &outlink); + GPU_material_output_link(mat, outlink); + + return 1; +} + +void register_node_type_sh_output(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW); + node_type_socket_templates(&ntype, sh_node_output_in, NULL); + node_type_size(&ntype, 80, 60, 200); + node_type_exec(&ntype, node_shader_exec_output); + node_type_gpu(&ntype, gpu_shader_output); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb.c b/source/blender/nodes/shader/nodes/node_shader_rgb.c new file mode 100644 index 00000000000..c9bb78b45dd --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_rgb.c @@ -0,0 +1,84 @@ +/* + * $Id: SHD_rgb.c 36481 2011-05-04 11:42:25Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_rgb.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** RGB ******************** */ +static bNodeSocketTemplate sh_node_rgb_out[]= { + { SOCK_RGBA, 0, "Color"}, + { -1, 0, "" } +}; + +static void node_shader_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + bNodeSocket *sock= node->outputs.first; + bNodeSocketValueRGBA *dval= (bNodeSocketValueRGBA*)sock->default_value; + /* uses the default value of the output socket, must be initialized here */ + dval->value[0] = 0.5f; + dval->value[1] = 0.5f; + dval->value[2] = 0.5f; + dval->value[3] = 1.0f; +} + +static void node_shader_exec_rgb(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) +{ + bNodeSocket *sock= node->outputs.first; + float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value; + + VECCOPY(out[0]->vec, col); +} + +static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value; + GPUNodeLink *vec = GPU_uniform(col); + + return GPU_stack_link(mat, "set_rgba", in, out, vec); +} + +void register_node_type_sh_rgb(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS); + node_type_socket_templates(&ntype, NULL, sh_node_rgb_out); + node_type_init(&ntype, node_shader_init_rgb); + node_type_size(&ntype, 140, 80, 140); + node_type_exec(&ntype, node_shader_exec_rgb); + node_type_gpu(&ntype, gpu_shader_rgb); + + nodeRegisterType(lb, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c new file mode 100644 index 00000000000..9528aca2574 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c @@ -0,0 +1,112 @@ +/* + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Juho Vepsäläinen + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_sepcombRGB.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** SEPARATE RGBA ******************** */ +static bNodeSocketTemplate sh_node_seprgb_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketTemplate sh_node_seprgb_out[]= { + { SOCK_FLOAT, 0, "R"}, + { SOCK_FLOAT, 0, "G"}, + { SOCK_FLOAT, 0, "B"}, + { -1, 0, "" } +}; + +static void node_shader_exec_seprgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) +{ + out[0]->vec[0] = in[0]->vec[0]; + out[1]->vec[0] = in[0]->vec[1]; + out[2]->vec[0] = in[0]->vec[2]; +} + +static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "separate_rgb", in, out); +} + +void register_node_type_sh_seprgb(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out); + node_type_size(&ntype, 80, 40, 140); + node_type_exec(&ntype, node_shader_exec_seprgb); + node_type_gpu(&ntype, gpu_shader_seprgb); + + nodeRegisterType(lb, &ntype); +} + + + +/* **************** COMBINE RGB ******************** */ +static bNodeSocketTemplate sh_node_combrgb_in[]= { + { SOCK_FLOAT, 1, "R", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, + { SOCK_FLOAT, 1, "G", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, + { SOCK_FLOAT, 1, "B", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, + { -1, 0, "" } +}; +static bNodeSocketTemplate sh_node_combrgb_out[]= { + { SOCK_RGBA, 0, "Image"}, + { -1, 0, "" } +}; + +static void node_shader_exec_combrgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) +{ + out[0]->vec[0] = in[0]->vec[0]; + out[0]->vec[1] = in[1]->vec[0]; + out[0]->vec[2] = in[2]->vec[0]; +} + +static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "combine_rgb", in, out); +} + +void register_node_type_sh_combrgb(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out); + node_type_size(&ntype, 80, 40, 140); + node_type_exec(&ntype, node_shader_exec_combrgb); + node_type_gpu(&ntype, gpu_shader_combrgb); + + nodeRegisterType(lb, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c new file mode 100644 index 00000000000..305639dff21 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.c @@ -0,0 +1,81 @@ +/* + * $Id: SHD_squeeze.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_squeeze.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** VALUE SQUEEZE ******************** */ +static bNodeSocketTemplate sh_node_squeeze_in[]= { + { SOCK_FLOAT, 1, "Value", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, + { SOCK_FLOAT, 1, "Width", 1.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, + { SOCK_FLOAT, 1, "Center", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_squeeze_out[]= { + { SOCK_FLOAT, 0, "Value"}, + { -1, 0, "" } +}; + +static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, +bNodeStack **out) +{ + float vec[3]; + + nodestack_get_vec(vec, SOCK_FLOAT, in[0]); + nodestack_get_vec(vec+1, SOCK_FLOAT, in[1]); + nodestack_get_vec(vec+2, SOCK_FLOAT, in[2]); + + out[0]->vec[0] = 1.0f / (1.0f + pow(2.71828183,-((vec[0]-vec[2])*vec[1]))) ; +} + +static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "squeeze", in, out); +} + +void register_node_type_sh_squeeze(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_squeeze_in, sh_node_squeeze_out); + node_type_size(&ntype, 120, 110, 160); + node_type_storage(&ntype, "node_squeeze", NULL, NULL); + node_type_exec(&ntype, node_shader_exec_squeeze); + node_type_gpu(&ntype, gpu_shader_squeeze); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c new file mode 100644 index 00000000000..a4957d8f683 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -0,0 +1,149 @@ +/* + * $Id: SHD_texture.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_texture.c + * \ingroup shdnodes + */ + + +#include "DNA_texture_types.h" + +#include "node_shader_util.h" + +/* **************** TEXTURE ******************** */ +static bNodeSocketTemplate sh_node_texture_in[]= { + { SOCK_VECTOR, 1, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, /* no limit */ + { -1, 0, "" } +}; +static bNodeSocketTemplate sh_node_texture_out[]= { + { SOCK_FLOAT, 0, "Value"}, + { SOCK_RGBA , 0, "Color"}, + { SOCK_VECTOR, 0, "Normal"}, + { -1, 0, "" } +}; + +static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + if(data && node->id) { + ShadeInput *shi= ((ShaderCallData *)data)->shi; + TexResult texres; + float vec[3], nor[3]={0.0f, 0.0f, 0.0f}; + int retval; + short which_output = node->custom1; + + short thread = shi->thread; + + /* out: value, color, normal */ + + /* we should find out if a normal as output is needed, for now we do all */ + texres.nor= nor; + texres.tr= texres.tg= texres.tb= 0.0f; + + if(in[0]->hasinput) { + nodestack_get_vec(vec, SOCK_VECTOR, in[0]); + + if(in[0]->datatype==NS_OSA_VECTORS) { + float *fp= in[0]->data; + retval= multitex_nodes((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output, NULL, NULL); + } + else if(in[0]->datatype==NS_OSA_VALUES) { + float *fp= in[0]->data; + float dxt[3], dyt[3]; + + dxt[0]= fp[0]; dxt[1]= dxt[2]= 0.0f; + dyt[0]= fp[1]; dyt[1]= dyt[2]= 0.0f; + retval= multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL); + } + else + retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL); + } + else { + VECCOPY(vec, shi->lo); + retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL); + } + + /* stupid exception */ + if( ((Tex *)node->id)->type==TEX_STUCCI) { + texres.tin= 0.5f + 0.7f*texres.nor[0]; + CLAMP(texres.tin, 0.0f, 1.0f); + } + + /* intensity and color need some handling */ + if(texres.talpha) + out[0]->vec[0]= texres.ta; + else + out[0]->vec[0]= texres.tin; + + if((retval & TEX_RGB)==0) { + out[1]->vec[0]= out[0]->vec[0]; + out[1]->vec[1]= out[0]->vec[0]; + out[1]->vec[2]= out[0]->vec[0]; + out[1]->vec[3]= 1.0f; + } + else { + out[1]->vec[0]= texres.tr; + out[1]->vec[1]= texres.tg; + out[1]->vec[2]= texres.tb; + out[1]->vec[3]= 1.0f; + } + + VECCOPY(out[2]->vec, nor); + + if(shi->do_preview) + nodeAddToPreview(node, out[1]->vec, shi->xs, shi->ys, shi->do_manage); + + } +} + +static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + Tex *tex = (Tex*)node->id; + + if(tex && tex->type == TEX_IMAGE && tex->ima) { + GPUNodeLink *texlink = GPU_image(tex->ima, NULL); + return GPU_stack_link(mat, "texture_image", in, out, texlink); + } + else + return 0; +} + +void register_node_type_sh_texture(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); + node_type_socket_templates(&ntype, sh_node_texture_in, sh_node_texture_out); + node_type_size(&ntype, 120, 80, 240); + node_type_exec(&ntype, node_shader_exec_texture); + node_type_gpu(&ntype, gpu_shader_texture); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c new file mode 100644 index 00000000000..9353143095a --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c @@ -0,0 +1,129 @@ +/* + * $Id: SHD_valToRgb.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_valToRgb.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** VALTORGB ******************** */ +static bNodeSocketTemplate sh_node_valtorgb_in[]= { + { SOCK_FLOAT, 1, "Fac", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { -1, 0, "" } +}; +static bNodeSocketTemplate sh_node_valtorgb_out[]= { + { SOCK_RGBA, 0, "Color"}, + { SOCK_FLOAT, 0, "Alpha"}, + { -1, 0, "" } +}; + +static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order in: fac */ + /* stack order out: col, alpha */ + + if(node->storage) { + float fac; + nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); + + do_colorband(node->storage, fac, out[0]->vec); + out[1]->vec[0]= out[0]->vec[3]; + } +} + +static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + node->storage= add_colorband(1); +} + +static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + colorband_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array)); +} + +void register_node_type_sh_valtorgb(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out); + node_type_size(&ntype, 240, 200, 300); + node_type_init(&ntype, node_shader_init_valtorgb); + node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, node_shader_exec_valtorgb); + node_type_gpu(&ntype, gpu_shader_valtorgb); + + nodeRegisterType(lb, &ntype); +} + + +/* **************** RGBTOBW ******************** */ +static bNodeSocketTemplate sh_node_rgbtobw_in[]= { + { SOCK_RGBA, 1, "Color", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketTemplate sh_node_rgbtobw_out[]= { + { SOCK_FLOAT, 0, "Val", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + + +static void node_shader_exec_rgbtobw(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) +{ + /* stack order out: bw */ + /* stack order in: col */ + + out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f; +} + +static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "rgbtobw", in, out); +} + +void register_node_type_sh_rgbtobw(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, sh_node_rgbtobw_in, sh_node_rgbtobw_out); + node_type_size(&ntype, 80, 40, 120); + node_type_exec(&ntype, node_shader_exec_rgbtobw); + node_type_gpu(&ntype, gpu_shader_rgbtobw); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_value.c b/source/blender/nodes/shader/nodes/node_shader_value.c new file mode 100644 index 00000000000..21ff565306d --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_value.c @@ -0,0 +1,82 @@ +/* + * $Id: SHD_value.c 36536 2011-05-07 13:27:27Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_value.c + * \ingroup shdnodes + */ + + +#include "node_shader_util.h" + +/* **************** VALUE ******************** */ +static bNodeSocketTemplate sh_node_value_out[]= { + { SOCK_FLOAT, 0, "Value"}, + { -1, 0, "" } +}; + +static void node_shader_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + bNodeSocket *sock= node->outputs.first; + bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value; + /* uses the default value of the output socket, must be initialized here */ + dval->value = 0.5f; +} + +static void node_shader_exec_value(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) +{ + bNodeSocket *sock= node->outputs.first; + float val= ((bNodeSocketValueFloat*)sock->default_value)->value; + + out[0]->vec[0]= val; +} + +static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + float *val= &((bNodeSocketValueFloat*)sock->default_value)->value; + GPUNodeLink *vec = GPU_uniform(val); + + return GPU_stack_link(mat, "set_value", in, out, vec); +} + +void register_node_type_sh_value(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS); + node_type_socket_templates(&ntype, NULL, sh_node_value_out); + node_type_init(&ntype, node_shader_init_value); + node_type_size(&ntype, 80, 50, 120); + node_type_exec(&ntype, node_shader_exec_value); + node_type_gpu(&ntype, gpu_shader_value); + + nodeRegisterType(lb, &ntype); +} + + diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c new file mode 100644 index 00000000000..c6a081431a2 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c @@ -0,0 +1,150 @@ +/* + * $Id: SHD_vectMath.c 36593 2011-05-10 11:19:26Z lukastoenne $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_vectMath.c + * \ingroup shdnodes + */ + + + +#include "node_shader_util.h" + + +/* **************** VECTOR MATH ******************** */ +static bNodeSocketTemplate sh_node_vect_math_in[]= { + { SOCK_VECTOR, 1, "Vector", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_VECTOR, 1, "Vector", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_vect_math_out[]= { + { SOCK_VECTOR, 0, "Vector"}, + { SOCK_FLOAT, 0, "Value"}, + { -1, 0, "" } +}; + +static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ + float vec1[3], vec2[3]; + + nodestack_get_vec(vec1, SOCK_VECTOR, in[0]); + nodestack_get_vec(vec2, SOCK_VECTOR, in[1]); + + if(node->custom1 == 0) { /* Add */ + out[0]->vec[0]= vec1[0] + vec2[0]; + out[0]->vec[1]= vec1[1] + vec2[1]; + out[0]->vec[2]= vec1[2] + vec2[2]; + + out[1]->vec[0]= (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; + } + else if(node->custom1 == 1) { /* Subtract */ + out[0]->vec[0]= vec1[0] - vec2[0]; + out[0]->vec[1]= vec1[1] - vec2[1]; + out[0]->vec[2]= vec1[2] - vec2[2]; + + out[1]->vec[0]= (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; + } + else if(node->custom1 == 2) { /* Average */ + out[0]->vec[0]= vec1[0] + vec2[0]; + out[0]->vec[1]= vec1[1] + vec2[1]; + out[0]->vec[2]= vec1[2] + vec2[2]; + + out[1]->vec[0] = normalize_v3( out[0]->vec ); + } + else if(node->custom1 == 3) { /* Dot product */ + out[1]->vec[0]= (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) + (vec1[2] * vec2[2]); + } + else if(node->custom1 == 4) { /* Cross product */ + out[0]->vec[0]= (vec1[1] * vec2[2]) - (vec1[2] * vec2[1]); + out[0]->vec[1]= (vec1[2] * vec2[0]) - (vec1[0] * vec2[2]); + out[0]->vec[2]= (vec1[0] * vec2[1]) - (vec1[1] * vec2[0]); + + out[1]->vec[0] = normalize_v3( out[0]->vec ); + } + else if(node->custom1 == 5) { /* Normalize */ + if(in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0]= vec1[0]; + out[0]->vec[1]= vec1[1]; + out[0]->vec[2]= vec1[2]; + } + else { + out[0]->vec[0]= vec2[0]; + out[0]->vec[1]= vec2[1]; + out[0]->vec[2]= vec2[2]; + } + + out[1]->vec[0] = normalize_v3( out[0]->vec ); + } + +} + +static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static const char *names[] = {"vec_math_add", "vec_math_sub", + "vec_math_average", "vec_math_dot", "vec_math_cross", + "vec_math_normalize"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 4: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 5: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + +void register_node_type_sh_vect_math(ListBase *lb) +{ + static bNodeType ntype; + + node_type_base(&ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, sh_node_vect_math_in, sh_node_vect_math_out); + node_type_size(&ntype, 80, 75, 140); + node_type_label(&ntype, node_vect_math_label); + node_type_storage(&ntype, "node_vect_math", NULL, NULL); + node_type_exec(&ntype, node_shader_exec_vect_math); + node_type_gpu(&ntype, gpu_shader_vect_math); + + nodeRegisterType(lb, &ntype); +} + + |