Blender V4.3
node_shader_tex_white_noise.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
7#include "BLI_noise.hh"
8
10
11#include "NOD_multi_function.hh"
12
13#include "UI_interface.hh"
14#include "UI_resources.hh"
15
17
19{
20 b.is_function_node();
21 b.add_input<decl::Vector>("Vector").min(-10000.0f).max(10000.0f).implicit_field(
23 b.add_input<decl::Float>("W")
24 .min(-10000.0f)
25 .max(10000.0f)
26 .make_available([](bNode &node) {
27 /* Default to 1 instead of 4, because it is faster. */
28 node.custom1 = 1;
29 })
30 .description("Value used as seed in 1D and 4D dimensions");
31 b.add_output<decl::Float>("Value");
32 b.add_output<decl::Color>("Color");
33}
34
36{
37 uiItemR(layout, ptr, "noise_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
38}
39
40static void node_shader_init_tex_white_noise(bNodeTree * /*ntree*/, bNode *node)
41{
42 node->custom1 = 3;
43}
44
45static const char *gpu_shader_get_name(const int dimensions)
46{
47 BLI_assert(dimensions >= 1 && dimensions <= 4);
48 return std::array{"node_white_noise_1d",
49 "node_white_noise_2d",
50 "node_white_noise_3d",
51 "node_white_noise_4d"}[dimensions - 1];
52}
53
55 bNode *node,
56 bNodeExecData * /*execdata*/,
57 GPUNodeStack *in,
58 GPUNodeStack *out)
59{
60 const char *name = gpu_shader_get_name(node->custom1);
61 return GPU_stack_link(mat, node, name, in, out);
62}
63
65{
66 bNodeSocket *sockVector = bke::node_find_socket(node, SOCK_IN, "Vector");
67 bNodeSocket *sockW = bke::node_find_socket(node, SOCK_IN, "W");
68
69 bke::node_set_socket_availability(ntree, sockVector, node->custom1 != 1);
70 bke::node_set_socket_availability(ntree, sockW, node->custom1 == 1 || node->custom1 == 4);
71}
72
74 private:
75 int dimensions_;
76
77 public:
78 WhiteNoiseFunction(int dimensions) : dimensions_(dimensions)
79 {
80 BLI_assert(dimensions >= 1 && dimensions <= 4);
81 static std::array<mf::Signature, 4> signatures{
86 };
87 this->set_signature(&signatures[dimensions - 1]);
88 }
89
90 static mf::Signature create_signature(int dimensions)
91 {
93 mf::SignatureBuilder builder{"WhiteNoise", signature};
94
95 if (ELEM(dimensions, 2, 3, 4)) {
96 builder.single_input<float3>("Vector");
97 }
98 if (ELEM(dimensions, 1, 4)) {
99 builder.single_input<float>("W");
100 }
101
102 builder.single_output<float>("Value", mf::ParamFlag::SupportsUnusedOutput);
103 builder.single_output<ColorGeometry4f>("Color", mf::ParamFlag::SupportsUnusedOutput);
104
105 return signature;
106 }
107
108 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
109 {
110 int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4);
111
112 MutableSpan<float> r_value = params.uninitialized_single_output_if_required<float>(param++,
113 "Value");
115 params.uninitialized_single_output_if_required<ColorGeometry4f>(param++, "Color");
116
117 const bool compute_value = !r_value.is_empty();
118 const bool compute_color = !r_color.is_empty();
119
120 switch (dimensions_) {
121 case 1: {
122 const VArray<float> &w = params.readonly_single_input<float>(0, "W");
123 if (compute_color) {
124 mask.foreach_index([&](const int64_t i) {
126 r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
127 });
128 }
129 if (compute_value) {
130 mask.foreach_index(
131 [&](const int64_t i) { r_value[i] = noise::hash_float_to_float(w[i]); });
132 }
133 break;
134 }
135 case 2: {
136 const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
137 if (compute_color) {
138 mask.foreach_index([&](const int64_t i) {
140 r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
141 });
142 }
143 if (compute_value) {
144 mask.foreach_index([&](const int64_t i) {
145 r_value[i] = noise::hash_float_to_float(float2(vector[i].x, vector[i].y));
146 });
147 }
148 break;
149 }
150 case 3: {
151 const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
152 if (compute_color) {
153 mask.foreach_index([&](const int64_t i) {
155 r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
156 });
157 }
158 if (compute_value) {
159 mask.foreach_index(
160 [&](const int64_t i) { r_value[i] = noise::hash_float_to_float(vector[i]); });
161 }
162 break;
163 }
164 case 4: {
165 const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
166 const VArray<float> &w = params.readonly_single_input<float>(1, "W");
167 if (compute_color) {
168 mask.foreach_index([&](const int64_t i) {
170 float4(vector[i].x, vector[i].y, vector[i].z, w[i]));
171 r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
172 });
173 }
174 if (compute_value) {
175 mask.foreach_index([&](const int64_t i) {
176 r_value[i] = noise::hash_float_to_float(
177 float4(vector[i].x, vector[i].y, vector[i].z, w[i]));
178 });
179 }
180 break;
181 }
182 }
183 }
184};
185
187{
188 const bNode &node = builder.node();
190}
191
193#ifdef WITH_MATERIALX
194{
195 /* MaterialX cellnoise node rounds float value of texture coordinate.
196 * Therefore it changes at different integer coordinates.
197 * The simple trick would be to multiply the texture coordinate by a large number. */
198 const float LARGE_NUMBER = 10000.0f;
199
200 NodeItem noise = empty();
201 NodeItem vector = empty();
202 NodeItem w = empty();
203
204 int dimension = node_->custom1;
205 switch (dimension) {
206 case 1:
207 w = get_input_value("W", NodeItem::Type::Vector2);
208 noise = create_node(
209 "cellnoise2d", NodeItem::Type::Float, {{"texcoord", w * val(LARGE_NUMBER)}});
210 break;
211 case 2:
212 vector = get_input_link("Vector", NodeItem::Type::Vector2);
213 if (!vector) {
214 vector = texcoord_node();
215 }
216 noise = create_node(
217 "cellnoise2d", NodeItem::Type::Float, {{"texcoord", vector * val(LARGE_NUMBER)}});
218 break;
219 case 3:
220 vector = get_input_link("Vector", NodeItem::Type::Vector3);
221 if (!vector) {
222 vector = texcoord_node(NodeItem::Type::Vector3);
223 }
224 noise = create_node(
225 "cellnoise3d", NodeItem::Type::Float, {{"position", vector * val(LARGE_NUMBER)}});
226 break;
227 case 4:
228 vector = get_input_link("Vector", NodeItem::Type::Vector3);
229 if (!vector) {
230 vector = texcoord_node(NodeItem::Type::Vector3);
231 }
232 w = get_input_value("W", NodeItem::Type::Float);
233 noise = create_node(
234 "cellnoise3d", NodeItem::Type::Float, {{"position", (vector + w) * val(LARGE_NUMBER)}});
235 break;
236 default:
238 break;
239 }
240
241 if (STREQ(socket_out_->name, "Value")) {
242 return noise;
243 }
244
245 /* NOTE: cellnoise node doesn't have colored output, so we create hsvtorgb node and put
246 * noise in first (Hue) channel to generate color. */
247 NodeItem combine = create_node("combine3",
248 NodeItem::Type::Color3,
249 {{"in1", noise}, {"in2", val(1.0f)}, {"in3", val(0.5f)}});
250 return create_node("hsvtorgb", NodeItem::Type::Color3, {{"in", combine}});
251}
252#endif
254
255} // namespace blender::nodes::node_shader_tex_white_noise_cc
256
258{
260
261 static blender::bke::bNodeType ntype;
262
263 sh_fn_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE);
264 ntype.declare = file_ns::sh_node_tex_white_noise_declare;
265 ntype.draw_buttons = file_ns::node_shader_buts_white_noise;
266 ntype.initfunc = file_ns::node_shader_init_tex_white_noise;
267 ntype.gpu_fn = file_ns::gpu_shader_tex_white_noise;
268 ntype.updatefunc = file_ns::node_shader_update_tex_white_noise;
269 ntype.build_multi_function = file_ns::sh_node_noise_build_multi_function;
270 ntype.materialx_fn = file_ns::node_shader_materialx;
271
273}
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:414
#define SH_NODE_TEX_WHITE_NOISE
Definition BKE_node.hh:987
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
#define STREQ(a, b)
@ SOCK_IN
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr bool is_empty() const
Definition BLI_span.hh:510
void set_signature(const Signature *signature)
void make_available(bNode &node) const
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_set_socket_availability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
Definition node.cc:3911
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
void position(const bNode &, void *r_value)
static const char * gpu_shader_get_name(const int dimensions)
static void sh_node_tex_white_noise_declare(NodeDeclarationBuilder &b)
static void node_shader_buts_white_noise(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_shader_update_tex_white_noise(bNodeTree *ntree, bNode *node)
static int gpu_shader_tex_white_noise(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder)
static void node_shader_init_tex_white_noise(bNodeTree *, bNode *node)
float hash_float_to_float(float k)
Definition noise.cc:188
float3 hash_float_to_float3(float k)
Definition noise.cc:225
VecBase< float, 4 > float4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
void register_node_type_sh_tex_white_noise()
void sh_fn_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
#define min(a, b)
Definition sort.c:32
__int64 int64_t
Definition stdint.h:89
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
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:318
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:336
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:257
PointerRNA * ptr
Definition wm_files.cc:4126