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:
Diffstat (limited to 'source/blender/nodes/intern/SHD_nodes')
-rw-r--r--source/blender/nodes/intern/SHD_nodes/Makefile5
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_camera.c10
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_curves.c24
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c808
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_geom.c16
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c11
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_invert.c8
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_mapping.c17
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_material.c82
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_math.c61
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c14
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_normal.c11
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_output.c16
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_rgb.c11
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c16
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c8
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_texture.c17
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c20
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_value.c9
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c31
20 files changed, 1024 insertions, 171 deletions
diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile
index ca83c25d277..1369d346fc6 100644
--- a/source/blender/nodes/intern/SHD_nodes/Makefile
+++ b/source/blender/nodes/intern/SHD_nodes/Makefile
@@ -35,6 +35,8 @@ include nan_compile.mk
CFLAGS += $(LEVEL_1_C_WARNINGS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I../../../python
CPPFLAGS += -I../../../blenkernel
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I../../../makesdna
@@ -42,3 +44,6 @@ CPPFLAGS += -I../../../blenlib
CPPFLAGS += -I../../../editors/include
CPPFLAGS += -I../../../imbuf
CPPFLAGS += -I../../../render/extern/include
+CPPFLAGS += -I../../../gpu
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c
index 63260ff91ed..20136d75540 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c
@@ -46,8 +46,13 @@ static void node_shader_exec_camera(void *data, bNode *node, bNodeStack **in, bN
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(out[0]->vec); /* get view distance */
- }
}
+}
+
+static int gpu_shader_camera(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION));
+}
bNodeType sh_node_camera= {
/* *next,*prev */ NULL, NULL,
@@ -63,6 +68,7 @@ bNodeType sh_node_camera= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_camera
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c
index b6f1f8d52cd..d277547b636 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c
@@ -56,6 +56,15 @@ static void node_shader_init_curve_vec(bNode* node)
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));
+}
+
bNodeType sh_node_curve_vec= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_CURVE_VEC,
@@ -70,7 +79,8 @@ bNodeType sh_node_curve_vec= {
/* initfunc */ node_shader_init_curve_vec,
/* freestoragefunc */ node_free_curves,
/* copystoragefunc */ node_copy_curves,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_curve_vec
};
@@ -100,6 +110,15 @@ static void node_shader_init_curve_rgb(bNode *node)
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));
+}
+
bNodeType sh_node_curve_rgb= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_CURVE_RGB,
@@ -114,6 +133,7 @@ bNodeType sh_node_curve_rgb= {
/* initfunc */ node_shader_init_curve_rgb,
/* freestoragefunc */ node_free_curves,
/* copystoragefunc */ node_copy_curves,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_curve_rgb
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
index 1ba777a0533..4fcfe3a789a 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
@@ -27,221 +27,749 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifdef USE_PYNODES /* note: won't work without patch */
-
+#ifndef DISABLE_PYTHON
#include <Python.h>
+#include <compile.h>
#include <eval.h>
+#endif
#include "DNA_text_types.h"
#include "BKE_text.h"
+#include "BKE_utildefines.h"
+// XXX
+#if 0
+#ifndef DISABLE_PYTHON
#include "api2_2x/Node.h"
#include "api2_2x/gen_utils.h"
#include "BPY_extern.h"
+#endif
+#endif
#include "../SHD_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);
+
+#ifndef DISABLE_PYTHON
static PyObject *init_dynamicdict(void) {
- PyObject *newscriptdict= PyDict_New();
+ PyObject *newscriptdict;
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ newscriptdict= PyDict_New();
+
PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins());
EXPP_dict_set_item_str(newscriptdict, "__name__", PyString_FromString("__main__"));
+
+ PyGILState_Release(gilstate);
+
return newscriptdict;
}
+#endif
+
+static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id)
+{
+ bNodeType *ntype = list->first;
-static void free_dynamicdict(PyObject *dict) {
- if(dict!=NULL) {
- Py_DECREF(dict);
+ 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_init(bNode *node) {
- NodeScriptDict *nsd= MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
- int type= node->custom2;
- node->custom2= 0;
- node->storage= nsd;
- if(type>=NODE_DYNAMIC_MENU) {
- if(type==NODE_DYNAMIC_MENU) {
- nodeMakeDynamicType(node);
- node->custom1= SH_NODE_DYNAMIC_NEW;
- } else {
- node->custom1= SH_NODE_DYNAMIC_ADDEXIST;
+static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo)
+{
+ bNodeSocketType *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);
+ }
+ }
}
- node->id= node->typeinfo->id;
- nodeDynamicParse(node);
- } else {
- if(node->custom1== SH_NODE_DYNAMIC_LOADED) {
- nodeMakeDynamicType(node);
- nodeDynamicParse(node);
- } else if(node->custom1== SH_NODE_DYNAMIC_ADDEXIST)
- nodeDynamicParse(node);
}
}
-static void node_dynamic_free(bNode *node)
+static void node_dynamic_free_storage_cb(bNode *node)
{
- NodeScriptDict *nsd= (NodeScriptDict *)(node->storage);
- BPy_Node *pynode= nsd->node;
- Py_XDECREF(pynode);
- free_dynamicdict((PyObject *)(nsd->dict));
+#ifndef DISABLE_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;
}
-static void node_dynamic_copy(bNode *orig_node, bNode *new_node)
+/* Disable pynode when its script fails */
+static void node_dynamic_disable(bNode *node)
{
- NodeScriptDict *nsd= (NodeScriptDict *)(orig_node->storage);
- new_node->storage= MEM_dupallocN(orig_node->storage);
- if(nsd->node)
- Py_INCREF((PyObject *)(nsd->node));
- if(nsd->dict)
- Py_INCREF((PyObject *)(nsd->dict));
+ node->custom1 = 0;
+ node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
}
-static void node_dynamic_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) {
- BPy_Node *mynode = NULL;
- NodeScriptDict *nsd = NULL;
- PyObject *pyresult = NULL;
- PyObject *args = NULL;
- ShadeInput *shi= ((ShaderCallData *)data)->shi;
+/* Disable all pynodes using the given text (script) id */
+static void node_dynamic_disable_all_by_id(ID *id)
+{
+#ifndef DISABLE_PYTHON
+ Material *ma; /* XXX hardcoded for shaders */
- if(node->custom1==SH_NODE_DYNAMIC_NEW) {
- nodeDynamicParse(node);
- 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->id == id) {
+ nd->custom1 = 0;
+ nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR);
+ }
+ }
+ }
}
+#endif
+}
- if(node->custom2<0)
- return;
+static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb)
+{
+ bNodeLink *link, *next;
+ bNodeSocket *sock;
- if(node->custom1==SH_NODE_DYNAMIC_READY || node->custom1==SH_NODE_DYNAMIC_UPDATED) {
- if(node->custom1== SH_NODE_DYNAMIC_UPDATED)
- node->custom1= SH_NODE_DYNAMIC_READY;
+ if (!lb) return;
- nsd = (NodeScriptDict *)node->storage;
+ 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);
+ }
+ }
+ }
+}
- mynode = (BPy_Node *)(nsd->node);
- if(mynode && PyCallable_Check((PyObject *)mynode)) {
- mynode->node= node;
- 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);
- if(!pyresult) {
- if(PyErr_Occurred()) {
- PyErr_Print();
- node->custom2= -1;
- } else {
- printf("PyObject_Call __call__ failed\n");
+/* 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);
}
}
- Py_XDECREF(pyresult);
- Py_DECREF(args);
}
}
}
-void nodeDynamicParse(struct bNode *node)
+/* 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)
+{
+#ifndef DISABLE_PYTHON
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
+ if (PyErr_Occurred()) { PyErr_Print(); }
+ 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);
+}
+
+#ifndef DISABLE_PYTHON
+/* node_dynamic_get_pynode:
+ * Find the pynode definition from the script */
+static PyObject *node_dynamic_get_pynode(PyObject *dict)
{
- BPy_Node *pynode= NULL;
- PyObject *dict= NULL;
PyObject *key= NULL;
- PyObject *value= NULL;
- PyObject *testinst= 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 /* DISABLE_PYTHON */
+
+static int node_dynamic_parse(struct bNode *node)
+{
+#ifdef DISABLE_PYTHON
+ return -1;
+#else
+ PyObject *dict= NULL;
+ PyObject *pynode_data= NULL;
+ PyObject *pynode= NULL;
PyObject *args= NULL;
- int pos = 0;
- NodeScriptDict *nsd= NULL;
+ NodeScriptDict *nsd = NULL;
PyObject *pyresult = NULL;
- PyObject *pycompiled = NULL;
- Text *txt = NULL;
- char *buf= 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)
+{
+#ifndef DISABLE_PYTHON
+ NodeScriptDict *nsd = NULL;
+ bNodeTree *nodetree = NULL;
+ bNodeType *ntype = NULL;
+ PyGILState_STATE gilstate;
- if(! node->id) {
+ /* 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;
}
- if(node->custom1!=SH_NODE_DYNAMIC_READY) {
- txt = (Text *)node->id;
- nsd = (NodeScriptDict *)node->storage;
+ /* 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(nsd->dict==NULL && (node->custom1==SH_NODE_DYNAMIC_NEW||node->custom1==SH_NODE_DYNAMIC_LOADED)) {
- nsd->dict= init_dynamicdict();
- } else if(nsd->dict==NULL && node->custom1==SH_NODE_DYNAMIC_ADDEXIST) {
- nsd->dict= node->typeinfo->pydict;
- nsd->node= node->typeinfo->pynode;
- Py_INCREF((PyObject *)(nsd->dict));
- Py_INCREF((PyObject *)(nsd->node));
- node->custom1= SH_NODE_DYNAMIC_READY;
+ 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;
}
- dict= (PyObject *)(nsd->dict);
+ }
+ 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->custom1!=SH_NODE_DYNAMIC_ADDEXIST) {
- buf = txt_to_buf( txt );
- /*printf("Running script (%s, %d)...", node->name, node->custom1);*/
- pyresult = PyRun_String(buf, Py_file_input, dict, dict);
- /*printf(" done\n");*/
+ if (node->storage)
+ fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n");
- MEM_freeN(buf);
+ 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(!pyresult) {
- if(PyErr_Occurred()) {
- PyErr_Print();
- }
- Py_XDECREF(pyresult);
- return;
+ 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;
+ }
+ }
- Py_DECREF(pyresult);
+ /* 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;
- while(PyDict_Next( (PyObject *)(nsd->dict), &pos, &key, &value) ) {
- if(PyObject_TypeCheck(value, &PyType_Type)==1) {
- BPy_DefinitionMap *outputdef= Node_CreateOutputDefMap(node);
- BPy_DefinitionMap *inputdef= Node_CreateInputDefMap(node);
-
- args= Py_BuildValue("(OO)", inputdef, outputdef);
- testinst= PyObject_Call(value, args, NULL);
-
- Py_DECREF(outputdef);
- Py_DECREF(inputdef);
- if(testinst && PyObject_TypeCheck(testinst, &Node_Type)==1) {
- Py_INCREF(testinst);
- Py_INCREF(dict);
- InitNode((BPy_Node *)(testinst), node);
- nsd->node= testinst;
- node->typeinfo->execfunc= node_dynamic_exec;
- if(node->custom1== SH_NODE_DYNAMIC_NEW || node->custom1== SH_NODE_DYNAMIC_LOADED) {
- node->typeinfo->pynode= testinst;
- node->typeinfo->pydict= nsd->dict;
- node->typeinfo->id= node->id;
- nodeAddSockets(node, node->typeinfo);
- nodeRegisterType(&node_all_shaders, node->typeinfo);
- node->custom1= SH_NODE_DYNAMIC_READY;
- }
- break;
- }
- Py_DECREF(args);
- }
- }
+ 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 /* DISABLE_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)
+{
+#ifdef DISABLE_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) {
+#ifdef DISABLE_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);
-bNodeType sh_node_dynamic = {
+ 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
+}
+
+bNodeType node_dynamic_typeinfo = {
/* next, prev */ NULL, NULL,
- /* type code */ SH_NODE_DYNAMIC,
+ /* type code */ NODE_DYNAMIC,
/* name */ "Dynamic",
/* width+range */ 150, 60, 300,
/* class+opts */ NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS,
/* input sock */ NULL,
/* output sock */ NULL,
/* storage */ "NodeScriptDict",
- /* execfunc */ node_dynamic_exec,
+ /* execfunc */ node_dynamic_exec_cb,
/* butfunc */ NULL,
- /* initfunc */ node_dynamic_init,
- /* freefunc */ node_dynamic_free,
- /* copyfunc */ node_dynamic_copy,
+ /* initfunc */ node_dynamic_init_cb,
+ /* freefunc */ node_dynamic_free_storage_cb,
+ /* copyfunc */ node_dynamic_copy_cb,
/* id */ NULL
};
-#endif /* USE_PYNODES */
+#else
+
+bNodeType node_dynamic_typeinfo = {NULL};
+
+#endif
+
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
index 24395059c60..bc345759b98 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
@@ -29,6 +29,7 @@
#include "../SHD_util.h"
+#include "DNA_customdata_types.h"
/* **************** GEOMETRY ******************** */
@@ -124,6 +125,18 @@ static void node_shader_init_geometry(bNode *node)
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 */
bNodeType sh_node_geom= {
/* *next,*prev */ NULL, NULL,
@@ -139,6 +152,7 @@ bNodeType sh_node_geom= {
/* initfunc */ node_shader_init_geometry,
/* freestoragefunc */ node_free_standard_storage,
/* copystoragefunc */ node_copy_standard_storage,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_geom
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c
index 8c07a2d1dc8..1b7b2dfb8e7 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c
@@ -54,9 +54,7 @@ static void do_hue_sat_fac(bNode *node, float *out, float *hue, float *sat, floa
hsv[0]+= (*hue - 0.5f);
if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
hsv[1]*= *sat;
- if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
hsv[2]*= *val;
- if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0;
hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
out[0]= mfac*in[0] + *fac*col[0];
@@ -73,6 +71,12 @@ static void node_shader_exec_hue_sat(void *data, bNode *node, bNodeStack **in, b
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 *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "hue_sat", in, out);
+}
+
bNodeType sh_node_hue_sat= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_HUE_SAT,
@@ -87,7 +91,8 @@ bNodeType sh_node_hue_sat= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_hue_sat
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c
index 4d1ce282fce..72ee1483ecf 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c
@@ -64,6 +64,11 @@ bNodeStack **out)
VECCOPY(out[0]->vec, col);
}
+static int gpu_shader_invert(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "invert", in, out);
+}
+
bNodeType sh_node_invert= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_INVERT,
@@ -78,6 +83,7 @@ bNodeType sh_node_invert= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_invert
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c
index 589954c8f7b..c081929a2fc 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c
@@ -69,6 +69,20 @@ static void node_shader_init_mapping(bNode *node)
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);
+}
+
bNodeType sh_node_mapping= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_MAPPING,
@@ -83,7 +97,8 @@ bNodeType sh_node_mapping= {
/* initfunc */ node_shader_init_mapping,
/* freestoragefunc */ node_free_standard_storage,
/* copystoragefunc */ node_copy_standard_storage,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_mapping
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c
index bdceb134c0d..c0a2534ac4a 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c
@@ -54,7 +54,6 @@ static bNodeSocketType sh_node_material_ext_in[]= {
{ SOCK_VALUE, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 1, "AmbCol", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 1, "Emit", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 1, "SpecTra", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
@@ -117,8 +116,6 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
if (node->type == SH_NODE_MATERIAL_EXT) {
if(in[MAT_IN_MIR]->hasinput)
nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]);
- if(in[MAT_IN_AMBCOL]->hasinput)
- nodestack_get_vec(&shi->ambr, SOCK_VECTOR, in[MAT_IN_AMBCOL]);
if(in[MAT_IN_AMB]->hasinput)
nodestack_get_vec(&shi->amb, SOCK_VALUE, in[MAT_IN_AMB]);
if(in[MAT_IN_EMIT]->hasinput)
@@ -185,6 +182,77 @@ static void node_shader_init_material(bNode* node)
node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC;
}
+static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ if(node->id) {
+ GPUShadeInput shi;
+ GPUShadeResult shr;
+
+ GPU_shadeinput_set(mat, (Material*)node->id, &shi);
+
+ /* write values */
+ if(in[MAT_IN_COLOR].hasinput)
+ shi.rgb = in[MAT_IN_COLOR].link;
+
+ if(in[MAT_IN_SPEC].hasinput)
+ shi.specrgb = in[MAT_IN_SPEC].link;
+
+ if(in[MAT_IN_REFL].hasinput)
+ shi.refl = in[MAT_IN_REFL].link;
+
+ /* retrieve normal */
+ if(in[MAT_IN_NORMAL].hasinput) {
+ GPUNodeLink *tmp;
+ shi.vn = in[MAT_IN_NORMAL].link;
+ 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(in[MAT_IN_AMB].hasinput)
+ shi.amb= in[MAT_IN_AMB].link;
+ if(in[MAT_IN_EMIT].hasinput)
+ shi.emit= in[MAT_IN_EMIT].link;
+ if(in[MAT_IN_ALPHA].hasinput)
+ shi.alpha= in[MAT_IN_ALPHA].link;
+ }
+
+ GPU_shaderesult_set(&shi, &shr); /* clears shr */
+
+ /* write to outputs */
+ if(node->custom1 & SH_NODE_MAT_DIFF) {
+ if(node->custom1 & SH_NODE_MAT_SPEC)
+ out[MAT_OUT_COLOR].link= shr.combined;
+ else
+ out[MAT_OUT_COLOR].link= shr.diff;
+ }
+ 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;
+}
bNodeType sh_node_material= {
/* *next,*prev */ NULL, NULL,
@@ -200,8 +268,8 @@ bNodeType sh_node_material= {
/* initfunc */ node_shader_init_material,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
-
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_material
};
bNodeType sh_node_material_ext= {
@@ -218,7 +286,7 @@ bNodeType sh_node_material_ext= {
/* initfunc */ node_shader_init_material,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
-
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_material
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_math.c b/source/blender/nodes/intern/SHD_nodes/SHD_math.c
index 95162e508d5..050c2cdcc95 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_math.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_math.c
@@ -174,10 +174,66 @@ bNodeStack **out)
else
out[0]->vec[0]= (int)(in[1]->vec[0] + 0.5f);
}
- break;
+ 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 char *names[] = {"math_add", "math_subtract", "math_multiply",
+ "math_divide", "math_sine", "math_cosine", "math_tangnet", "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;
+}
+
bNodeType sh_node_math= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_MATH,
@@ -192,6 +248,7 @@ bNodeType sh_node_math= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_math
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c
index dba70253fda..2da1dee5623 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c
@@ -60,6 +60,17 @@ static void node_shader_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, b
VECCOPY(out[0]->vec, col);
}
+static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ static 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"};
+
+ return GPU_stack_link(mat, names[node->custom1], in, out);
+}
+
+
bNodeType sh_node_mix_rgb= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_MIX_RGB,
@@ -74,6 +85,7 @@ bNodeType sh_node_mix_rgb= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_mix_rgb
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c
index f1ffd3446af..9d4ea1ccf67 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c
@@ -57,6 +57,14 @@ static void node_shader_exec_normal(void *data, bNode *node, bNodeStack **in, bN
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(sock->ns.vec);
+
+ return GPU_stack_link(mat, "normal", in, out, vec);
+}
+
bNodeType sh_node_normal= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_NORMAL,
@@ -71,6 +79,7 @@ bNodeType sh_node_normal= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_normal
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_output.c b/source/blender/nodes/intern/SHD_nodes/SHD_output.c
index 0a9a30c452b..76856cfd2e8 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_output.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_output.c
@@ -62,6 +62,19 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN
}
}
+static int gpu_shader_output(GPUMaterial *mat, bNode *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;
+}
+
bNodeType sh_node_output= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_OUTPUT,
@@ -76,7 +89,8 @@ bNodeType sh_node_output= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_output
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c
index 4e56e26d3ad..1aa1a2ffc33 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c
@@ -42,6 +42,14 @@ static void node_shader_exec_rgb(void *data, bNode *node, bNodeStack **in, bNode
VECCOPY(out[0]->vec, sock->ns.vec);
}
+static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ bNodeSocket *sock= node->outputs.first;
+ GPUNodeLink *vec = GPU_uniform(sock->ns.vec);
+
+ return GPU_stack_link(mat, "set_rgba", in, out, vec);
+}
+
bNodeType sh_node_rgb= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_RGB,
@@ -56,6 +64,7 @@ bNodeType sh_node_rgb= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_rgb
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c
index 2b52a8e2229..6d5df2a1321 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c
@@ -48,6 +48,11 @@ static void node_shader_exec_seprgb(void *data, bNode *node, bNodeStack **in, bN
out[2]->vec[0] = in[0]->vec[2];
}
+static int gpu_shader_seprgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "separate_rgb", in, out);
+}
+
bNodeType sh_node_seprgb= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_SEPRGB,
@@ -62,7 +67,8 @@ bNodeType sh_node_seprgb= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_seprgb
};
@@ -86,6 +92,11 @@ static void node_shader_exec_combrgb(void *data, bNode *node, bNodeStack **in, b
out[0]->vec[2] = in[2]->vec[0];
}
+static int gpu_shader_combrgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "combine_rgb", in, out);
+}
+
bNodeType sh_node_combrgb= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_COMBRGB,
@@ -100,6 +111,7 @@ bNodeType sh_node_combrgb= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_combrgb
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c
index 30abad666c4..d3480a6ae9d 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c
@@ -54,6 +54,11 @@ bNodeStack **out)
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 *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "squeeze", in, out);
+}
+
bNodeType sh_node_squeeze= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_SQUEEZE,
@@ -68,6 +73,7 @@ bNodeType sh_node_squeeze= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_squeeze
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c
index ace11a20d42..31dbde940fd 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c
@@ -27,6 +27,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include "DNA_texture_types.h"
+
#include "../SHD_util.h"
/* **************** TEXTURE ******************** */
@@ -110,6 +112,18 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
}
}
+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;
+}
+
bNodeType sh_node_texture= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_TEXTURE,
@@ -124,7 +138,8 @@ bNodeType sh_node_texture= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_texture
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c
index cf7e33d9dca..301c0cb7031 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c
@@ -59,6 +59,15 @@ static void node_shader_init_valtorgb(bNode *node)
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));
+}
+
bNodeType sh_node_valtorgb= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_VALTORGB,
@@ -73,7 +82,8 @@ bNodeType sh_node_valtorgb= {
/* initfunc */ node_shader_init_valtorgb,
/* freestoragefunc */ node_free_standard_storage,
/* copystoragefunc */ node_copy_standard_storage,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_valtorgb
};
@@ -96,6 +106,11 @@ static void node_shader_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, b
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 *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "rgbtobw", in, out);
+}
+
bNodeType sh_node_rgbtobw= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_RGBTOBW,
@@ -110,7 +125,8 @@ bNodeType sh_node_rgbtobw= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_rgbtobw
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_value.c b/source/blender/nodes/intern/SHD_nodes/SHD_value.c
index 57ef7226066..768ef3cda3d 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_value.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_value.c
@@ -42,7 +42,13 @@ static void node_shader_exec_value(void *data, bNode *node, bNodeStack **in, bNo
out[0]->vec[0]= sock->ns.vec[0];
}
+static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ bNodeSocket *sock= node->outputs.first;
+ GPUNodeLink *vec = GPU_uniform(sock->ns.vec);
+ return GPU_stack_link(mat, "set_value", in, out, vec);
+}
bNodeType sh_node_value= {
/* *next,*prev */ NULL, NULL,
@@ -58,7 +64,8 @@ bNodeType sh_node_value= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_value
};
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c
index 8d0a4b3abe3..96db8db18a6 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c
@@ -99,6 +99,34 @@ static void node_shader_exec_vect_math(void *data, bNode *node, bNodeStack **in,
}
+static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+{
+ static char *names[] = {"vec_math_add", "vec_math_subtract",
+ "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;
+}
+
bNodeType sh_node_vect_math= {
/* *next,*prev */ NULL, NULL,
/* type code */ SH_NODE_VECT_MATH,
@@ -113,6 +141,7 @@ bNodeType sh_node_vect_math= {
/* initfunc */ NULL,
/* freestoragefunc */ NULL,
/* copystoragefunc */ NULL,
- /* id */ NULL
+ /* id */ NULL, NULL, NULL,
+ /* gpufunc */ gpu_shader_vect_math
};