b942aa00fb427df06cc5bc48bf8ffea9cbf3a01f
[blender.git] / source / blender / nodes / shader / nodes / node_shader_tex_voronoi.c
1 /**
2  * $Id: node_shader_output.c 32517 2010-10-16 14:32:17Z campbellbarton $
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2005 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include "../node_shader_util.h"
31 #include "node_shader_noise.h"
32
33 static float voronoi_tex(int distance_metric, int coloring,
34         float weight1, float weight2, float weight3, float weight4,
35         float exponent, float intensity, float size, float vec[3], float color[3])
36 {
37         float aw1 = fabsf(weight1);
38         float aw2 = fabsf(weight2);
39         float aw3 = fabsf(weight3);
40         float aw4 = fabsf(weight4);
41         float sc = (aw1 + aw2 + aw3 + aw4);
42         float da[4];
43         float pa[4][3];
44         float fac;
45         float p[3];
46
47         if(sc != 0.0f)
48                 sc = intensity/sc;
49         
50         /* compute distance and point coordinate of 4 nearest neighbours */
51         mul_v3_v3fl(p, vec, 1.0f/size);
52         voronoi_generic(p, distance_metric, exponent, da, pa);
53
54         /* Scalar output */
55         fac = sc * fabsf(weight1*da[0] + weight2*da[1] + weight3*da[2] + weight4*da[3]);
56
57         /* colored output */
58         if(coloring == SHD_VORONOI_INTENSITY) {
59                 color[0]= color[1]= color[2]= fac;
60         }
61         else {
62                 float rgb1[3], rgb2[3], rgb3[3], rgb4[3];
63
64                 cellnoise_color(rgb1, pa[0]);
65                 cellnoise_color(rgb2, pa[1]);
66                 cellnoise_color(rgb3, pa[2]);
67                 cellnoise_color(rgb4, pa[3]);
68
69                 mul_v3_v3fl(color, rgb1, aw1);
70                 madd_v3_v3fl(color, rgb2, aw2);
71                 madd_v3_v3fl(color, rgb3, aw3);
72                 madd_v3_v3fl(color, rgb4, aw4);
73
74                 if(coloring != SHD_VORONOI_POSITION) {
75                         float t1 = MIN2((da[1] - da[0])*10.0f, 1.0f);
76
77                         if(coloring == SHD_VORONOI_POSITION_OUTLINE_INTENSITY)
78                                 mul_v3_fl(color, t1*fac);
79                         else if(coloring == SHD_VORONOI_POSITION_OUTLINE)
80                                 mul_v3_fl(color, t1*sc);
81                 }
82                 else {
83                         mul_v3_fl(color, sc);
84                 }
85         }
86
87         return fac;
88 }
89
90 /* **************** VORONOI ******************** */
91
92 static bNodeSocketTemplate sh_node_tex_voronoi_in[]= {
93         {       SOCK_VECTOR, 1, "Vector",               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
94         {       SOCK_FLOAT, 1, "Size",                  0.25f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
95         {       SOCK_FLOAT, 1, "Weight1",               1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
96         {       SOCK_FLOAT, 1, "Weight2",               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
97         {       SOCK_FLOAT, 1, "Weight3",               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
98         {       SOCK_FLOAT, 1, "Weight4",               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
99         {       SOCK_FLOAT, 1, "Exponent",              2.5f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
100         {       -1, 0, ""       }
101 };
102
103 static bNodeSocketTemplate sh_node_tex_voronoi_out[]= {
104         {       SOCK_RGBA, 0, "Color",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
105         {       SOCK_FLOAT, 0, "Fac",           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
106         {       -1, 0, ""       }
107 };
108
109 static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
110 {
111         NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi");
112         tex->distance_metric = SHD_VORONOI_ACTUAL_DISTANCE;
113         tex->coloring = SHD_VORONOI_INTENSITY;
114
115         node->storage = tex;
116 }
117
118 static void node_shader_exec_tex_voronoi(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
119 {
120         ShaderCallData *scd= (ShaderCallData*)data;
121         NodeTexVoronoi *tex= (NodeTexVoronoi*)node->storage;
122         bNodeSocket *vecsock = node->inputs.first;
123         float vec[3], size, w1, w2, w3, w4, exponent;
124         
125         if(vecsock->link)
126                 nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
127         else
128                 copy_v3_v3(vec, scd->co);
129
130         nodestack_get_vec(&size, SOCK_FLOAT, in[1]);
131         nodestack_get_vec(&w1, SOCK_FLOAT, in[2]);
132         nodestack_get_vec(&w2, SOCK_FLOAT, in[3]);
133         nodestack_get_vec(&w3, SOCK_FLOAT, in[4]);
134         nodestack_get_vec(&w4, SOCK_FLOAT, in[5]);
135         nodestack_get_vec(&exponent, SOCK_FLOAT, in[6]);
136
137         out[1]->vec[0]= voronoi_tex(tex->distance_metric, tex->coloring, w1, w2, w3, w4,
138                 exponent, 1.0f, size, vec, out[0]->vec);
139 }
140
141 static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
142 {
143         if(!in[0].link)
144                 in[0].link = GPU_attribute(CD_ORCO, "");
145
146         return GPU_stack_link(mat, "node_tex_voronoi", in, out);
147 }
148
149 /* node type definition */
150 void register_node_type_sh_tex_voronoi(ListBase *lb)
151 {
152         static bNodeType ntype;
153
154         node_type_base(&ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, 0);
155         node_type_compatibility(&ntype, NODE_NEW_SHADING);
156         node_type_socket_templates(&ntype, sh_node_tex_voronoi_in, sh_node_tex_voronoi_out);
157         node_type_size(&ntype, 150, 60, 200);
158         node_type_init(&ntype, node_shader_init_tex_voronoi);
159         node_type_storage(&ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage);
160         node_type_exec(&ntype, node_shader_exec_tex_voronoi);
161         node_type_gpu(&ntype, node_shader_gpu_tex_voronoi);
162
163         nodeRegisterType(lb, &ntype);
164 };
165