Cleanup: deduplicate image user initialization, make consistent.
[blender.git] / source / blender / nodes / shader / nodes / node_shader_tex_image.c
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 #include "../node_shader_util.h"
21
22 /* **************** OUTPUT ******************** */
23
24 static bNodeSocketTemplate sh_node_tex_image_in[] = {
25     {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
26     {-1, 0, ""},
27 };
28
29 static bNodeSocketTemplate sh_node_tex_image_out[] = {
30     {SOCK_RGBA,
31      0,
32      N_("Color"),
33      0.0f,
34      0.0f,
35      0.0f,
36      0.0f,
37      0.0f,
38      1.0f,
39      PROP_NONE,
40      SOCK_NO_INTERNAL_LINK},
41     {SOCK_FLOAT,
42      0,
43      N_("Alpha"),
44      0.0f,
45      0.0f,
46      0.0f,
47      0.0f,
48      0.0f,
49      1.0f,
50      PROP_NONE,
51      SOCK_NO_INTERNAL_LINK},
52     {-1, 0, ""},
53 };
54
55 static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node)
56 {
57   NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
58   BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
59   BKE_texture_colormapping_default(&tex->base.color_mapping);
60   tex->color_space = SHD_COLORSPACE_COLOR;
61   BKE_imageuser_default(&tex->iuser);
62
63   node->storage = tex;
64 }
65
66 static int node_shader_gpu_tex_image(GPUMaterial *mat,
67                                      bNode *node,
68                                      bNodeExecData *UNUSED(execdata),
69                                      GPUNodeStack *in,
70                                      GPUNodeStack *out)
71 {
72   static const char *names[] = {
73       "node_tex_image_linear",
74       "node_tex_image_nearest",
75       "node_tex_image_cubic",
76       "node_tex_image_smart",
77   };
78   static const char *names_box[] = {
79       "tex_box_sample_linear",
80       "tex_box_sample_nearest",
81       "tex_box_sample_cubic",
82       "tex_box_sample_smart",
83   };
84   static const char *names_clip[] = {
85       "tex_clip_linear",
86       "tex_clip_nearest",
87       "tex_clip_cubic",
88       "tex_clip_smart",
89   };
90
91   Image *ima = (Image *)node->id;
92   NodeTexImage *tex = node->storage;
93
94   /* We get the image user from the original node, since GPU image keeps
95    * a pointer to it and the dependency refreshes the original. */
96   bNode *node_original = node->original ? node->original : node;
97   NodeTexImage *tex_original = node_original->storage;
98   ImageUser *iuser = &tex_original->iuser;
99
100   const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX) ? names_box[tex->interpolation] :
101                                                                   names[tex->interpolation];
102   bool do_color_correction = false;
103   bool do_texco_extend = (tex->extension != SHD_IMAGE_EXTENSION_REPEAT);
104   const bool do_texco_clip = (tex->extension == SHD_IMAGE_EXTENSION_CLIP);
105
106   if (do_texco_extend && (tex->projection != SHD_PROJ_BOX) &&
107       ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) {
108     gpu_node_name = "node_tex_image_cubic_extend";
109     /* We do it inside the sampling function */
110     do_texco_extend = false;
111   }
112
113   GPUNodeLink *norm, *col1, *col2, *col3, *input_coords;
114
115   int isdata = tex->color_space == SHD_COLORSPACE_NONE;
116   float blend = tex->projection_blend;
117
118   if (!ima)
119     return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
120
121   ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
122   if ((tex->color_space == SHD_COLORSPACE_COLOR) && ibuf &&
123       (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
124       GPU_material_do_color_management(mat)) {
125     do_color_correction = true;
126   }
127   BKE_image_release_ibuf(ima, ibuf, NULL);
128
129   if (!in[0].link)
130     in[0].link = GPU_attribute(CD_MTFACE, "");
131
132   node_shader_gpu_tex_mapping(mat, node, in, out);
133
134   switch (tex->projection) {
135     case SHD_PROJ_FLAT:
136       if (do_texco_clip) {
137         GPU_link(mat, "set_rgb", in[0].link, &input_coords);
138       }
139       if (do_texco_extend) {
140         GPU_link(mat, "point_texco_clamp", in[0].link, GPU_image(ima, iuser, isdata), &in[0].link);
141       }
142       GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
143       break;
144     case SHD_PROJ_BOX:
145       GPU_link(mat,
146                "mat3_mul",
147                GPU_builtin(GPU_VIEW_NORMAL),
148                GPU_builtin(GPU_INVERSE_NORMAL_MATRIX),
149                &norm);
150       GPU_link(mat,
151                gpu_node_name,
152                in[0].link,
153                norm,
154                GPU_image(ima, iuser, isdata),
155                &col1,
156                &col2,
157                &col3);
158       if (do_color_correction) {
159         GPU_link(mat, "srgb_to_linearrgb", col1, &col1);
160         GPU_link(mat, "srgb_to_linearrgb", col2, &col2);
161         GPU_link(mat, "srgb_to_linearrgb", col3, &col3);
162       }
163       GPU_link(mat,
164                "node_tex_image_box",
165                in[0].link,
166                norm,
167                col1,
168                col2,
169                col3,
170                GPU_image(ima, iuser, isdata),
171                GPU_uniform(&blend),
172                &out[0].link,
173                &out[1].link);
174       break;
175     case SHD_PROJ_SPHERE:
176       GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
177       GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
178       if (do_texco_clip) {
179         GPU_link(mat, "set_rgb", in[0].link, &input_coords);
180       }
181       if (do_texco_extend) {
182         GPU_link(mat, "point_texco_clamp", in[0].link, GPU_image(ima, iuser, isdata), &in[0].link);
183       }
184       GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
185       break;
186     case SHD_PROJ_TUBE:
187       GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
188       GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
189       if (do_texco_clip) {
190         GPU_link(mat, "set_rgb", in[0].link, &input_coords);
191       }
192       if (do_texco_extend) {
193         GPU_link(mat, "point_texco_clamp", in[0].link, GPU_image(ima, iuser, isdata), &in[0].link);
194       }
195       GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
196       break;
197   }
198
199   if (do_texco_clip && (tex->projection != SHD_PROJ_BOX)) {
200     GPU_link(mat,
201              names_clip[tex->interpolation],
202              input_coords,
203              GPU_image(ima, iuser, isdata),
204              out[0].link,
205              &out[0].link,
206              &out[1].link);
207   }
208
209   if (do_color_correction && (tex->projection != SHD_PROJ_BOX)) {
210     GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
211   }
212
213   return true;
214 }
215
216 /* node type definition */
217 void register_node_type_sh_tex_image(void)
218 {
219   static bNodeType ntype;
220
221   sh_node_type_base(&ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, 0);
222   node_type_socket_templates(&ntype, sh_node_tex_image_in, sh_node_tex_image_out);
223   node_type_init(&ntype, node_shader_init_tex_image);
224   node_type_storage(
225       &ntype, "NodeTexImage", node_free_standard_storage, node_copy_standard_storage);
226   node_type_gpu(&ntype, node_shader_gpu_tex_image);
227   node_type_label(&ntype, node_image_label);
228   node_type_size_preset(&ntype, NODE_SIZE_LARGE);
229
230   nodeRegisterType(&ntype);
231 }