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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2008-11-13 00:16:53 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2008-11-13 00:16:53 +0300
commitbdfe7d89e2f1292644577972c716931b4ce3c6c3 (patch)
treed00eb50b749cb001e2b08272c91791e66740b05d /source/blender/nodes
parent78a1c27c4a6abe0ed31ca93ad21910f3df04da56 (diff)
parent7e4db234cee71ead34ee81a12e27da4bd548eb4b (diff)
Merge of trunk into blender 2.5:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r12987:17416 Issues: * GHOST/X11 had conflicting changes. Some code was added in 2.5, which was later added in trunk also, but reverted partially, specifically revision 16683. I have left out this reversion in the 2.5 branch since I think it is needed there. http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16683 * Scons had various conflicting changes, I decided to go with trunk version for everything except priorities and some library renaming. * In creator.c, there were various fixes and fixes for fixes related to the -w -W and -p options. In 2.5 -w and -W is not coded yet, and -p is done differently. Since this is changed so much, and I don't think those fixes would be needed in 2.5, I've left them out. * Also in creator.c: there was code for a python bugfix where the screen was not initialized when running with -P. The code that initializes the screen there I had to disable, that can't work in 2.5 anymore but left it commented as a reminder. Further I had to disable some new function calls. using src/ and python/, as was done already in this branch, disabled function calls: * bpath.c: error reporting * BME_conversions.c: editmesh conversion functions. * SHD_dynamic: disabled almost completely, there is no python/. * KX_PythonInit.cpp and Ketsji/ build files: Mathutils is not there, disabled. * text.c: clipboard copy call. * object.c: OB_SUPPORT_MATERIAL. * DerivedMesh.c and subsurf_ccg, stipple_quarttone. Still to be done: * Go over files and functions that were moved to a different location but could still use changes that were done in trunk.
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/CMP_node.h3
-rw-r--r--source/blender/nodes/CMakeLists.txt5
-rw-r--r--source/blender/nodes/Makefile2
-rw-r--r--source/blender/nodes/SConscript40
-rw-r--r--source/blender/nodes/SHD_node.h2
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c57
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_bilateralblur.c272
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_blur.c17
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_brightness.c4
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_curves.c8
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_defocus.c31
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_directionalblur.c143
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_displace.c71
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_gamma.c5
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_glare.c18
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c2
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_idMask.c22
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_image.c54
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_math.c21
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_premulkey.c77
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_texture.c26
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c11
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c75
-rw-r--r--source/blender/nodes/intern/CMP_nodes/Makefile2
-rw-r--r--source/blender/nodes/intern/CMP_util.c193
-rw-r--r--source/blender/nodes/intern/CMP_util.h5
-rw-r--r--source/blender/nodes/intern/Makefile2
-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
-rw-r--r--source/blender/nodes/intern/SHD_util.c4
-rw-r--r--source/blender/nodes/intern/SHD_util.h15
49 files changed, 2054 insertions, 328 deletions
diff --git a/source/blender/nodes/CMP_node.h b/source/blender/nodes/CMP_node.h
index 4b7e721ca57..020bbdebfa2 100644
--- a/source/blender/nodes/CMP_node.h
+++ b/source/blender/nodes/CMP_node.h
@@ -66,6 +66,8 @@ extern bNodeType cmp_node_normalize;
extern bNodeType cmp_node_filter;
extern bNodeType cmp_node_blur;
+extern bNodeType cmp_node_dblur;
+extern bNodeType cmp_node_bilateralblur;
extern bNodeType cmp_node_vecblur;
extern bNodeType cmp_node_dilateerode;
extern bNodeType cmp_node_defocus;
@@ -83,6 +85,7 @@ extern bNodeType cmp_node_sepyuva;
extern bNodeType cmp_node_combyuva;
extern bNodeType cmp_node_sepycca;
extern bNodeType cmp_node_combycca;
+extern bNodeType cmp_node_premulkey;
extern bNodeType cmp_node_diff_matte;
extern bNodeType cmp_node_chroma;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 0be26622536..7f003cb2b42 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -26,13 +26,14 @@
FILE(GLOB SRC intern/*.c intern/CMP_nodes/*.c intern/SHD_nodes/*.c)
SET(INC
- . ../../../intern/guardedalloc ../include ../blenlib ../makesdna
+ . ../../../intern/guardedalloc ../editors/include ../blenlib ../makesdna
../python ../render/extern/include ../../../intern/decimation/extern
../imbuf ../avi ../../../intern/elbeem/extern
../../../intern/iksolver/extern ../blenloader ../quicktime
- ../blenkernel ../editors/include
+ ../blenkernel ../../../extern/glew/include ../gpu
${SDL_INC}
${ZLIB_INC}
+ ${PYTHON_INC}
)
IF(WITH_VERSE)
diff --git a/source/blender/nodes/Makefile b/source/blender/nodes/Makefile
index 65a0e591848..57f57ebebfe 100644
--- a/source/blender/nodes/Makefile
+++ b/source/blender/nodes/Makefile
@@ -6,7 +6,7 @@
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
+# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript
index 746be45eb91..5f7f29dab83 100644
--- a/source/blender/nodes/SConscript
+++ b/source/blender/nodes/SConscript
@@ -7,40 +7,44 @@ sources += env.Glob('intern/SHD_nodes/*.c')
incs = '. ./intern '
incs += '#/intern/guardedalloc ../editors/include ../blenlib ../makesdna'
-incs += ' ../python ../render/extern/include '
+incs += ' ../render/extern/include '
incs += ' ../imbuf ../avi '
-incs += ' ../blenloader ../quicktime'
+incs += ' ../blenloader'
incs += ' ../blenkernel ../renderconverter '
-
-
+incs += ' ../gpu #/extern/glew/include '
incs += ' ' + env['BF_OPENGL_INC']
incs += ' ' + env['BF_ZLIB_INC']
-incs += ' ' + env['BF_SDL_INC']
defs = ''
+if env['WITH_BF_PYTHON']:
+ incs += ' ' + env['BF_PYTHON_INC']
+ incs += ' ../python'
+else:
+ defs += 'DISABLE_PYTHON'
+
if env['WITH_BF_INTERNATIONAL']:
- defs += 'WITH_FREETYPE2'
+ defs += ' WITH_FREETYPE2'
if env['WITH_BF_VERSE']:
- defs += ' WITH_VERSE'
- incs += ' ' + env['BF_VERSE_INCLUDE']
+ defs += ' WITH_VERSE'
+ incs += ' ' + env['BF_VERSE_INCLUDE']
if env['WITH_BF_VERSE']:
- defs += ' WITH_VERSE'
+ defs += ' WITH_VERSE'
-if env['WITH_BF_OPENEXR'] == 1:
- defs += ' WITH_OPENEXR'
+if env['WITH_BF_OPENEXR']:
+ defs += ' WITH_OPENEXR'
-if env['WITH_BF_FFMPEG'] == 1:
- defs += ' WITH_FFMPEG'
- incs += ' ' + env['BF_FFMPEG_INC']
+if env['WITH_BF_FFMPEG']:
+ defs += ' WITH_FFMPEG'
+ incs += ' ' + env['BF_FFMPEG_INC']
-if env['WITH_BF_QUICKTIME'] == 1:
- defs += ' WITH_QUICKTIME'
- incs += ' ' + env['BF_QUICKTIME_INC']
+if env['WITH_BF_QUICKTIME']:
+ defs += ' WITH_QUICKTIME'
+ incs += ' ' + env['BF_QUICKTIME_INC']
-defs += ' WITH_CCGSUBSURF'
+defs += ' WITH_CCGSUBSURF '
env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core','player'], priority = [80, 15] )
diff --git a/source/blender/nodes/SHD_node.h b/source/blender/nodes/SHD_node.h
index 8064a543ca0..d75d7c9f568 100644
--- a/source/blender/nodes/SHD_node.h
+++ b/source/blender/nodes/SHD_node.h
@@ -56,13 +56,13 @@ extern bNodeType sh_node_curve_rgb;
extern bNodeType sh_node_math;
extern bNodeType sh_node_vect_math;
extern bNodeType sh_node_squeeze;
+extern bNodeType node_dynamic_typeinfo;
extern bNodeType sh_node_material_ext;
extern bNodeType sh_node_invert;
extern bNodeType sh_node_seprgb;
extern bNodeType sh_node_combrgb;
extern bNodeType sh_node_hue_sat;
-
#endif
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c b/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c
index f108098750c..4972ff4ae5a 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c
@@ -47,16 +47,16 @@ static void do_alphaover_premul(bNode *node, float *out, float *src, float *over
if(over[3]<=0.0f) {
QUATCOPY(out, src);
}
- else if(*fac==1.0f && over[3]>=1.0f) {
+ else if(fac[0]==1.0f && over[3]>=1.0f) {
QUATCOPY(out, over);
}
else {
- float mul= 1.0f - *fac*over[3];
+ float mul= 1.0f - fac[0]*over[3];
- out[0]= (mul*src[0]) + *fac*over[0];
- out[1]= (mul*src[1]) + *fac*over[1];
- out[2]= (mul*src[2]) + *fac*over[2];
- out[3]= (mul*src[3]) + *fac*over[3];
+ out[0]= (mul*src[0]) + fac[0]*over[0];
+ out[1]= (mul*src[1]) + fac[0]*over[1];
+ out[2]= (mul*src[2]) + fac[0]*over[2];
+ out[3]= (mul*src[3]) + fac[0]*over[3];
}
}
@@ -67,7 +67,7 @@ static void do_alphaover_key(bNode *node, float *out, float *src, float *over, f
if(over[3]<=0.0f) {
QUATCOPY(out, src);
}
- else if(*fac==1.0f && over[3]>=1.0f) {
+ else if(fac[0]==1.0f && over[3]>=1.0f) {
QUATCOPY(out, over);
}
else {
@@ -81,6 +81,31 @@ static void do_alphaover_key(bNode *node, float *out, float *src, float *over, f
}
}
+/* result will be still premul, but the over part is premulled */
+static void do_alphaover_mixed(bNode *node, float *out, float *src, float *over, float *fac)
+{
+
+ if(over[3]<=0.0f) {
+ QUATCOPY(out, src);
+ }
+ else if(fac[0]==1.0f && over[3]>=1.0f) {
+ QUATCOPY(out, over);
+ }
+ else {
+ NodeTwoFloats *ntf= node->storage;
+ float addfac= 1.0f - ntf->x + over[3]*ntf->x;
+ float premul= fac[0]*addfac;
+ float mul= 1.0f - fac[0]*over[3];
+
+ out[0]= (mul*src[0]) + premul*over[0];
+ out[1]= (mul*src[1]) + premul*over[1];
+ out[2]= (mul*src[2]) + premul*over[2];
+ out[3]= (mul*src[3]) + fac[0]*over[3];
+ }
+}
+
+
+
static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
@@ -97,8 +122,11 @@ static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **i
/* make output size of input image */
CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+ NodeTwoFloats *ntf= node->storage;
- if(node->custom1)
+ if(ntf->x != 0.0f)
+ composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_mixed, CB_RGBA, CB_RGBA, CB_VAL);
+ else if(node->custom1)
composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_key, CB_RGBA, CB_RGBA, CB_VAL);
else
composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_premul, CB_RGBA, CB_RGBA, CB_VAL);
@@ -107,6 +135,11 @@ static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **i
}
}
+static void node_alphaover_init(bNode* node)
+{
+ node->storage= MEM_callocN(sizeof(NodeTwoFloats), "NodeTwoFloats");
+}
+
bNodeType cmp_node_alphaover= {
/* *next,*prev */ NULL, NULL,
/* type code */ CMP_NODE_ALPHAOVER,
@@ -115,12 +148,12 @@ bNodeType cmp_node_alphaover= {
/* class+opts */ NODE_CLASS_OP_COLOR, NODE_OPTIONS,
/* input sock */ cmp_node_alphaover_in,
/* output sock */ cmp_node_alphaover_out,
- /* storage */ "",
+ /* storage */ "NodeTwoFloats",
/* execfunc */ node_composit_exec_alphaover,
/* butfunc */ NULL,
- /* initfunc */ NULL,
- /* freestoragefunc */ NULL,
- /* copystoragefunc */ NULL,
+ /* initfunc */ node_alphaover_init,
+ /* freestoragefunc */ node_free_standard_storage,
+ /* copystoragefunc */ node_copy_standard_storage,
/* id */ NULL
};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_bilateralblur.c b/source/blender/nodes/intern/CMP_nodes/CMP_bilateralblur.c
new file mode 100644
index 00000000000..b954e876ea1
--- /dev/null
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_bilateralblur.c
@@ -0,0 +1,272 @@
+/**
+ *
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Vilem Novak
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "../CMP_util.h"
+
+/* **************** BILATERALBLUR ******************** */
+static bNodeSocketType cmp_node_bilateralblur_in[]= {
+ { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "Determinator", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketType cmp_node_bilateralblur_out[]= {
+ { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+#define INIT_C3\
+ mean0 = 1; mean1[0] = src[0];mean1[1] = src[1];mean1[2] = src[2];mean1[3] = src[3];
+
+/* finds color distances */
+#define COLOR_DISTANCE_C3(c1, c2)\
+ ((c1[0] - c2[0])*(c1[0] - c2[0]) + \
+ (c1[1] - c2[1])*(c1[1] - c2[1]) + \
+ (c1[2] - c2[2])*(c1[2] - c2[2]) + \
+ (c1[3] - c2[3])*(c1[3] - c2[3]))
+
+/* this is the main kernel function for comparing color distances
+ and adding them weighted to the final color */
+#define KERNEL_ELEMENT_C3(k)\
+ temp_color = src + deltas[k];\
+ ref_color = ref + deltas[k];\
+ w = weight_tab[k] + COLOR_DISTANCE_C3(ref, ref_color )*i2sigma_color;\
+ w = 1./(w*w + 1); \
+ mean0 += w;\
+ mean1[0] += temp_color[0]*w; \
+ mean1[1] += temp_color[1]*w; \
+ mean1[2] += temp_color[2]*w; \
+ mean1[3] += temp_color[3]*w;
+
+/* write blurred values to image */
+#define UPDATE_OUTPUT_C3\
+ mean0 = 1./mean0;\
+ dest[x*pix + 0] = mean1[0]*mean0; \
+ dest[x*pix + 1] = mean1[1]*mean0; \
+ dest[x*pix + 2] = mean1[2]*mean0; \
+ dest[x*pix + 3] = mean1[3]*mean0;
+
+/* initializes deltas for fast access to neighbour pixels */
+#define INIT_3X3_DELTAS( deltas, step, nch ) \
+ ((deltas)[0] = (nch), (deltas)[1] = -(step) + (nch), \
+ (deltas)[2] = -(step), (deltas)[3] = -(step) - (nch), \
+ (deltas)[4] = -(nch), (deltas)[5] = (step) - (nch), \
+ (deltas)[6] = (step), (deltas)[7] = (step) + (nch));
+
+
+/* code of this node was heavily inspired by the smooth function of opencv library.
+The main change is an optional image input */
+static void node_composit_exec_bilateralblur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ NodeBilateralBlurData *nbbd= node->storage;
+ CompBuf *new, *source, *img= in[0]->data , *refimg= in[1]->data;
+ double mean0, w, i2sigma_color, i2sigma_space;
+ double mean1[4];
+ double weight_tab[8];
+ float *src, *dest, *ref, *temp_color, *ref_color;
+ float sigma_color, sigma_space;
+ int imgx, imgy, x, y, pix, i, step;
+ int deltas[8];
+ short found_determinator= 0;
+
+ if(img == NULL || out[0]->hasoutput == 0)
+ return;
+
+ if(img->type != CB_RGBA) {
+ img= typecheck_compbuf(in[0]->data, CB_RGBA);
+ }
+
+ imgx= img->x;
+ imgy= img->y;
+ pix= img->type;
+ step= pix * imgx;
+
+ if(refimg) {
+ if(refimg->x == imgx && refimg->y == imgy) {
+ if(ELEM3(refimg->type, CB_VAL, CB_VEC2, CB_VEC3)) {
+ refimg= typecheck_compbuf(in[1]->data, CB_RGBA);
+ found_determinator= 1;
+ }
+ }
+ }
+ else {
+ refimg= img;
+ }
+
+ /* allocs */
+ source= dupalloc_compbuf(img);
+ new= alloc_compbuf(imgx, imgy, pix, 1);
+
+ /* accept image offsets from other nodes */
+ new->xof= img->xof;
+ new->yof= img->yof;
+
+ /* bilateral code properties */
+ sigma_color= nbbd->sigma_color;
+ sigma_space= nbbd->sigma_space;
+
+ i2sigma_color= 1. / (sigma_color * sigma_color);
+ i2sigma_space= 1. / (sigma_space * sigma_space);
+
+ INIT_3X3_DELTAS(deltas, step, pix);
+
+ weight_tab[0] = weight_tab[2] = weight_tab[4] = weight_tab[6] = i2sigma_space;
+ weight_tab[1] = weight_tab[3] = weight_tab[5] = weight_tab[7] = i2sigma_space * 2;
+
+ /* iterations */
+ for(i= 0; i < nbbd->iter; i++) {
+ src= source->rect;
+ ref= refimg->rect;
+ dest= new->rect;
+ /*goes through image, there are more loops for 1st/last line and all other lines*/
+ /*kernel element accumulates surrounding colors, which are then written with the update_output function*/
+ for(x= 0; x < imgx; x++, src+= pix, ref+= pix) {
+ INIT_C3;
+
+ KERNEL_ELEMENT_C3(6);
+
+ if(x > 0) {
+ KERNEL_ELEMENT_C3(5);
+ KERNEL_ELEMENT_C3(4);
+ }
+
+ if(x < imgx - 1) {
+ KERNEL_ELEMENT_C3(7);
+ KERNEL_ELEMENT_C3(0);
+ }
+
+ UPDATE_OUTPUT_C3;
+ }
+
+ dest+= step;
+
+ for(y= 1; y < imgy - 1; y++, dest+= step, src+= pix, ref+= pix) {
+ x= 0;
+
+ INIT_C3;
+
+ KERNEL_ELEMENT_C3(0);
+ KERNEL_ELEMENT_C3(1);
+ KERNEL_ELEMENT_C3(2);
+ KERNEL_ELEMENT_C3(6);
+ KERNEL_ELEMENT_C3(7);
+
+ UPDATE_OUTPUT_C3;
+
+ src+= pix;
+ ref+= pix;
+
+ for(x= 1; x < imgx - 1; x++, src+= pix, ref+= pix) {
+ INIT_C3;
+
+ KERNEL_ELEMENT_C3(0);
+ KERNEL_ELEMENT_C3(1);
+ KERNEL_ELEMENT_C3(2);
+ KERNEL_ELEMENT_C3(3);
+ KERNEL_ELEMENT_C3(4);
+ KERNEL_ELEMENT_C3(5);
+ KERNEL_ELEMENT_C3(6);
+ KERNEL_ELEMENT_C3(7);
+
+ UPDATE_OUTPUT_C3;
+ }
+
+ INIT_C3;
+
+ KERNEL_ELEMENT_C3(2);
+ KERNEL_ELEMENT_C3(3);
+ KERNEL_ELEMENT_C3(4);
+ KERNEL_ELEMENT_C3(5);
+ KERNEL_ELEMENT_C3(6);
+
+ UPDATE_OUTPUT_C3;
+ }
+
+ for(x= 0; x < imgx; x++, src+= pix, ref+= pix) {
+ INIT_C3;
+
+ KERNEL_ELEMENT_C3(2);
+
+ if(x > 0) {
+ KERNEL_ELEMENT_C3(3);
+ KERNEL_ELEMENT_C3(4);
+ }
+ if(x < imgx - 1) {
+ KERNEL_ELEMENT_C3(1);
+ KERNEL_ELEMENT_C3(0);
+ }
+
+ UPDATE_OUTPUT_C3;
+ }
+
+ if(node->exec & NODE_BREAK) break;
+
+ SWAP(CompBuf, *source, *new);
+ }
+
+ if(node->exec & NODE_BREAK)
+ free_compbuf(source);
+
+ if(img != in[0]->data)
+ free_compbuf(img);
+
+ if(found_determinator == 1) {
+ if(refimg != in[1]->data)
+ free_compbuf(refimg);
+ }
+
+ out[0]->data= source;
+
+ free_compbuf(new);
+}
+
+static void node_composit_init_bilateralblur(bNode* node)
+{
+ NodeBilateralBlurData *nbbd= MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data");
+ node->storage= nbbd;
+ nbbd->sigma_color= 0.3;
+ nbbd->sigma_space= 5.0;
+}
+
+bNodeType cmp_node_bilateralblur= {
+ /* *next,*prev */ NULL, NULL,
+ /* type code */ CMP_NODE_BILATERALBLUR,
+ /* name */ "Bilateral Blur",
+ /* width+range */ 150, 120, 200,
+ /* class+opts */ NODE_CLASS_OP_FILTER, NODE_OPTIONS,
+ /* input sock */ cmp_node_bilateralblur_in,
+ /* output sock */ cmp_node_bilateralblur_out,
+ /* storage */ "NodeBilateralBlurData",
+ /* execfunc */ node_composit_exec_bilateralblur,
+ /* butfunc */ NULL,
+ /* initfunc */ node_composit_init_bilateralblur,
+ /* freestoragefunc */ node_free_standard_storage,
+ /* copystoragefunc */ node_copy_standard_storage,
+ /* id */ NULL
+
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c
index 8ef4af4d219..e7e799b6e76 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c
@@ -22,7 +22,8 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
+ * Juho Vepsäläinen
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -397,7 +398,7 @@ static void bokeh_single_image(bNode *node, CompBuf *new, CompBuf *img, float fa
int maxyr= y+rady>imgy-1?imgy-y-1:rady;
float *destd= new->rect + pix*( (y + minyr)*imgx + x + minxr);
- float *dgausd= gausstab + (minyr+rady)*2*radx + minxr+radx;
+ float *dgausd= gausstab + (minyr+rady)*(2*radx+1) + minxr+radx;
if(x<=0) src= srcd;
else if(x<imgx) src+= pix;
@@ -556,16 +557,20 @@ static void blur_with_reference(bNode *node, CompBuf *new, CompBuf *img, CompBuf
static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
CompBuf *new, *img= in[0]->data;
+ NodeBlurData *nbd= node->storage;
- if(img==NULL || out[0]->hasoutput==0)
- return;
+ if(img==NULL) return;
+
+ /* store image in size that is needed for absolute/relative conversions on ui level */
+ nbd->image_in_width= img->x;
+ nbd->image_in_height= img->y;
+
+ if(out[0]->hasoutput==0) return;
if (((NodeBlurData *)node->storage)->filtertype == R_FILTER_FAST_GAUSS) {
CompBuf *new, *img = in[0]->data;
/*from eeshlo's original patch, removed to fit in with the existing blur node */
/*const float sx = in[1]->vec[0], sy = in[2]->vec[0];*/
-
- NodeBlurData *nbd= node->storage;
const float sx = ((float)nbd->sizex)/2.0f, sy = ((float)nbd->sizey)/2.0f;
int c;
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_brightness.c b/source/blender/nodes/intern/CMP_nodes/CMP_brightness.c
index c87307434b5..f6363cc7ffa 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_brightness.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_brightness.c
@@ -35,8 +35,8 @@
static bNodeSocketType cmp_node_brightcontrast_in[]= {
{ SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
- { SOCK_VALUE, 1, "bright", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f},
- { SOCK_VALUE, 1, "contrast", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f},
+ { SOCK_VALUE, 1, "Bright", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f},
+ { SOCK_VALUE, 1, "Contrast", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f},
{ -1, 0, "" }
};
static bNodeSocketType cmp_node_brightcontrast_out[]= {
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_curves.c b/source/blender/nodes/intern/CMP_nodes/CMP_curves.c
index 17d9821a5ef..01af0e1db1d 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_curves.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_curves.c
@@ -22,7 +22,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Björn C. Schaefer
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -123,6 +123,8 @@ bNodeType cmp_node_curve_vec= {
static bNodeSocketType cmp_node_curve_rgb_in[]= {
{ SOCK_VALUE, 1, "Fac", 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { SOCK_RGBA, 1, "Black Level", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { SOCK_RGBA, 1, "White Level", 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f},
{ -1, 0, "" }
};
@@ -157,7 +159,7 @@ static void do_curves_fac(bNode *node, float *out, float *in, float *fac)
static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- /* stack order input: fac, image */
+ /* stack order input: fac, image, black level, white level */
/* stack order output: image */
if(out[0]->hasoutput==0)
@@ -172,6 +174,8 @@ static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **i
CompBuf *cbuf= in[1]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+ curvemapping_set_black_white(node->storage, in[2]->vec, in[3]->vec);
+
if(in[0]->vec[0] == 1.0)
composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA);
else
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c b/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c
index 53d01ab1d12..6f175671296 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c
@@ -235,7 +235,7 @@ static void IIR_gauss_single(CompBuf* buf, float sigma)
#undef YVV
}
-static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, float inpval)
+static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, float inpval, int no_zbuf)
{
NodeDefocus *nqd = node->storage;
CompBuf *wts; // weights buffer
@@ -283,7 +283,7 @@ static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf,
// if 'no_zbuf' flag set (which is always set if input is not an image),
// values are instead interpreted directly as blur radius values
- if (nqd->no_zbuf) {
+ if (no_zbuf) {
// to prevent *reaaallly* big radius values and impossible calculation times,
// limit the maximum to half the image width or height, whichever is smaller
float maxr = 0.5f*(float)MIN2(img->x, img->y);
@@ -376,8 +376,10 @@ static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf,
// some sort of visual feedback would be nice, or at least this text in the renderwin header
// but for now just print some info in the console every 8 scanlines.
if (((y & 7)==0) || (y==(img->y-1))) {
- printf("\rdefocus: Processing Line %d of %d ... ", y+1, img->y);
- fflush(stdout);
+ if(G.background==0) {
+ printf("\rdefocus: Processing Line %d of %d ... ", y+1, img->y);
+ fflush(stdout);
+ }
}
// esc set by main calling process
if(node->exec & NODE_BREAK)
@@ -698,7 +700,7 @@ static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf,
// sampled, simple rejection sampling here, good enough
unsigned int maxsam, s, ui = BLI_rand()*BLI_rand();
float wcor, cpr = BLI_frand();
- if (nqd->no_zbuf)
+ if (no_zbuf)
maxsam = nqd->samples; // no zbuffer input, use sample value directly
else {
// depth adaptive sampling hack, the more out of focus, the more samples taken, 16 minimum.
@@ -772,14 +774,13 @@ static void node_composit_exec_defocus(void *data, bNode *node, bNodeStack **in,
{
CompBuf *new, *old, *zbuf_use = NULL, *img = in[0]->data, *zbuf = in[1]->data;
NodeDefocus *nqd = node->storage;
+ int no_zbuf = nqd->no_zbuf;
if ((img==NULL) || (out[0]->hasoutput==0)) return;
// if image not valid type or fstop==infinite (128), nothing to do, pass in to out
- if (((img->type!=CB_RGBA) && (img->type!=CB_VAL)) || ((nqd->no_zbuf==0) && (nqd->fstop==128.f))) {
- new = alloc_compbuf(img->x, img->y, img->type, 0);
- new->rect = img->rect;
- out[0]->data = new;
+ if (((img->type!=CB_RGBA) && (img->type!=CB_VAL)) || ((no_zbuf==0) && (nqd->fstop==128.f))) {
+ out[0]->data = pass_on_compbuf(img);
return;
}
@@ -793,21 +794,27 @@ static void node_composit_exec_defocus(void *data, bNode *node, bNodeStack **in,
}
zbuf_use = typecheck_compbuf(zbuf, CB_VAL);
}
- else nqd->no_zbuf = 1; // no zbuffer input
+ else no_zbuf = 1; // no zbuffer input
// ok, process
old = img;
if (nqd->gamco) {
- // gamma correct, blender func is simplified, fixed value & RGBA only, should make user param
+ // gamma correct, blender func is simplified, fixed value & RGBA only,
+ // should make user param. also depremul and premul afterwards, gamma
+ // correction can't work with premul alpha
old = dupalloc_compbuf(img);
+ premul_compbuf(old, 1);
gamma_correct_compbuf(old, 0);
+ premul_compbuf(old, 0);
}
new = alloc_compbuf(old->x, old->y, old->type, 1);
- defocus_blur(node, new, old, zbuf_use, in[1]->vec[0]*nqd->scale);
+ defocus_blur(node, new, old, zbuf_use, in[1]->vec[0]*nqd->scale, no_zbuf);
if (nqd->gamco) {
+ premul_compbuf(new, 1);
gamma_correct_compbuf(new, 1);
+ premul_compbuf(new, 0);
free_compbuf(old);
}
if(node->exec & NODE_BREAK) {
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_directionalblur.c b/source/blender/nodes/intern/CMP_nodes/CMP_directionalblur.c
new file mode 100644
index 00000000000..27f535186db
--- /dev/null
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_directionalblur.c
@@ -0,0 +1,143 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Alfredo de Greef (eeshlo)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+static bNodeSocketType cmp_node_dblur_in[]= {
+ { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.f, 0.f, 1.f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketType cmp_node_dblur_out[]= {
+ { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static CompBuf *dblur(bNode *node, CompBuf *img, int iterations, int wrap,
+ float center_x, float center_y, float dist, float angle, float spin, float zoom)
+{
+ if ((dist != 0.f) || (spin != 0.f) || (zoom != 0.f)) {
+ void (*getpix)(CompBuf*, float, float, float*) = wrap ? qd_getPixelLerpWrap : qd_getPixelLerp;
+ const float a= angle * (float)M_PI / 180.f;
+ const float itsc= 1.f / pow(2.f, (float)iterations);
+ float D;
+ float center_x_pix, center_y_pix;
+ float tx, ty;
+ float sc, rot;
+ CompBuf *tmp;
+ int i, j;
+
+ tmp= dupalloc_compbuf(img);
+
+ D= dist * sqrtf(img->x * img->x + img->y * img->y);
+ center_x_pix= center_x * img->x;
+ center_y_pix= center_y * img->y;
+
+ tx= itsc * D * cos(a);
+ ty= -itsc * D * sin(a);
+ sc= itsc * zoom;
+ rot= itsc * spin * (float)M_PI / 180.f;
+
+ /* blur the image */
+ for(i= 0; i < iterations; ++i) {
+ const float cs= cos(rot), ss= sin(rot);
+ const float isc= 1.f / (1.f + sc);
+ unsigned int x, y;
+ float col[4]= {0,0,0,0};
+
+ for(y= 0; y < img->y; ++y) {
+ const float v= isc * (y - center_y_pix) + ty;
+
+ for(x= 0; x < img->x; ++x) {
+ const float u= isc * (x - center_x_pix) + tx;
+ unsigned int p= (x + y * img->x) * img->type;
+
+ getpix(tmp, cs * u + ss * v + center_x_pix, cs * v - ss * u + center_y_pix, col);
+
+ /* mix img and transformed tmp */
+ for(j= 0; j < 4; ++j)
+ img->rect[p + j]= AVG2(img->rect[p + j], col[j]);
+ }
+ }
+
+ /* copy img to tmp */
+ if(i != (iterations - 1))
+ memcpy(tmp->rect, img->rect, sizeof(float) * img->x * img->y * img->type);
+
+ /* double transformations */
+ tx *= 2.f, ty *= 2.f;
+ sc *= 2.f, rot *= 2.f;
+
+ if(node->exec & NODE_BREAK) break;
+ }
+
+ free_compbuf(tmp);
+ }
+
+ return img;
+}
+
+static void node_composit_exec_dblur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ NodeDBlurData *ndbd= node->storage;
+ CompBuf *new, *img= in[0]->data;
+
+ if((img == NULL) || (out[0]->hasoutput == 0)) return;
+
+ if (img->type != CB_RGBA)
+ new = typecheck_compbuf(img, CB_RGBA);
+ else
+ new = dupalloc_compbuf(img);
+
+ out[0]->data= dblur(node, new, ndbd->iter, ndbd->wrap, ndbd->center_x, ndbd->center_y, ndbd->distance, ndbd->angle, ndbd->spin, ndbd->zoom);
+}
+
+static void node_composit_init_dblur(bNode* node)
+{
+ NodeDBlurData *ndbd= MEM_callocN(sizeof(NodeDBlurData), "node dblur data");
+ node->storage= ndbd;
+ ndbd->center_x= 0.5;
+ ndbd->center_y= 0.5;
+}
+
+bNodeType cmp_node_dblur = {
+ /* *next,*prev */ NULL, NULL,
+ /* type code */ CMP_NODE_DBLUR,
+ /* name */ "Directional Blur",
+ /* width+range */ 150, 120, 200,
+ /* class+opts */ NODE_CLASS_OP_FILTER, NODE_OPTIONS,
+ /* input sock */ cmp_node_dblur_in,
+ /* output sock */ cmp_node_dblur_out,
+ /* storage */ "NodeDBlurData",
+ /* execfunc */ node_composit_exec_dblur,
+ /* butfunc */ NULL,
+ /* initfunc */ node_composit_init_dblur,
+ /* freestoragefunc */ node_free_standard_storage,
+ /* copystoragefunc */ node_copy_standard_storage,
+ /* id */ NULL
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_displace.c b/source/blender/nodes/intern/CMP_nodes/CMP_displace.c
index 0ec15d9eb77..f5b6edcea80 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_displace.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_displace.c
@@ -44,18 +44,22 @@ static bNodeSocketType cmp_node_displace_out[]= {
{ -1, 0, "" }
};
+static float *vecbuf_get_pixel(CompBuf *vecbuf, float *veccol, int x, int y)
+{
+ /* the x-xrad stuff is a bit weird, but i seem to need it otherwise
+ * my returned pixels are offset weirdly */
+ return compbuf_get_pixel(vecbuf, veccol, x-vecbuf->xrad, y-vecbuf->yrad, vecbuf->xrad, vecbuf->yrad);
+}
+
static void do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *veccol, float *xscale, float *yscale)
{
ImBuf *ibuf;
- int x, y, sx, sy;
float dx=0.0, dy=0.0;
float dspx, dspy;
- float uv[2];
-
- float *out= stackbuf->rect, *vec=vecbuf->rect, *in= cbuf->rect;
+ float uv[2], col[4], colnext[4], colprev[4];
float *vp, *vpnext, *vpprev;
-
- int row = 3*vecbuf->x;
+ float *out= stackbuf->rect, *vec=vecbuf->rect, *in= cbuf->rect;
+ int x, y, vx, vy, sx, sy;
/* ibuf needed for sampling */
ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
@@ -65,37 +69,50 @@ static void do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float
sx= stackbuf->x;
sy= stackbuf->y;
+
+ QUATCOPY(col, veccol);
+ QUATCOPY(colnext, veccol);
+ QUATCOPY(colprev, veccol);
for(y=0; y<sy; y++) {
for(x= 0; x< sx; x++, out+=4, in+=4, vec+=3) {
- /* the x-xrad stuff is a bit weird, but i seem to need it otherwise
- * my returned pixels are offset weirdly */
- vp = compbuf_get_pixel(vecbuf, veccol, x-vecbuf->xrad, y-vecbuf->yrad, vecbuf->xrad, vecbuf->yrad);
+ vp = vecbuf_get_pixel(vecbuf, col, x, y);
+
+ /* this happens in compbuf_get_pixel, need to make sure the following
+ * check takes them into account */
+ vx= x-vecbuf->xof;
+ vy= y-vecbuf->yof;
/* find the new displaced co-ords, also correcting for translate offset */
- dspx = x - (*xscale * vp[0]);
- dspy = y - (*yscale * vp[1]);
+ dspx = vx - (*xscale * vp[0]);
+ dspy = vy - (*yscale * vp[1]);
/* convert image space to 0.0-1.0 UV space for sampling, correcting for translate offset */
uv[0] = dspx / (float)sx;
uv[1] = dspy / (float)sy;
-
- if(x>0 && x< vecbuf->x-1 && y>0 && y< vecbuf->y-1) {
- vpnext = vp+row;
- vpprev = vp-row;
-
- /* adaptive sampling, X channel */
- dx= 0.5f*(fabs(vp[0]-vp[-3]) + fabs(vp[0]-vp[3]));
-
- dx+= 0.25f*(fabs(vp[0]-vpprev[-3]) + fabs(vp[0]-vpnext[-3]));
- dx+= 0.25f*(fabs(vp[0]-vpprev[+3]) + fabs(vp[0]-vpnext[+3]));
-
- /* adaptive sampling, Y channel */
- dy= 0.5f*(fabs(vp[1]-vp[-row+1]) + fabs(vp[1]-vp[row+1]));
-
- dy+= 0.25f*(fabs(vp[1]-vpprev[+1-3]) + fabs(vp[1]-vpnext[+1-3]));
- dy+= 0.25f*(fabs(vp[1]-vpprev[+1+3]) + fabs(vp[1]-vpnext[+1+3]));
+
+ if(vx>0 && vx< vecbuf->x-1 && vy>0 && vy< vecbuf->y-1) {
+ /* adaptive sampling, X and Y channel.
+ * we call vecbuf_get_pixel for every pixel since the input
+ * might be a procedural, and then we can't use offsets */
+ vpprev = vecbuf_get_pixel(vecbuf, colprev, x-1, y);
+ vpnext = vecbuf_get_pixel(vecbuf, colnext, x+1, y);
+ dx= 0.5f*(fabs(vp[0]-vpprev[0]) + fabs(vp[0]-vpnext[0]));
+
+ vpprev = vecbuf_get_pixel(vecbuf, colprev, x, y-1);
+ vpnext = vecbuf_get_pixel(vecbuf, colnext, x, y+1);
+ dy= 0.5f*(fabs(vp[1]-vpnext[1]) + fabs(vp[1]-vpprev[1]));
+
+ vpprev = vecbuf_get_pixel(vecbuf, colprev, x-1, y-1);
+ vpnext = vecbuf_get_pixel(vecbuf, colnext, x-1, y+1);
+ dx+= 0.25f*(fabs(vp[0]-vpprev[0]) + fabs(vp[0]-vpnext[0]));
+ dy+= 0.25f*(fabs(vp[1]-vpprev[1]) + fabs(vp[1]-vpnext[1]));
+
+ vpprev = vecbuf_get_pixel(vecbuf, colprev, x+1, y-1);
+ vpnext = vecbuf_get_pixel(vecbuf, colnext, x+1, y+1);
+ dx+= 0.25f*(fabs(vp[0]-vpprev[0]) + fabs(vp[0]-vpnext[0]));
+ dy+= 0.25f*(fabs(vp[1]-vpprev[1]) + fabs(vp[1]-vpnext[1]));
/* scaled down to prevent blurriness */
/* 8: magic number, provides a good level of sharpness without getting too aliased */
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c b/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c
index 5d0ab729e08..e77de3726cb 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c
@@ -34,7 +34,7 @@
static bNodeSocketType cmp_node_gamma_in[]= {
{ SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
- { SOCK_VALUE, 1, "Gamma", 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 2.0f},
+ { SOCK_VALUE, 1, "Gamma", 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 10.0f},
{ -1, 0, "" }
};
static bNodeSocketType cmp_node_gamma_out[]= {
@@ -46,7 +46,8 @@ static void do_gamma(bNode *node, float *out, float *in, float *fac)
{
int i=0;
for(i=0; i<3; i++) {
- out[i] = pow(in[i],fac[0]);
+ /* check for negative to avoid nan's */
+ out[i] = (in[i] > 0.0f)? pow(in[i],fac[0]): in[i];
}
out[3] = in[3];
}
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_glare.c b/source/blender/nodes/intern/CMP_nodes/CMP_glare.c
index e7b8fd00c93..9ab4038607f 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_glare.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_glare.c
@@ -424,15 +424,18 @@ static void fglow(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
static void node_composit_exec_glare(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- CompBuf *new, *img = in[0]->data;
+ CompBuf *new, *src, *img = in[0]->data;
NodeGlare* ndg = node->storage;
if ((img == NULL) || (out[0]->hasoutput == 0)) return;
- if (img->type != CB_RGBA)
+ if (img->type != CB_RGBA) {
new = typecheck_compbuf(img, CB_RGBA);
- else
+ src = typecheck_compbuf(img, CB_RGBA);
+ } else {
new = dupalloc_compbuf(img);
+ src = dupalloc_compbuf(img);
+ }
{
int x, y;
@@ -448,19 +451,20 @@ static void node_composit_exec_glare(void *data, bNode *node, bNodeStack **in, b
switch (ndg->type) {
case 0:
- star4(ndg, new, img);
+ star4(ndg, new, src);
break;
case 1:
- fglow(ndg, new, img);
+ fglow(ndg, new, src);
break;
case 3:
- ghosts(ndg, new, img);
+ ghosts(ndg, new, src);
break;
case 2:
default:
- streaks(ndg, new, img);
+ streaks(ndg, new, src);
}
+ free_compbuf(src);
out[0]->data = new;
}
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c b/source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c
index eeddb4ce756..92614d1cc6a 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c
@@ -52,9 +52,7 @@ static void do_hue_sat_fac(bNode *node, float *out, float *in, float *fac)
hsv[0]+= (nhs->hue - 0.5f);
if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
hsv[1]*= nhs->sat;
- if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
hsv[2]*= nhs->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];
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c b/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c
index abb9fa98d97..a40579ac3b2 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c
@@ -63,8 +63,25 @@ static void do_idmask(CompBuf *stackbuf, CompBuf *cbuf, float idnr)
MEM_freeN(abuf);
}
+/* full sample version */
+static void do_idmask_fsa(CompBuf *stackbuf, CompBuf *cbuf, float idnr)
+{
+ float *rect, *rs;
+ int x;
+
+ rect= cbuf->rect;
+ rs= stackbuf->rect;
+ for(x= cbuf->x*cbuf->y - 1; x>=0; x--)
+ if(rect[x]==idnr)
+ rs[x]= 1.0f;
+
+}
+
+
static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
+ RenderData *rd= data;
+
if(out[0]->hasoutput==0)
return;
@@ -77,7 +94,10 @@ static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in,
stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */;
- do_idmask(stackbuf, cbuf, (float)node->custom1);
+ if(rd->scemode & R_FULL_SAMPLE)
+ do_idmask_fsa(stackbuf, cbuf, (float)node->custom1);
+ else
+ do_idmask(stackbuf, cbuf, (float)node->custom1);
out[0]->data= stackbuf;
}
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_image.c b/source/blender/nodes/intern/CMP_nodes/CMP_image.c
index 20308e968d3..be5a1d7241b 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_image.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_image.c
@@ -48,6 +48,7 @@ static bNodeSocketType cmp_node_rlayers_out[]= {
{ SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Mist", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
@@ -78,6 +79,21 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
stackbuf->rect= ibuf->rect_float;
}
+ /*code to respect the premul flag of images; I'm
+ not sure if this is a good idea for multilayer images,
+ since it never worked before for them.
+ if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
+ //premul the image
+ int i;
+ float *pixel = stackbuf->rect;
+
+ for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
+ pixel[0] *= pixel[3];
+ pixel[1] *= pixel[3];
+ pixel[2] *= pixel[3];
+ }
+ }
+ */
return stackbuf;
};
@@ -149,6 +165,8 @@ void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, I
out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO);
if(out[RRES_OUT_INDEXOB]->hasoutput)
out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
+ if(out[RRES_OUT_MIST]->hasoutput)
+ out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST);
};
@@ -184,11 +202,32 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, b
else {
stackbuf= node_composit_get_image(rd, ima, iuser);
- /* put image on stack */
- out[0]->data= stackbuf;
+ if (stackbuf) {
+ /*respect image premul option*/
+ if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
+ int i;
+ float *pixel;
+
+ /*first duplicate stackbuf->rect, since it's just a pointer
+ to the source imbuf, and we don't want to change that.*/
+ stackbuf->rect = MEM_dupallocN(stackbuf->rect);
+
+ /*premul the image*/
+
+ pixel = stackbuf->rect;
+ for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
+ pixel[0] *= pixel[3];
+ pixel[1] *= pixel[3];
+ pixel[2] *= pixel[3];
+ }
+ }
- if(out[2]->hasoutput)
- out[2]->data= node_composit_get_zimage(node, rd);
+ /* put image on stack */
+ out[0]->data= stackbuf;
+
+ if(out[2]->hasoutput)
+ out[2]->data= node_composit_get_zimage(node, rd);
+ }
}
/* alpha and preview for both types */
@@ -205,6 +244,7 @@ static void node_composit_init_image(bNode* node)
{
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
node->storage= iuser;
+ iuser->frames= 1;
iuser->sfra= 1;
iuser->fie_ima= 2;
iuser->ok= 1;
@@ -236,7 +276,7 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in
CompBuf *buf;
int buftype= CB_VEC3;
- if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB))
+ if(ELEM3(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST))
buftype= CB_VAL;
else if(passcode==SCE_PASS_VECTOR)
buftype= CB_VEC4;
@@ -282,7 +322,9 @@ void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out
if(out[RRES_OUT_RADIO]->hasoutput)
out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO);
if(out[RRES_OUT_INDEXOB]->hasoutput)
- out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
+ out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
+ if(out[RRES_OUT_MIST]->hasoutput)
+ out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_math.c b/source/blender/nodes/intern/CMP_nodes/CMP_math.c
index cf2af9bbc11..421c1343df7 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_math.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_math.c
@@ -57,7 +57,7 @@ static void do_math(bNode *node, float *out, float *in, float *in2)
break;
case 3: /* Divide */
{
- if(in[1]==0) /* We don't want to divide by zero. */
+ if(in2[0]==0) /* We don't want to divide by zero. */
out[0]= 0.0;
else
out[0]= in[0] / in2[0];
@@ -131,7 +131,23 @@ static void do_math(bNode *node, float *out, float *in, float *in2)
{
out[0]= (int)(in[0] + 0.5f);
}
- break;
+ break;
+ case 15: /* Less Than */
+ {
+ if( in[0] < in2[0] )
+ out[0]= 1.0f;
+ else
+ out[0]= 0.0f;
+ }
+ break;
+ case 16: /* Greater Than */
+ {
+ if( in[0] > in2[0] )
+ out[0]= 1.0f;
+ else
+ out[0]= 0.0f;
+ }
+ break;
}
}
@@ -142,7 +158,6 @@ static void node_composit_exec_math(void *data, bNode *node, bNodeStack **in, bN
CompBuf *stackbuf;
/* check for inputs and outputs for early out*/
- if(in[0]->hasinput==0 && in[1]->hasinput==0) return;
if(out[0]->hasoutput==0) return;
/* no image-color operation */
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_premulkey.c b/source/blender/nodes/intern/CMP_nodes/CMP_premulkey.c
new file mode 100644
index 00000000000..4fde652c59d
--- /dev/null
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_premulkey.c
@@ -0,0 +1,77 @@
+/**
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2006 Blender Foundation.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): none yet.
+*
+* ***** END GPL LICENSE BLOCK *****
+
+*/
+
+#include "../CMP_util.h"
+
+/* **************** Premul and Key Alpha Convert ******************** */
+
+static bNodeSocketType cmp_node_premulkey_in[]= {
+ { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType cmp_node_premulkey_out[]= {
+ { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void node_composit_exec_premulkey(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ if(out[0]->hasoutput==0)
+ return;
+
+ if(in[0]->data) {
+ CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+
+ stackbuf= dupalloc_compbuf(cbuf);
+ premul_compbuf(stackbuf, node->custom1 == 1);
+
+ out[0]->data = stackbuf;
+ if(cbuf != in[0]->data)
+ free_compbuf(cbuf);
+ }
+}
+
+bNodeType cmp_node_premulkey= {
+ /* *next,*prev */ NULL, NULL,
+ /* type code */ CMP_NODE_PREMULKEY,
+ /* name */ "Alpha Convert",
+ /* width+range */ 140, 100, 320,
+ /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+ /* input sock */ cmp_node_premulkey_in,
+ /* output sock */ cmp_node_premulkey_out,
+ /* storage */ "",
+ /* execfunc */ node_composit_exec_premulkey,
+ /* butfunc */ NULL,
+ /* initfunc */ NULL,
+ /* freestoragefunc */ NULL,
+ /* copysotragefunc */ NULL,
+ /* id */ NULL
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_texture.c b/source/blender/nodes/intern/CMP_nodes/CMP_texture.c
index 31afe74bd11..c1f1948dba1 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_texture.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_texture.c
@@ -42,19 +42,18 @@ static bNodeSocketType cmp_node_texture_out[]= {
};
/* called without rect allocated */
-static void texture_procedural(CompBuf *cbuf, float *col, float xco, float yco)
+static void texture_procedural(CompBuf *cbuf, float *out, float xco, float yco)
{
bNode *node= cbuf->node;
- bNodeSocket *sock= node->inputs.first;
TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
- float vec[3], *size, nor[3]={0.0f, 0.0f, 0.0f};
- int retval, type= cbuf->type;
+ float vec[3], *size, nor[3]={0.0f, 0.0f, 0.0f}, col[4];
+ int retval, type= cbuf->procedural_type;
- size= sock->next->ns.vec;
+ size= cbuf->procedural_size;
- vec[0]= size[0]*(xco + sock->ns.vec[0]);
- vec[1]= size[1]*(yco + sock->ns.vec[1]);
- vec[2]= size[2]*sock->ns.vec[2];
+ vec[0]= size[0]*(xco + cbuf->procedural_offset[0]);
+ vec[1]= size[1]*(yco + cbuf->procedural_offset[1]);
+ vec[2]= size[2]*cbuf->procedural_offset[2];
retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres);
@@ -80,6 +79,8 @@ static void texture_procedural(CompBuf *cbuf, float *col, float xco, float yco)
else {
VECCOPY(col, nor);
}
+
+ typecheck_compbuf_color(out, col, cbuf->type, cbuf->procedural_type);
}
/* texture node outputs get a small rect, to make sure all other nodes accept it */
@@ -106,6 +107,9 @@ static void node_composit_exec_texture(void *data, bNode *node, bNodeStack **in,
prevbuf->rect_procedural= texture_procedural;
prevbuf->node= node;
+ VECCOPY(prevbuf->procedural_offset, in[0]->vec);
+ VECCOPY(prevbuf->procedural_size, in[1]->vec);
+ prevbuf->procedural_type= CB_RGBA;
composit1_pixel_processor(node, prevbuf, prevbuf, out[0]->vec, do_copy_rgba, CB_RGBA);
generate_preview(node, prevbuf);
free_compbuf(prevbuf);
@@ -115,6 +119,9 @@ static void node_composit_exec_texture(void *data, bNode *node, bNodeStack **in,
stackbuf->rect_procedural= texture_procedural;
stackbuf->node= node;
+ VECCOPY(stackbuf->procedural_offset, in[0]->vec);
+ VECCOPY(stackbuf->procedural_size, in[1]->vec);
+ stackbuf->procedural_type= CB_VAL;
out[0]->data= stackbuf;
}
@@ -123,6 +130,9 @@ static void node_composit_exec_texture(void *data, bNode *node, bNodeStack **in,
stackbuf->rect_procedural= texture_procedural;
stackbuf->node= node;
+ VECCOPY(stackbuf->procedural_offset, in[0]->vec);
+ VECCOPY(stackbuf->procedural_size, in[1]->vec);
+ stackbuf->procedural_type= CB_RGBA;
out[1]->data= stackbuf;
}
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c
index 662d8e8dde9..950ad97a397 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c
@@ -63,7 +63,7 @@ static float avgLogLum(CompBuf *src, float* auto_key, float* Lav, float* Cav)
}
-void static tonemap(NodeTonemap* ntm, CompBuf* dst, CompBuf* src)
+static void tonemap(NodeTonemap* ntm, CompBuf* dst, CompBuf* src)
{
int x, y;
float dr, dg, db, al, igm = (ntm->gamma==0.f) ? 1 : (1.f / ntm->gamma);
@@ -130,13 +130,16 @@ static void node_composit_exec_tonemap(void *data, bNode *node, bNodeStack **in,
if ((img==NULL) || (out[0]->hasoutput==0)) return;
if (img->type != CB_RGBA)
- new = typecheck_compbuf(img, CB_RGBA);
- else
- new = dupalloc_compbuf(img);
+ img = typecheck_compbuf(img, CB_RGBA);
+
+ new = dupalloc_compbuf(img);
tonemap(node->storage, new, img);
out[0]->data = new;
+
+ if(img!=in[0]->data)
+ free_compbuf(img);
}
static void node_composit_init_tonemap(bNode* node)
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c b/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c
index 29cf8f34d54..daf61609692 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c
@@ -45,6 +45,19 @@ static bNodeSocketType cmp_node_zcombine_out[]= {
{ -1, 0, "" }
};
+static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float *src2, float *z2)
+{
+ if(*z1 <= *z2) {
+ QUATCOPY(out, src1);
+ }
+ else {
+ QUATCOPY(out, src2);
+
+ if(node->custom1)
+ *z1= *z2;
+ }
+}
+
static void do_zcombine_mask(bNode *node, float *out, float *z1, float *z2)
{
if(*z1 > *z2) {
@@ -67,43 +80,58 @@ static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, f
static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
+ RenderData *rd= data;
+ CompBuf *cbuf= in[0]->data;
+ CompBuf *zbuf;
+
/* stack order in: col z col z */
/* stack order out: col z */
- if(out[0]->hasoutput==0)
+ if(out[0]->hasoutput==0 && out[1]->hasoutput==0)
return;
/* no input image; do nothing now */
if(in[0]->data==NULL) {
return;
}
+
+ if(out[1]->hasoutput) {
+ /* copy or make a buffer for for the first z value, here we write result in */
+ if(in[1]->data)
+ zbuf= dupalloc_compbuf(in[1]->data);
+ else {
+ float *zval;
+ int tot= cbuf->x*cbuf->y;
+
+ zbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
+ for(zval= zbuf->rect; tot; tot--, zval++)
+ *zval= in[1]->vec[0];
+ }
+ /* lazy coder hack */
+ node->custom1= 1;
+ out[1]->data= zbuf;
+ }
+ else {
+ node->custom1= 0;
+ zbuf= in[1]->data;
+ }
+
+ if(rd->scemode & R_FULL_SAMPLE) {
+ /* make output size of first input image */
+ CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
+
+ composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, zbuf, in[1]->vec, in[2]->data, in[2]->vec,
+ in[3]->data, in[3]->vec, do_zcombine, CB_RGBA, CB_VAL, CB_RGBA, CB_VAL);
+
+ out[0]->data= stackbuf;
+ }
else {
/* make output size of first input image */
- CompBuf *cbuf= in[0]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
- CompBuf *zbuf, *mbuf;
+ CompBuf *mbuf;
float *fp;
int x;
char *aabuf;
- if(out[1]->hasoutput) {
- /* copy or make a buffer for for the first z value, here we write result in */
- if(in[1]->data)
- zbuf= dupalloc_compbuf(in[1]->data);
- else {
- float *zval;
- int tot= cbuf->x*cbuf->y;
-
- zbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
- for(zval= zbuf->rect; tot; tot--, zval++)
- *zval= in[1]->vec[0];
- }
- /* lazy coder hack */
- node->custom1= 1;
- }
- else {
- node->custom1= 0;
- zbuf= in[1]->data;
- }
/* make a mask based on comparison, optionally write zvalue */
mbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
@@ -131,9 +159,8 @@ static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in
MEM_freeN(aabuf);
out[0]->data= stackbuf;
- if(node->custom1)
- out[1]->data= zbuf;
}
+
}
bNodeType cmp_node_zcombine= {
diff --git a/source/blender/nodes/intern/CMP_nodes/Makefile b/source/blender/nodes/intern/CMP_nodes/Makefile
index bf79d14c020..b70b591a588 100644
--- a/source/blender/nodes/intern/CMP_nodes/Makefile
+++ b/source/blender/nodes/intern/CMP_nodes/Makefile
@@ -42,3 +42,5 @@ CPPFLAGS += -I../../../blenlib
CPPFLAGS += -I../../../editors/include
CPPFLAGS += -I../../../imbuf
CPPFLAGS += -I../../../render/extern/include
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
diff --git a/source/blender/nodes/intern/CMP_util.c b/source/blender/nodes/intern/CMP_util.c
index eee33e33ff5..f9805645115 100644
--- a/source/blender/nodes/intern/CMP_util.c
+++ b/source/blender/nodes/intern/CMP_util.c
@@ -122,6 +122,48 @@ void print_compbuf(char *str, CompBuf *cbuf)
}
+/* used for disabling node (similar code in drawnode.c for disable line) */
+void node_compo_pass_on(bNode *node, bNodeStack **nsin, bNodeStack **nsout)
+{
+ CompBuf *valbuf= NULL, *colbuf= NULL, *vecbuf= NULL;
+ bNodeSocket *sock;
+ int a;
+
+ /* connect the first value buffer in with first value out */
+ /* connect the first RGBA buffer in with first RGBA out */
+
+ /* test the inputs */
+ for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
+ if(nsin[a]->data) {
+ CompBuf *cbuf= nsin[a]->data;
+ if(cbuf->type==1 && valbuf==NULL) valbuf= cbuf;
+ if(cbuf->type==3 && vecbuf==NULL) vecbuf= cbuf;
+ if(cbuf->type==4 && colbuf==NULL) colbuf= cbuf;
+ }
+ }
+
+ /* outputs */
+ if(valbuf || colbuf || vecbuf) {
+ for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
+ if(nsout[a]->hasoutput) {
+ if(sock->type==SOCK_VALUE && valbuf) {
+ nsout[a]->data= pass_on_compbuf(valbuf);
+ valbuf= NULL;
+ }
+ if(sock->type==SOCK_VECTOR && vecbuf) {
+ nsout[a]->data= pass_on_compbuf(vecbuf);
+ vecbuf= NULL;
+ }
+ if(sock->type==SOCK_RGBA && colbuf) {
+ nsout[a]->data= pass_on_compbuf(colbuf);
+ colbuf= NULL;
+ }
+ }
+ }
+ }
+}
+
+
CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type)
{
CompBuf *cbuf;
@@ -183,17 +225,100 @@ CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy)
return outbuf;
}
+void typecheck_compbuf_color(float *out, float *in, int outtype, int intype)
+{
+ if(intype == outtype) {
+ memcpy(out, in, sizeof(float)*outtype);
+ }
+ else if(outtype==CB_VAL) {
+ if(intype==CB_VEC2) {
+ *out= 0.5f*(in[0]+in[1]);
+ }
+ else if(intype==CB_VEC3) {
+ *out= 0.333333f*(in[0]+in[1]+in[2]);
+ }
+ else if(intype==CB_RGBA) {
+ *out= in[0]*0.35f + in[1]*0.45f + in[2]*0.2f;
+ }
+ }
+ else if(outtype==CB_VEC2) {
+ if(intype==CB_VAL) {
+ out[0]= in[0];
+ out[1]= in[0];
+ }
+ else if(intype==CB_VEC3) {
+ out[0]= in[0];
+ out[1]= in[1];
+ }
+ else if(intype==CB_RGBA) {
+ out[0]= in[0];
+ out[1]= in[1];
+ }
+ }
+ else if(outtype==CB_VEC3) {
+ if(intype==CB_VAL) {
+ out[0]= in[0];
+ out[1]= in[0];
+ out[2]= in[0];
+ }
+ else if(intype==CB_VEC2) {
+ out[0]= in[0];
+ out[1]= in[1];
+ out[2]= 0.0f;
+ }
+ else if(intype==CB_RGBA) {
+ out[0]= in[0];
+ out[1]= in[1];
+ out[2]= in[2];
+ }
+ }
+ else if(outtype==CB_RGBA) {
+ if(intype==CB_VAL) {
+ out[0]= in[0];
+ out[1]= in[0];
+ out[2]= in[0];
+ out[3]= 1.0f;
+ }
+ else if(intype==CB_VEC2) {
+ out[0]= in[0];
+ out[1]= in[1];
+ out[2]= 0.0f;
+ out[3]= 1.0f;
+ }
+ else if(intype==CB_VEC3) {
+ out[0]= in[0];
+ out[1]= in[1];
+ out[2]= in[2];
+ out[3]= 1.0f;
+ }
+ }
+}
+
CompBuf *typecheck_compbuf(CompBuf *inbuf, int type)
{
- if(inbuf && inbuf->type!=type && inbuf->rect_procedural==NULL) {
- CompBuf *outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1);
- float *inrf= inbuf->rect;
- float *outrf= outbuf->rect;
- int x= inbuf->x*inbuf->y;
-
+ if(inbuf && inbuf->type!=type) {
+ CompBuf *outbuf;
+ float *inrf, *outrf;
+ int x;
+
+ outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1);
+
/* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
outbuf->xof= inbuf->xof;
outbuf->yof= inbuf->yof;
+
+ if(inbuf->rect_procedural) {
+ outbuf->rect_procedural= inbuf->rect_procedural;
+ VECCOPY(outbuf->procedural_size, inbuf->procedural_size);
+ VECCOPY(outbuf->procedural_offset, inbuf->procedural_offset);
+ outbuf->procedural_type= inbuf->procedural_type;
+ outbuf->node= inbuf->node;
+ return outbuf;
+ }
+
+ inrf= inbuf->rect;
+ outrf= outbuf->rect;
+ x= inbuf->x*inbuf->y;
if(type==CB_VAL) {
if(inbuf->type==CB_VEC2) {
@@ -460,6 +585,25 @@ CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel)
return valbuf;
}
+static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy)
+{
+ CompBuf *outbuf;
+ float *outfp;
+ int xrad, yrad, x, y;
+
+ outbuf= alloc_compbuf(newx, newy, CB_RGBA, 1);
+
+ outfp= outbuf->rect;
+ xrad= outbuf->xrad;
+ yrad= outbuf->yrad;
+
+ for(y= -yrad; y<-yrad+outbuf->y; y++)
+ for(x= -xrad; x<-xrad+outbuf->x; x++, outfp+=outbuf->type)
+ cbuf->rect_procedural(cbuf, outfp, (float)x/(float)xrad, (float)y/(float)yrad);
+
+ return outbuf;
+}
+
void generate_preview(bNode *node, CompBuf *stackbuf)
{
bNodePreview *preview= node->preview;
@@ -467,7 +611,7 @@ void generate_preview(bNode *node, CompBuf *stackbuf)
if(preview && stackbuf) {
CompBuf *cbuf, *stackbuf_use;
- if(stackbuf->rect==NULL) return;
+ if(stackbuf->rect==NULL && stackbuf->rect_procedural==NULL) return;
stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA);
@@ -480,7 +624,10 @@ void generate_preview(bNode *node, CompBuf *stackbuf)
preview->xsize= (140*stackbuf->x)/stackbuf->y;
}
- cbuf= scalefast_compbuf(stackbuf_use, preview->xsize, preview->ysize);
+ if(stackbuf_use->rect_procedural)
+ cbuf= generate_procedural_preview(stackbuf_use, preview->xsize, preview->ysize);
+ else
+ cbuf= scalefast_compbuf(stackbuf_use, preview->xsize, preview->ysize);
/* this ensures free-compbuf does the right stuff */
SWAP(float *, cbuf->rect, node->preview->rect);
@@ -575,6 +722,36 @@ void gamma_correct_compbuf(CompBuf *img, int inversed)
}
}
+void premul_compbuf(CompBuf *img, int inversed)
+{
+ float *drect;
+ int x;
+
+ if(img->type!=CB_RGBA) return;
+
+ drect= img->rect;
+ if(inversed) {
+ for(x=img->x*img->y; x>0; x--, drect+=4) {
+ if(fabs(drect[3]) < 1e-5f) {
+ drect[0]= 0.0f;
+ drect[1]= 0.0f;
+ drect[2]= 0.0f;
+ }
+ else {
+ drect[0] /= drect[3];
+ drect[1] /= drect[3];
+ drect[2] /= drect[3];
+ }
+ }
+ }
+ else {
+ for(x=img->x*img->y; x>0; x--, drect+=4) {
+ drect[0] *= drect[3];
+ drect[1] *= drect[3];
+ drect[2] *= drect[3];
+ }
+ }
+}
diff --git a/source/blender/nodes/intern/CMP_util.h b/source/blender/nodes/intern/CMP_util.h
index 44f76b0822e..8443c022d17 100644
--- a/source/blender/nodes/intern/CMP_util.h
+++ b/source/blender/nodes/intern/CMP_util.h
@@ -92,6 +92,8 @@ typedef struct CompBuf {
int xof, yof; /* relative to center of target image */
void (*rect_procedural)(struct CompBuf *, float *, float, float);
+ float procedural_size[3], procedural_offset[3];
+ int procedural_type;
bNode *node; /* only in use for procedural bufs */
struct CompBuf *next, *prev; /* for pass-on, works nicer than reference counting */
@@ -117,10 +119,12 @@ CompBuf *dupalloc_compbuf(CompBuf *cbuf);
CompBuf *pass_on_compbuf(CompBuf *cbuf);
void free_compbuf(CompBuf *cbuf);
void print_compbuf(char *str, CompBuf *cbuf);
+void node_compo_pass_on(struct bNode *node, struct bNodeStack **nsin, struct bNodeStack **nsout);
CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type);
CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy);
CompBuf *typecheck_compbuf(CompBuf *inbuf, int type);
+void typecheck_compbuf_color(float *out, float *in, int outtype, int intype);
float *compbuf_get_pixel(CompBuf *cbuf, float *rectf, int x, int y, int xrad, int yrad);
/* **************************************************** */
@@ -161,6 +165,7 @@ void do_hsva_to_rgba(bNode *node, float *out, float *in);
void do_ycca_to_rgba(bNode *node, float *out, float *in);
void gamma_correct_compbuf(CompBuf *img, int inversed);
+void premul_compbuf(CompBuf *img, int inversed);
void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2);
extern void node_ID_title_cb(void *node_v, void *unused_v);
diff --git a/source/blender/nodes/intern/Makefile b/source/blender/nodes/intern/Makefile
index 59c57e42bc1..7c9a67b6cc5 100644
--- a/source/blender/nodes/intern/Makefile
+++ b/source/blender/nodes/intern/Makefile
@@ -42,6 +42,8 @@ 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)
DIRS = SHD_nodes CMP_nodes
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
};
diff --git a/source/blender/nodes/intern/SHD_util.c b/source/blender/nodes/intern/SHD_util.c
index c9f58fbce49..f673834d2b7 100644
--- a/source/blender/nodes/intern/SHD_util.c
+++ b/source/blender/nodes/intern/SHD_util.c
@@ -164,7 +164,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
case MAT_IN_MIR:
VECCOPY(&ma->mirr, sock->ns.vec); break;
case MAT_IN_AMB:
- VECCOPY(&ma->ambr, sock->ns.vec); break;
+ ma->amb= sock->ns.vec[0]; break;
case MAT_IN_EMIT:
ma->emit= sock->ns.vec[0]; break;
case MAT_IN_SPECTRA:
@@ -188,7 +188,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
case MAT_IN_MIR:
VECCOPY(sock->ns.vec, &ma->mirr); break;
case MAT_IN_AMB:
- VECCOPY(sock->ns.vec, &ma->ambr); break;
+ sock->ns.vec[0]= ma->amb; break;
case MAT_IN_EMIT:
sock->ns.vec[0]= ma->emit; break;
case MAT_IN_SPECTRA:
diff --git a/source/blender/nodes/intern/SHD_util.h b/source/blender/nodes/intern/SHD_util.h
index fcab420f3f2..0d9783fdd4b 100644
--- a/source/blender/nodes/intern/SHD_util.h
+++ b/source/blender/nodes/intern/SHD_util.h
@@ -72,6 +72,8 @@
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
+#include "GPU_material.h"
+
//XXX #include "butspace.h"
//XXX #include "wm_event_types.h"
@@ -100,13 +102,12 @@ typedef struct ShaderCallData {
#define MAT_IN_REFL 2
#define MAT_IN_NORMAL 3
#define MAT_IN_MIR 4
-#define MAT_IN_AMBCOL 5
-#define MAT_IN_AMB 6
-#define MAT_IN_EMIT 7
-#define MAT_IN_SPECTRA 8
-#define MAT_IN_RAY_MIRROR 9
-#define MAT_IN_ALPHA 10
-#define MAT_IN_TRANSLUCENCY 11
+#define MAT_IN_AMB 5
+#define MAT_IN_EMIT 6
+#define MAT_IN_SPECTRA 7
+#define MAT_IN_RAY_MIRROR 8
+#define MAT_IN_ALPHA 9
+#define MAT_IN_TRANSLUCENCY 10
/* output socket defines */
#define MAT_OUT_COLOR 0