1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2005 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup shdnodes
22 */
23
24 #include "node_shader_util.h"
25
26 /* **************** CURVE VEC ******************** */
27 static bNodeSocketTemplate sh_node_curve_vec_in[] = {
28 {SOCK_FLOAT, N_("Fac"), 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
29 {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE},
30 {-1, ""},
31 };
32
33 static bNodeSocketTemplate sh_node_curve_vec_out[] = {
34 {SOCK_VECTOR, N_("Vector")},
35 {-1, ""},
36 };
37
node_shader_exec_curve_vec(void * UNUSED (data),int UNUSED (thread),bNode * node,bNodeExecData * UNUSED (execdata),bNodeStack ** in,bNodeStack ** out)38 static void node_shader_exec_curve_vec(void *UNUSED(data),
39 int UNUSED(thread),
40 bNode *node,
41 bNodeExecData *UNUSED(execdata),
42 bNodeStack **in,
43 bNodeStack **out)
44 {
45 float vec[3];
46
47 /* stack order input: vec */
48 /* stack order output: vec */
49 nodestack_get_vec(vec, SOCK_VECTOR, in[1]);
50 BKE_curvemapping_evaluate3F(node->storage, out[0]->vec, vec);
51 }
52
node_shader_init_curve_vec(bNodeTree * UNUSED (ntree),bNode * node)53 static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node)
54 {
55 node->storage = BKE_curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
56 }
57
gpu_shader_curve_vec(GPUMaterial * mat,bNode * node,bNodeExecData * UNUSED (execdata),GPUNodeStack * in,GPUNodeStack * out)58 static int gpu_shader_curve_vec(GPUMaterial *mat,
59 bNode *node,
60 bNodeExecData *UNUSED(execdata),
61 GPUNodeStack *in,
62 GPUNodeStack *out)
63 {
64 float *array, layer;
65 int size;
66
67 CurveMapping *cumap = node->storage;
68
69 BKE_curvemapping_table_RGBA(cumap, &array, &size);
70 GPUNodeLink *tex = GPU_color_band(mat, size, array, &layer);
71
72 float ext_xyz[3][4];
73 float range_xyz[3];
74
75 for (int a = 0; a < 3; a++) {
76 const CurveMap *cm = &cumap->cm[a];
77 ext_xyz[a][0] = cm->mintable;
78 ext_xyz[a][2] = cm->maxtable;
79 range_xyz[a] = 1.0f / max_ff(1e-8f, cm->maxtable - cm->mintable);
80 /* Compute extrapolation gradients. */
81 if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) {
82 ext_xyz[a][1] = (cm->ext_in[0] != 0.0f) ? (cm->ext_in[1] / (cm->ext_in[0] * range_xyz[a])) :
83 1e8f;
84 ext_xyz[a][3] = (cm->ext_out[0] != 0.0f) ?
85 (cm->ext_out[1] / (cm->ext_out[0] * range_xyz[a])) :
86 1e8f;
87 }
88 else {
89 ext_xyz[a][1] = 0.0f;
90 ext_xyz[a][3] = 0.0f;
91 }
92 }
93
94 return GPU_stack_link(mat,
95 node,
96 "curves_vec",
97 in,
98 out,
99 tex,
100 GPU_constant(&layer),
101 GPU_uniform(range_xyz),
102 GPU_uniform(ext_xyz[0]),
103 GPU_uniform(ext_xyz[1]),
104 GPU_uniform(ext_xyz[2]));
105 }
106
register_node_type_sh_curve_vec(void)107 void register_node_type_sh_curve_vec(void)
108 {
109 static bNodeType ntype;
110
111 sh_node_type_base(&ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, 0);
112 node_type_socket_templates(&ntype, sh_node_curve_vec_in, sh_node_curve_vec_out);
113 node_type_init(&ntype, node_shader_init_curve_vec);
114 node_type_size_preset(&ntype, NODE_SIZE_LARGE);
115 node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
116 node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_vec);
117 node_type_gpu(&ntype, gpu_shader_curve_vec);
118
119 nodeRegisterType(&ntype);
120 }
121
122 /* **************** CURVE RGB ******************** */
123 static bNodeSocketTemplate sh_node_curve_rgb_in[] = {
124 {SOCK_FLOAT, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_FACTOR},
125 {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
126 {-1, ""},
127 };
128
129 static bNodeSocketTemplate sh_node_curve_rgb_out[] = {
130 {SOCK_RGBA, N_("Color")},
131 {-1, ""},
132 };
133
node_shader_exec_curve_rgb(void * UNUSED (data),int UNUSED (thread),bNode * node,bNodeExecData * UNUSED (execdata),bNodeStack ** in,bNodeStack ** out)134 static void node_shader_exec_curve_rgb(void *UNUSED(data),
135 int UNUSED(thread),
136 bNode *node,
137 bNodeExecData *UNUSED(execdata),
138 bNodeStack **in,
139 bNodeStack **out)
140 {
141 float vec[3];
142 float fac;
143
144 /* stack order input: vec */
145 /* stack order output: vec */
146 nodestack_get_vec(&fac, SOCK_FLOAT, in[0]);
147 nodestack_get_vec(vec, SOCK_VECTOR, in[1]);
148 BKE_curvemapping_evaluateRGBF(node->storage, out[0]->vec, vec);
149 if (fac != 1.0f) {
150 interp_v3_v3v3(out[0]->vec, vec, out[0]->vec, fac);
151 }
152 }
153
node_shader_init_curve_rgb(bNodeTree * UNUSED (ntree),bNode * node)154 static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node)
155 {
156 node->storage = BKE_curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
157 }
158
gpu_shader_curve_rgb(GPUMaterial * mat,bNode * node,bNodeExecData * UNUSED (execdata),GPUNodeStack * in,GPUNodeStack * out)159 static int gpu_shader_curve_rgb(GPUMaterial *mat,
160 bNode *node,
161 bNodeExecData *UNUSED(execdata),
162 GPUNodeStack *in,
163 GPUNodeStack *out)
164 {
165 float *array, layer;
166 int size;
167 bool use_opti = true;
168
169 CurveMapping *cumap = node->storage;
170
171 BKE_curvemapping_init(cumap);
172 BKE_curvemapping_table_RGBA(cumap, &array, &size);
173 GPUNodeLink *tex = GPU_color_band(mat, size, array, &layer);
174
175 float ext_rgba[4][4];
176 float range_rgba[4];
177
178 for (int a = 0; a < CM_TOT; a++) {
179 const CurveMap *cm = &cumap->cm[a];
180 ext_rgba[a][0] = cm->mintable;
181 ext_rgba[a][2] = cm->maxtable;
182 range_rgba[a] = 1.0f / max_ff(1e-8f, cm->maxtable - cm->mintable);
183 /* Compute extrapolation gradients. */
184 if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) {
185 ext_rgba[a][1] = (cm->ext_in[0] != 0.0f) ?
186 (cm->ext_in[1] / (cm->ext_in[0] * range_rgba[a])) :
187 1e8f;
188 ext_rgba[a][3] = (cm->ext_out[0] != 0.0f) ?
189 (cm->ext_out[1] / (cm->ext_out[0] * range_rgba[a])) :
190 1e8f;
191 }
192 else {
193 ext_rgba[a][1] = 0.0f;
194 ext_rgba[a][3] = 0.0f;
195 }
196
197 /* Check if rgb comps are just linear. */
198 if (a < 3) {
199 if (range_rgba[a] != 1.0f || ext_rgba[a][1] != 1.0f || ext_rgba[a][2] != 1.0f ||
200 cm->totpoint != 2 || cm->curve[0].x != 0.0f || cm->curve[0].y != 0.0f ||
201 cm->curve[1].x != 1.0f || cm->curve[1].y != 1.0f) {
202 use_opti = false;
203 }
204 }
205 }
206
207 if (use_opti) {
208 return GPU_stack_link(mat,
209 node,
210 "curves_rgb_opti",
211 in,
212 out,
213 tex,
214 GPU_constant(&layer),
215 GPU_uniform(range_rgba),
216 GPU_uniform(ext_rgba[3]));
217 }
218
219 return GPU_stack_link(mat,
220 node,
221 "curves_rgb",
222 in,
223 out,
224 tex,
225 GPU_constant(&layer),
226 GPU_uniform(range_rgba),
227 GPU_uniform(ext_rgba[0]),
228 GPU_uniform(ext_rgba[1]),
229 GPU_uniform(ext_rgba[2]),
230 GPU_uniform(ext_rgba[3]));
231 }
232
register_node_type_sh_curve_rgb(void)233 void register_node_type_sh_curve_rgb(void)
234 {
235 static bNodeType ntype;
236
237 sh_node_type_base(&ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, 0);
238 node_type_socket_templates(&ntype, sh_node_curve_rgb_in, sh_node_curve_rgb_out);
239 node_type_init(&ntype, node_shader_init_curve_rgb);
240 node_type_size_preset(&ntype, NODE_SIZE_LARGE);
241 node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
242 node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_rgb);
243 node_type_gpu(&ntype, gpu_shader_curve_rgb);
244
245 nodeRegisterType(&ntype);
246 }
247