Blender V5.0
node_shader_tex_image.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "node_shader_util.hh"
6#include "node_util.hh"
7
8#include "BKE_image.hh"
9#include "BKE_node_runtime.hh"
10#include "BKE_texture.h"
11
13
15
17
19{
20 b.is_function_node();
21 b.add_input<decl::Vector>("Vector").implicit_field(NODE_DEFAULT_INPUT_POSITION_FIELD);
22 b.add_output<decl::Color>("Color").no_muted_links();
23 b.add_output<decl::Float>("Alpha").no_muted_links();
24}
25
35
37 bNode *node,
38 bNodeExecData * /*execdata*/,
41{
42 Image *ima = (Image *)node->id;
43 NodeTexImage *tex = (NodeTexImage *)node->storage;
44
45 /* We get the image user from the original node, since GPU image keeps
46 * a pointer to it and the dependency refreshes the original. */
47 bNode *node_original = node->runtime->original ? node->runtime->original : node;
48 NodeTexImage *tex_original = (NodeTexImage *)node_original->storage;
49 ImageUser *iuser = &tex_original->iuser;
50
51 if (!ima) {
52 return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
53 }
54
55 GPUNodeLink **texco = &in[0].link;
56 if (!*texco) {
57 *texco = GPU_attribute(mat, CD_AUTO_FROM_NAME, "");
58 node_shader_gpu_bump_tex_coord(mat, node, texco);
59 }
60
62
64
65 switch (tex->extension) {
69 break;
73 break;
77 break;
81 break;
82 default:
83 break;
84 }
85
87 /* TODO(fclem): For now assume mipmap is always enabled. */
90 }
91 const bool use_cubic = ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART);
92
93 /* Only use UDIM tiles if projection is flat.
94 * Otherwise treat the first tile as a single image. (See #141776). */
95 const bool use_udim = ima->source == IMA_SRC_TILED && tex->projection == SHD_PROJ_FLAT;
96 if (use_udim) {
97 const char *gpu_node_name = use_cubic ? "node_tex_tile_cubic" : "node_tex_tile_linear";
98 GPUNodeLink *gpu_image, *gpu_image_tile_mapping;
99 GPU_image_tiled(mat, ima, iuser, sampler_state, &gpu_image, &gpu_image_tile_mapping);
100 /* UDIM tiles needs a `sampler2DArray` and `sampler1DArray` for tile mapping. */
101 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image, gpu_image_tile_mapping);
102 }
103 else {
104 const char *gpu_node_name = use_cubic ? "node_tex_image_cubic" : "node_tex_image_linear";
105
106 switch (tex->projection) {
107 case SHD_PROJ_FLAT: {
108 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
109 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
110 break;
111 }
112 case SHD_PROJ_BOX: {
113 gpu_node_name = use_cubic ? "tex_box_sample_cubic" : "tex_box_sample_linear";
114 GPUNodeLink *vnor, *wnor, *col1, *col2, *col3;
116 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
117 GPU_link(mat, "world_normals_get", &vnor);
118 GPU_link(mat, "normal_transform_world_to_object", vnor, &wnor);
119 GPU_link(mat, gpu_node_name, in[0].link, wnor, gpu_image, &col1, &col2, &col3);
120 GPU_link(mat, "tex_box_blend", wnor, col1, col2, col3, blend, &out[0].link, &out[1].link);
121 break;
122 }
123 case SHD_PROJ_SPHERE: {
124 /* This projection is known to have a derivative discontinuity.
125 * Hide it by turning off mipmapping. */
127 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
128 GPU_link(mat, "point_texco_remap_square", *texco, texco);
129 GPU_link(mat, "point_map_to_sphere", *texco, texco);
130 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
131 break;
132 }
133 case SHD_PROJ_TUBE: {
134 /* This projection is known to have a derivative discontinuity.
135 * Hide it by turning off mipmapping. */
137 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
138 GPU_link(mat, "point_texco_remap_square", *texco, texco);
139 GPU_link(mat, "point_map_to_tube", *texco, texco);
140 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
141 break;
142 }
143 }
144 }
145
146 if (out[0].hasoutput) {
149 {
150 /* Don't let alpha affect color output in these cases. */
151 GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
152 }
153 else {
154 /* Output premultiplied alpha depending on alpha socket usage. This makes
155 * it so that if we blend the color with a transparent shader using alpha as
156 * a factor, we don't multiply alpha into the color twice. And if we do
157 * not, then there will be no artifacts from zero alpha areas. */
158 if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
159 if (out[1].hasoutput) {
160 GPU_link(mat, "color_alpha_unpremultiply", out[0].link, &out[0].link);
161 }
162 else {
163 GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
164 }
165 }
166 else {
167 if (out[1].hasoutput) {
168 GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
169 }
170 else {
171 GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link);
172 }
173 }
174 }
175 }
176
177 return true;
178}
179
181#ifdef WITH_MATERIALX
182{
183 /* Getting node name for Color output. This name will be used for <image> node. */
184 std::string image_node_name = node_name("Color");
185
186 NodeItem res = graph_.get_node(image_node_name);
187 if (!res.node) {
188 res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
189
190 Image *image = (Image *)node_->id;
191 if (image) {
192 NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
193
194 std::string image_path = image->id.name;
195 if (graph_.export_params.image_fn) {
196 Scene *scene = DEG_get_input_scene(graph_.depsgraph);
197 Main *bmain = DEG_get_bmain(graph_.depsgraph);
198 image_path = graph_.export_params.image_fn(bmain, scene, image, &tex_image->iuser);
199 }
200
201 NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
202 if (!vector) {
203 vector = texcoord_node();
204 }
205 /* TODO: add math to vector depending of tex_image->projection */
206
207 std::string filtertype;
208 switch (tex_image->interpolation) {
210 filtertype = "linear";
211 break;
213 filtertype = "closest";
214 break;
215 case SHD_INTERP_CUBIC:
216 case SHD_INTERP_SMART:
217 filtertype = "cubic";
218 break;
219 default:
221 }
222 std::string addressmode;
223 switch (tex_image->extension) {
225 addressmode = "periodic";
226 break;
228 addressmode = "clamp";
229 break;
231 addressmode = "constant";
232 break;
234 addressmode = "mirror";
235 break;
236 default:
238 }
239
240 NodeItem::Type node_type = NodeItem::Type::Color4;
241 const char *node_colorspace = nullptr;
242
243 const char *image_colorspace = image->colorspace_settings.name;
244 if (IMB_colormanagement_space_name_is_data(image_colorspace)) {
245 node_type = NodeItem::Type::Vector4;
246 }
247 else if (IMB_colormanagement_space_name_is_scene_linear(image_colorspace)) {
248 node_colorspace = "lin_rec709";
249 }
250 else if (IMB_colormanagement_space_name_is_srgb(image_colorspace)) {
251 node_colorspace = "srgb_texture";
252 }
253
254 res = create_node("image",
255 node_type,
256 {{"texcoord", vector},
257 {"filtertype", val(filtertype)},
258 {"uaddressmode", val(addressmode)},
259 {"vaddressmode", val(addressmode)}});
260 res.set_input("file", image_path, NodeItem::Type::Filename);
261 res.node->setName(image_node_name);
262 if (node_colorspace) {
263 res.node->setAttribute("colorspace", node_colorspace);
264 }
265 }
266 }
267
268 if (STREQ(socket_out_->identifier, "Alpha")) {
269 res = res[3];
270 }
271 return res;
272}
273#endif
275
276} // namespace blender::nodes::node_shader_tex_image_cc
277
279{
281
282 static blender::bke::bNodeType ntype;
283
284 sh_node_type_base(&ntype, "ShaderNodeTexImage", SH_NODE_TEX_IMAGE);
285 ntype.ui_name = "Image Texture";
286 ntype.ui_description = "Sample an image file as a texture";
287 ntype.enum_name_legacy = "TEX_IMAGE";
289 ntype.declare = file_ns::sh_node_tex_image_declare;
290 ntype.initfunc = file_ns::node_shader_init_tex_image;
293 ntype.gpu_fn = file_ns::node_shader_gpu_tex_image;
296 ntype.materialx_fn = file_ns::node_shader_materialx;
297
299}
void BKE_imageuser_default(ImageUser *iuser)
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:457
#define SH_NODE_TEX_IMAGE
void BKE_texture_mapping_default(struct TexMapping *texmap, int type)
Definition texture.cc:234
void BKE_texture_colormapping_default(struct ColorMapping *colormap)
Definition texture.cc:337
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define ELEM(...)
#define STREQ(a, b)
Main * DEG_get_bmain(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
@ CD_AUTO_FROM_NAME
@ IMA_SRC_TILED
@ IMA_ALPHA_IGNORE
@ IMA_ALPHA_PREMUL
@ IMA_ALPHA_CHANNEL_PACKED
@ NODE_DEFAULT_INPUT_POSITION_FIELD
@ SHD_INTERP_LINEAR
@ SHD_INTERP_SMART
@ SHD_INTERP_CUBIC
@ SHD_INTERP_CLOSEST
@ SHD_IMAGE_EXTENSION_MIRROR
@ SHD_IMAGE_EXTENSION_CLIP
@ SHD_IMAGE_EXTENSION_REPEAT
@ SHD_IMAGE_EXTENSION_EXTEND
@ SHD_PROJ_TUBE
@ SHD_PROJ_SPHERE
@ SHD_PROJ_BOX
@ SHD_PROJ_FLAT
@ TEXMAP_TYPE_POINT
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser, GPUSamplerState sampler_state)
void GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser, GPUSamplerState sampler_state, GPUNodeLink **r_image_tiled_link, GPUNodeLink **r_image_tiled_mapping_link)
GPUNodeLink * GPU_attribute(GPUMaterial *mat, eCustomDataType type, const char *name)
bool GPU_link(GPUMaterial *mat, const char *name,...)
GPUNodeLink * GPU_uniform(const float *num)
@ GPU_SAMPLER_EXTEND_MODE_MIRRORED_REPEAT
@ GPU_SAMPLER_EXTEND_MODE_REPEAT
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
@ GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER
@ GPU_SAMPLER_FILTERING_MIPMAP
@ GPU_SAMPLER_FILTERING_ANISOTROPIC
@ GPU_SAMPLER_FILTERING_LINEAR
bool IMB_colormanagement_space_name_is_srgb(const char *name)
bool IMB_colormanagement_space_name_is_scene_linear(const char *name)
bool IMB_colormanagement_space_name_is_data(const char *name)
#define in
#define out
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5414
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
Definition node.cc:5396
static void node_shader_init_tex_image(bNodeTree *, bNode *node)
static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void sh_node_tex_image_declare(NodeDeclarationBuilder &b)
std::vector< ElementType, Eigen::aligned_allocator< ElementType > > vector
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
void register_node_type_sh_tex_image()
void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *)
void sh_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *, GPUNodeLink **link)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
void node_image_label(const bNodeTree *, const bNode *node, char *label, int label_maxncpy)
Definition node_util.cc:189
GPUSamplerExtendMode extend_yz
static constexpr GPUSamplerState default_sampler()
GPUSamplerFiltering filtering
void disable_filtering_flag(GPUSamplerFiltering filtering_flags)
GPUSamplerExtendMode extend_x
ColorManagedColorspaceSettings colorspace_settings
short source
char alpha_mode
TexMapping tex_mapping
ColorMapping color_mapping
NodeTexBase base
struct ID * id
bNodeRuntimeHandle * runtime
void * storage
Defines a node type.
Definition BKE_node.hh:238
NodeMaterialXFunction materialx_fn
Definition BKE_node.hh:344
std::string ui_description
Definition BKE_node.hh:244
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:289
void(* labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy)
Definition BKE_node.hh:270
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:342
const char * enum_name_legacy
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:362
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)