Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Toenne <lukas.toenne@googlemail.com>2011-09-06 01:01:50 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2011-09-06 01:01:50 +0400
commit8e0fe8bff72e2dc2926618577eaffdd3417a8304 (patch)
tree43b933c88cac451518dc68846c1119acacffca4f /source/blender/nodes/shader
parent6e9ff495eb082aeb49e6a1da23a7827d3fcd0fde (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')
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c212
-rw-r--r--source/blender/nodes/shader/node_shader_util.c287
-rw-r--r--source/blender/nodes/shader/node_shader_util.h130
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_camera.c76
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c327
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.c142
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_dynamic.c792
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geom.c153
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hueSatVal.c99
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_invert.c90
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c104
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_material.c336
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c256
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c91
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal.c95
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output.c96
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_rgb.c84
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c112
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_squeeze.c81
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_texture.c149
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.c129
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_value.c82
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c150
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);
+}
+
+