diff options
Diffstat (limited to 'source/blender/nodes/intern/SHD_nodes')
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 }; |