Blender V4.3
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(implicit_field_inputs::position);
22 b.add_output<decl::Color>("Color").no_muted_links();
23 b.add_output<decl::Float>("Alpha").no_muted_links();
24}
25
26static void node_shader_init_tex_image(bNodeTree * /*ntree*/, bNode *node)
27{
28 NodeTexImage *tex = MEM_cnew<NodeTexImage>(__func__);
32
33 node->storage = tex;
34}
35
37 bNode *node,
38 bNodeExecData * /*execdata*/,
39 GPUNodeStack *in,
40 GPUNodeStack *out)
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
61 node_shader_gpu_tex_mapping(mat, node, in, out);
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 if (ima->source == IMA_SRC_TILED) {
94 const char *gpu_node_name = use_cubic ? "node_tex_tile_cubic" : "node_tex_tile_linear";
95 GPUNodeLink *gpu_image, *gpu_image_tile_mapping;
96 GPU_image_tiled(mat, ima, iuser, sampler_state, &gpu_image, &gpu_image_tile_mapping);
97 /* UDIM tiles needs a `sampler2DArray` and `sampler1DArray` for tile mapping. */
98 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image, gpu_image_tile_mapping);
99 }
100 else {
101 const char *gpu_node_name = use_cubic ? "node_tex_image_cubic" : "node_tex_image_linear";
102
103 switch (tex->projection) {
104 case SHD_PROJ_FLAT: {
105 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
106 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
107 break;
108 }
109 case SHD_PROJ_BOX: {
110 gpu_node_name = use_cubic ? "tex_box_sample_cubic" : "tex_box_sample_linear";
111 GPUNodeLink *vnor, *wnor, *col1, *col2, *col3;
113 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
114 GPU_link(mat, "world_normals_get", &vnor);
115 GPU_link(mat, "normal_transform_world_to_object", vnor, &wnor);
116 GPU_link(mat, gpu_node_name, in[0].link, wnor, gpu_image, &col1, &col2, &col3);
117 GPU_link(mat, "tex_box_blend", wnor, col1, col2, col3, blend, &out[0].link, &out[1].link);
118 break;
119 }
120 case SHD_PROJ_SPHERE: {
121 /* This projection is known to have a derivative discontinuity.
122 * Hide it by turning off mipmapping. */
124 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
125 GPU_link(mat, "point_texco_remap_square", *texco, texco);
126 GPU_link(mat, "point_map_to_sphere", *texco, texco);
127 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
128 break;
129 }
130 case SHD_PROJ_TUBE: {
131 /* This projection is known to have a derivative discontinuity.
132 * Hide it by turning off mipmapping. */
134 GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
135 GPU_link(mat, "point_texco_remap_square", *texco, texco);
136 GPU_link(mat, "point_map_to_tube", *texco, texco);
137 GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
138 break;
139 }
140 }
141 }
142
143 if (out[0].hasoutput) {
146 {
147 /* Don't let alpha affect color output in these cases. */
148 GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
149 }
150 else {
151 /* Output premultiplied alpha depending on alpha socket usage. This makes
152 * it so that if we blend the color with a transparent shader using alpha as
153 * a factor, we don't multiply alpha into the color twice. And if we do
154 * not, then there will be no artifacts from zero alpha areas. */
155 if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
156 if (out[1].hasoutput) {
157 GPU_link(mat, "color_alpha_unpremultiply", out[0].link, &out[0].link);
158 }
159 else {
160 GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
161 }
162 }
163 else {
164 if (out[1].hasoutput) {
165 GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
166 }
167 else {
168 GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link);
169 }
170 }
171 }
172 }
173
174 return true;
175}
176
178#ifdef WITH_MATERIALX
179{
180 /* Getting node name for Color output. This name will be used for <image> node. */
181 std::string image_node_name = node_name(false) + "_Color";
182
183 NodeItem res = empty();
184 res.node = graph_->getNode(image_node_name);
185 if (!res.node) {
186 res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
187
188 Image *image = (Image *)node_->id;
189 if (image) {
190 NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
191
192 std::string image_path = image->id.name;
193 if (export_params_.image_fn) {
194 Scene *scene = DEG_get_input_scene(depsgraph_);
195 Main *bmain = DEG_get_bmain(depsgraph_);
196 image_path = export_params_.image_fn(bmain, scene, image, &tex_image->iuser);
197 }
198
199 NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
200 if (!vector) {
201 vector = texcoord_node();
202 }
203 /* TODO: add math to vector depending of tex_image->projection */
204
205 std::string filtertype;
206 switch (tex_image->interpolation) {
208 filtertype = "linear";
209 break;
211 filtertype = "closest";
212 break;
213 case SHD_INTERP_CUBIC:
214 case SHD_INTERP_SMART:
215 filtertype = "cubic";
216 break;
217 default:
219 }
220 std::string addressmode;
221 switch (tex_image->extension) {
223 addressmode = "periodic";
224 break;
226 addressmode = "clamp";
227 break;
229 addressmode = "constant";
230 break;
232 addressmode = "mirror";
233 break;
234 default:
236 }
237
238 NodeItem::Type node_type = NodeItem::Type::Color4;
239 const char *node_colorspace = nullptr;
240
241 const char *image_colorspace = image->colorspace_settings.name;
242 if (IMB_colormanagement_space_name_is_data(image_colorspace)) {
243 node_type = NodeItem::Type::Vector4;
244 }
245 else if (IMB_colormanagement_space_name_is_scene_linear(image_colorspace)) {
246 node_colorspace = "lin_rec709";
247 }
248 else if (IMB_colormanagement_space_name_is_srgb(image_colorspace)) {
249 node_colorspace = "srgb_texture";
250 }
251
252 res = create_node("image",
253 node_type,
254 {{"texcoord", vector},
255 {"filtertype", val(filtertype)},
256 {"uaddressmode", val(addressmode)},
257 {"vaddressmode", val(addressmode)}});
258 res.set_input("file", image_path, NodeItem::Type::Filename);
259 res.node->setName(image_node_name);
260 if (node_colorspace) {
261 res.node->setAttribute("colorspace", node_colorspace);
262 }
263 }
264 }
265
266 if (STREQ(socket_out_->name, "Alpha")) {
267 res = res[3];
268 }
269 return res;
270}
271#endif
273
274} // namespace blender::nodes::node_shader_tex_image_cc
275
277{
279
280 static blender::bke::bNodeType ntype;
281
282 sh_node_type_base(&ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE);
283 ntype.declare = file_ns::sh_node_tex_image_declare;
284 ntype.initfunc = file_ns::node_shader_init_tex_image;
287 ntype.gpu_fn = file_ns::node_shader_gpu_tex_image;
290 ntype.materialx_fn = file_ns::node_shader_materialx;
291
293}
void BKE_imageuser_default(ImageUser *iuser)
#define SH_NODE_TEX_IMAGE
Definition BKE_node.hh:930
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:414
void BKE_texture_mapping_default(struct TexMapping *texmap, int type)
Definition texture.cc:247
void BKE_texture_colormapping_default(struct ColorMapping *colormap)
Definition texture.cc:350
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#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_ALPHA_IGNORE
@ IMA_ALPHA_PREMUL
@ IMA_ALPHA_CHANNEL_PACKED
@ IMA_SRC_TILED
@ SHD_PROJ_TUBE
@ SHD_PROJ_SPHERE
@ SHD_PROJ_BOX
@ SHD_PROJ_FLAT
@ SHD_IMAGE_EXTENSION_MIRROR
@ SHD_IMAGE_EXTENSION_CLIP
@ SHD_IMAGE_EXTENSION_REPEAT
@ SHD_IMAGE_EXTENSION_EXTEND
@ SHD_INTERP_LINEAR
@ SHD_INTERP_SMART
@ SHD_INTERP_CUBIC
@ SHD_INTERP_CLOSEST
@ 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)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
local_group_size(16, 16) .push_constant(Type b
void node_type_size_preset(bNodeType *ntype, eNodeSizePreset size)
Definition node.cc:4614
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
void position(const bNode &, void *r_value)
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)
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
void register_node_type_sh_tex_image()
void sh_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *)
void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *, GPUNodeLink **link)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
void node_image_label(const bNodeTree *, const bNode *node, char *label, int label_maxncpy)
Definition node_util.cc:193
GPUNodeLink * link
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:218
NodeMaterialXFunction materialx_fn
Definition BKE_node.hh:320
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
void(* labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy)
Definition BKE_node.hh:249
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:318
NodeDeclareFunction declare
Definition BKE_node.hh:347