Cleanup: deduplicate image user initialization, make consistent.
[blender.git] / source / blender / nodes / shader / nodes / node_shader_tex_environment.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_environment_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_environment_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     {-1, 0, ""},
42 };
43
44 static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node)
45 {
46   NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
47   BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
48   BKE_texture_colormapping_default(&tex->base.color_mapping);
49   tex->color_space = SHD_COLORSPACE_COLOR;
50   tex->projection = SHD_PROJ_EQUIRECTANGULAR;
51   BKE_imageuser_default(&tex->iuser);
52
53   node->storage = tex;
54 }
55
56 static int node_shader_gpu_tex_environment(GPUMaterial *mat,
57                                            bNode *node,
58                                            bNodeExecData *UNUSED(execdata),
59                                            GPUNodeStack *in,
60                                            GPUNodeStack *out)
61 {
62   Image *ima = (Image *)node->id;
63   NodeTexEnvironment *tex = node->storage;
64
65   /* We get the image user from the original node, since GPU image keeps
66    * a pointer to it and the dependency refreshes the original. */
67   bNode *node_original = node->original ? node->original : node;
68   NodeTexImage *tex_original = node_original->storage;
69   ImageUser *iuser = &tex_original->iuser;
70
71   int isdata = tex->color_space == SHD_COLORSPACE_NONE;
72   GPUNodeLink *outalpha;
73
74   if (!ima)
75     return GPU_stack_link(mat, node, "node_tex_environment_empty", in, out);
76
77   if (!in[0].link) {
78     GPU_link(mat, "node_tex_environment_texco", GPU_builtin(GPU_VIEW_POSITION), &in[0].link);
79   }
80
81   node_shader_gpu_tex_mapping(mat, node, in, out);
82
83   /* Compute texture coordinate. */
84   if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) {
85     /* To fix pole issue we clamp the v coordinate. The clamp value depends on the filter size. */
86     float clamp_size = (ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) ? 1.5 : 0.5;
87     GPU_link(mat,
88              "node_tex_environment_equirectangular",
89              in[0].link,
90              GPU_constant(&clamp_size),
91              GPU_image(ima, iuser, isdata),
92              &in[0].link);
93   }
94   else {
95     GPU_link(mat, "node_tex_environment_mirror_ball", in[0].link, &in[0].link);
96   }
97
98   /* Sample texture with correct interpolation. */
99   switch (tex->interpolation) {
100     case SHD_INTERP_LINEAR:
101       /* Force the highest mipmap and don't do anisotropic filtering.
102        * This is to fix the artifact caused by derivatives discontinuity. */
103       GPU_link(mat,
104                "node_tex_image_linear_no_mip",
105                in[0].link,
106                GPU_image(ima, iuser, isdata),
107                &out[0].link,
108                &outalpha);
109       break;
110     case SHD_INTERP_CLOSEST:
111       GPU_link(mat,
112                "node_tex_image_nearest",
113                in[0].link,
114                GPU_image(ima, iuser, isdata),
115                &out[0].link,
116                &outalpha);
117       break;
118     default:
119       GPU_link(mat,
120                "node_tex_image_cubic",
121                in[0].link,
122                GPU_image(ima, iuser, isdata),
123                &out[0].link,
124                &outalpha);
125       break;
126   }
127
128   ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
129   if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
130       GPU_material_do_color_management(mat)) {
131     GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
132   }
133   BKE_image_release_ibuf(ima, ibuf, NULL);
134
135   return true;
136 }
137
138 /* node type definition */
139 void register_node_type_sh_tex_environment(void)
140 {
141   static bNodeType ntype;
142
143   sh_node_type_base(&ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, 0);
144   node_type_socket_templates(&ntype, sh_node_tex_environment_in, sh_node_tex_environment_out);
145   node_type_init(&ntype, node_shader_init_tex_environment);
146   node_type_storage(
147       &ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage);
148   node_type_gpu(&ntype, node_shader_gpu_tex_environment);
149   node_type_label(&ntype, node_image_label);
150   node_type_size_preset(&ntype, NODE_SIZE_LARGE);
151
152   nodeRegisterType(&ntype);
153 }