3f0ba3c1c60f8431c53d9e6c5371ac060187d358
[blender.git] / source / blender / nodes / shader / nodes / node_shader_subsurface_scattering.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include "../node_shader_util.h"
29
30 /* **************** OUTPUT ******************** */
31
32 static bNodeSocketTemplate sh_node_subsurface_scattering_in[] = {
33         {       SOCK_RGBA, 1, N_("Color"),                      0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
34         {       SOCK_FLOAT, 1, N_("Scale"),                     1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
35         {       SOCK_VECTOR, 1, N_("Radius"),           1.0f, 0.2f, 0.1f, 0.0f, 0.0f, 100.0f},
36         {       SOCK_FLOAT, 1, N_("Sharpness"),         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
37         {       SOCK_FLOAT, 1, N_("Texture Blur"),      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
38         {       SOCK_VECTOR, 1, N_("Normal"),           0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
39         {       -1, 0, ""       }
40 };
41
42 static bNodeSocketTemplate sh_node_subsurface_scattering_out[] = {
43         {       SOCK_SHADER, 0, N_("BSSRDF")},
44         {       -1, 0, ""       }
45 };
46
47 static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node)
48 {
49         node->custom1 = SHD_SUBSURFACE_BURLEY;
50 }
51
52 static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
53 {
54         if (!in[5].link)
55                 GPU_link(mat, "world_normals_get", &in[5].link);
56
57         GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE);
58
59         if (node->sss_id == 1) {
60                 bNodeSocket *socket = BLI_findlink(&node->original->inputs, 2);
61                 bNodeSocketValueRGBA *socket_data = socket->default_value;
62                 bNodeSocket *socket_sharp = BLI_findlink(&node->original->inputs, 3);
63                 bNodeSocketValueFloat *socket_data_sharp = socket_sharp->default_value;
64                 /* For some reason it seems that the socket value is in ARGB format. */
65                 GPU_material_sss_profile_create(mat, &socket_data->value[1],
66                                                      &node->original->custom1,
67                                                      &socket_data_sharp->value);
68         }
69
70         return GPU_stack_link(mat, node, "node_subsurface_scattering", in, out, GPU_uniform(&node->sss_id));
71 }
72
73 static void node_shader_update_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node)
74 {
75         bNodeSocket *sock;
76         int falloff = node->custom1;
77
78         for (sock = node->inputs.first; sock; sock = sock->next) {
79                 if (STREQ(sock->name, "Sharpness")) {
80                         if (falloff == SHD_SUBSURFACE_CUBIC)
81                                 sock->flag &= ~SOCK_UNAVAIL;
82                         else
83                                 sock->flag |= SOCK_UNAVAIL;
84
85                 }
86         }
87 }
88
89 /* node type definition */
90 void register_node_type_sh_subsurface_scattering(void)
91 {
92         static bNodeType ntype;
93
94         sh_node_type_base(&ntype, SH_NODE_SUBSURFACE_SCATTERING, "Subsurface Scattering", NODE_CLASS_SHADER, 0);
95         node_type_socket_templates(&ntype, sh_node_subsurface_scattering_in, sh_node_subsurface_scattering_out);
96         node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
97         node_type_init(&ntype, node_shader_init_subsurface_scattering);
98         node_type_storage(&ntype, "", NULL, NULL);
99         node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering);
100         node_type_update(&ntype, node_shader_update_subsurface_scattering, NULL);
101
102         nodeRegisterType(&ntype);
103 }