Blender V4.3
node_shader_tex_wave.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_texture.h"
9
10#include "BLI_math_vector.h"
11#include "BLI_noise.hh"
12
13#include "NOD_multi_function.hh"
14
15#include "RNA_access.hh"
16
17#include "UI_interface.hh"
18#include "UI_resources.hh"
19
21
23{
24 b.is_function_node();
25 b.add_input<decl::Vector>("Vector").implicit_field(implicit_field_inputs::position);
26 b.add_input<decl::Float>("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f).description(
27 "Overall texture scale");
28 b.add_input<decl::Float>("Distortion")
29 .min(-1000.0f)
30 .max(1000.0f)
31 .default_value(0.0f)
32 .description("Amount of distortion of the wave");
33 b.add_input<decl::Float>("Detail").min(0.0f).max(15.0f).default_value(2.0f).description(
34 "Amount of distortion noise detail");
35 b.add_input<decl::Float>("Detail Scale")
36 .min(-1000.0f)
37 .max(1000.0f)
38 .default_value(1.0f)
39 .description("Scale of distortion noise");
40 b.add_input<decl::Float>("Detail Roughness")
41 .min(0.0f)
42 .max(1.0f)
43 .default_value(0.5f)
44 .subtype(PROP_FACTOR)
45 .description("Blend between a smoother noise pattern, and rougher with sharper peaks");
46 b.add_input<decl::Float>("Phase Offset")
47 .min(-1000.0f)
48 .max(1000.0f)
49 .default_value(0.0f)
50 .description(
51 "Position of the wave along the Bands Direction.\n"
52 "This can be used as an input for more control over the distortion");
53 b.add_output<decl::Color>("Color").no_muted_links();
54 b.add_output<decl::Float>("Fac").no_muted_links();
55}
56
58{
59 uiItemR(layout, ptr, "wave_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
60 int type = RNA_enum_get(ptr, "wave_type");
61 if (type == SHD_WAVE_BANDS) {
62 uiItemR(layout, ptr, "bands_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
63 }
64 else { /* SHD_WAVE_RINGS */
65 uiItemR(layout, ptr, "rings_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
66 }
67
68 uiItemR(layout, ptr, "wave_profile", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
69}
70
71static void node_shader_init_tex_wave(bNodeTree * /*ntree*/, bNode *node)
72{
73 NodeTexWave *tex = MEM_cnew<NodeTexWave>(__func__);
75 BKE_texture_colormapping_default(&tex->base.color_mapping);
76 tex->wave_type = SHD_WAVE_BANDS;
77 tex->bands_direction = SHD_WAVE_BANDS_DIRECTION_X;
78 tex->rings_direction = SHD_WAVE_RINGS_DIRECTION_X;
79 tex->wave_profile = SHD_WAVE_PROFILE_SIN;
80 node->storage = tex;
81}
82
84 bNode *node,
85 bNodeExecData * /*execdata*/,
86 GPUNodeStack *in,
87 GPUNodeStack *out)
88{
89 node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
90 node_shader_gpu_tex_mapping(mat, node, in, out);
91
92 NodeTexWave *tex = (NodeTexWave *)node->storage;
93 float wave_type = tex->wave_type;
94 float bands_direction = tex->bands_direction;
95 float rings_direction = tex->rings_direction;
96 float wave_profile = tex->wave_profile;
97
98 return GPU_stack_link(mat,
99 node,
100 "node_tex_wave",
101 in,
102 out,
103 GPU_constant(&wave_type),
104 GPU_constant(&bands_direction),
105 GPU_constant(&rings_direction),
106 GPU_constant(&wave_profile));
107}
108
110 private:
111 int wave_type_;
112 int bands_direction_;
113 int rings_direction_;
114 int wave_profile_;
115
116 public:
117 WaveFunction(int wave_type, int bands_direction, int rings_direction, int wave_profile)
118 : wave_type_(wave_type),
119 bands_direction_(bands_direction),
120 rings_direction_(rings_direction),
121 wave_profile_(wave_profile)
122 {
123 static const mf::Signature signature = []() {
125 mf::SignatureBuilder builder{"MagicFunction", signature};
126 builder.single_input<float3>("Vector");
127 builder.single_input<float>("Scale");
128 builder.single_input<float>("Distortion");
129 builder.single_input<float>("Detail");
130 builder.single_input<float>("Detail Scale");
131 builder.single_input<float>("Detail Roughness");
132 builder.single_input<float>("Phase Offset");
133 builder.single_output<ColorGeometry4f>("Color", mf::ParamFlag::SupportsUnusedOutput);
134 builder.single_output<float>("Fac");
135 return signature;
136 }();
137 this->set_signature(&signature);
138 }
139
140 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
141 {
142 const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
143 const VArray<float> &scale = params.readonly_single_input<float>(1, "Scale");
144 const VArray<float> &distortion = params.readonly_single_input<float>(2, "Distortion");
145 const VArray<float> &detail = params.readonly_single_input<float>(3, "Detail");
146 const VArray<float> &dscale = params.readonly_single_input<float>(4, "Detail Scale");
147 const VArray<float> &droughness = params.readonly_single_input<float>(5, "Detail Roughness");
148 const VArray<float> &phase = params.readonly_single_input<float>(6, "Phase Offset");
149
151 params.uninitialized_single_output_if_required<ColorGeometry4f>(7, "Color");
152 MutableSpan<float> r_fac = params.uninitialized_single_output<float>(8, "Fac");
153
154 mask.foreach_index([&](const int64_t i) {
155 float3 p = vector[i] * scale[i];
156 /* Prevent precision issues on unit coordinates. */
157 p = (p + 0.000001f) * 0.999999f;
158
159 float n = 0.0f;
160 float val = 0.0f;
161
162 switch (wave_type_) {
163 case SHD_WAVE_BANDS:
164 switch (bands_direction_) {
166 n = p.x * 20.0f;
167 break;
169 n = p.y * 20.0f;
170 break;
172 n = p.z * 20.0f;
173 break;
175 n = (p.x + p.y + p.z) * 10.0f;
176 break;
177 }
178 break;
179 case SHD_WAVE_RINGS:
180 float3 rp = p;
181 switch (rings_direction_) {
183 rp *= float3(0.0f, 1.0f, 1.0f);
184 break;
186 rp *= float3(1.0f, 0.0f, 1.0f);
187 break;
189 rp *= float3(1.0f, 1.0f, 0.0f);
190 break;
192 /* Ignore. */
193 break;
194 }
195 n = len_v3(rp) * 20.0f;
196 break;
197 }
198
199 n += phase[i];
200
201 if (distortion[i] != 0.0f) {
202 n += distortion[i] *
203 (noise::perlin_fbm<float3>(p * dscale[i], detail[i], droughness[i], 2.0f, true) *
204 2.0f -
205 1.0f);
206 }
207
208 switch (wave_profile_) {
210 val = 0.5f + 0.5f * sinf(n - M_PI_2);
211 break;
213 n /= M_PI * 2.0f;
214 val = n - floorf(n);
215 break;
217 n /= M_PI * 2.0f;
218 val = fabsf(n - floorf(n + 0.5f)) * 2.0f;
219 break;
220 }
221
222 r_fac[i] = val;
223 });
224 if (!r_color.is_empty()) {
225 mask.foreach_index([&](const int64_t i) {
226 r_color[i] = ColorGeometry4f(r_fac[i], r_fac[i], r_fac[i], 1.0f);
227 });
228 }
229 }
230};
231
233{
234 const bNode &node = builder.node();
235 NodeTexWave *tex = (NodeTexWave *)node.storage;
237 tex->wave_type, tex->bands_direction, tex->rings_direction, tex->wave_profile);
238}
239
241#ifdef WITH_MATERIALX
242{
243 NodeTexWave *tex = (NodeTexWave *)node_->storage;
244
245 NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
246 NodeItem distortion = get_input_value("Distortion", NodeItem::Type::Float);
247 NodeItem detail = get_input_default("Detail", NodeItem::Type::Float);
248 NodeItem detail_scale = get_input_value("Detail Scale", NodeItem::Type::Float);
249 NodeItem detail_rough = get_input_value("Detail Roughness", NodeItem::Type::Float);
250 NodeItem phase_offset = get_input_value("Phase Offset", NodeItem::Type::Float);
251 NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
252 if (!vector) {
253 vector = texcoord_node(NodeItem::Type::Vector3);
254 }
255
256 /* Adjustment to get result as Cycles. */
257 distortion = distortion * val(10.0f);
258 detail_scale = detail_scale * val(10.0f);
259
260 NodeItem pos = vector * scale;
261 NodeItem fractal = create_node("fractal3d",
262 NodeItem::Type::Float,
263 {{"position", pos},
264 {"octaves", val(int(detail.value->asA<float>()))},
265 {"lacunarity", val(2.0f)}});
266 NodeItem value = val(0.0f);
267 switch (tex->wave_type) {
268 case SHD_WAVE_BANDS:
269 switch (tex->bands_direction) {
271 value = pos[0] * val(20.0f);
272 break;
274 value = pos[1] * val(20.0f);
275 break;
277 value = pos[2] * val(20.0f);
278 break;
280 value = (pos[0] + pos[1] + pos[2]) * val(10.0f);
281 break;
282 default:
284 }
285 break;
286 case SHD_WAVE_RINGS:
287 NodeItem rpos = pos;
288 switch (tex->rings_direction) {
290 rpos = pos * val(MaterialX::Vector3(0.0f, 1.0f, 1.0f));
291 break;
293 rpos = pos * val(MaterialX::Vector3(1.0f, 0.0f, 1.0f));
294 break;
296 rpos = pos * val(MaterialX::Vector3(1.0f, 1.0f, 0.0f));
297 break;
299 /* Ignore. */
300 break;
301 default:
303 }
304 value = rpos.length() * val(20.0f);
305 break;
306 }
307 value = value + phase_offset + distortion * detail_scale * fractal;
308
309 NodeItem res = empty();
310 switch (tex->wave_profile) {
312 res = val(0.5f) + val(0.5f) * (value - val(float(M_PI_2))).sin();
313 break;
315 value = value / val(float(M_PI * 2.0f));
316 res = value - value.floor();
317 break;
319 value = value / val(float(M_PI * 2.0f));
320 res = (value - (value + val(0.5f)).floor()).abs() * val(2.0f);
321 break;
322 default:
324 }
325 return res;
326}
327#endif
329
330} // namespace blender::nodes::node_shader_tex_wave_cc
331
333{
334 namespace file_ns = blender::nodes::node_shader_tex_wave_cc;
335
336 static blender::bke::bNodeType ntype;
337
339 ntype.declare = file_ns::sh_node_tex_wave_declare;
340 ntype.draw_buttons = file_ns::node_shader_buts_tex_wave;
342 ntype.initfunc = file_ns::node_shader_init_tex_wave;
345 ntype.gpu_fn = file_ns::node_shader_gpu_tex_wave;
346 ntype.build_multi_function = file_ns::sh_node_wave_tex_build_multi_function;
347 ntype.materialx_fn = file_ns::node_shader_materialx;
348
350}
#define SH_NODE_TEX_WAVE
Definition BKE_node.hh:935
#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 M_PI_2
#define M_PI
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
@ SHD_WAVE_RINGS_DIRECTION_Z
@ SHD_WAVE_RINGS_DIRECTION_Y
@ SHD_WAVE_RINGS_DIRECTION_X
@ SHD_WAVE_RINGS_DIRECTION_SPHERICAL
@ SHD_WAVE_BANDS_DIRECTION_Y
@ SHD_WAVE_BANDS_DIRECTION_X
@ SHD_WAVE_BANDS_DIRECTION_Z
@ SHD_WAVE_BANDS_DIRECTION_DIAGONAL
@ SHD_WAVE_PROFILE_SIN
@ SHD_WAVE_PROFILE_TRI
@ SHD_WAVE_PROFILE_SAW
@ SHD_WAVE_RINGS
@ SHD_WAVE_BANDS
@ TEXMAP_TYPE_POINT
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
@ PROP_FACTOR
Definition RNA_types.hh:154
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
void set_signature(const Signature *signature)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
WaveFunction(int wave_type, int bands_direction, int rings_direction, int wave_profile)
local_group_size(16, 16) .push_constant(Type b
#define sinf(x)
#define floorf(x)
#define fabsf(x)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 floor(const float2 a)
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
T sin(const AngleRadianBase< T > &a)
void position(const bNode &, void *r_value)
static void sh_node_wave_tex_build_multi_function(NodeMultiFunctionBuilder &builder)
static void node_shader_init_tex_wave(bNodeTree *, bNode *node)
static void node_shader_buts_tex_wave(uiLayout *layout, bContext *, PointerRNA *ptr)
static void sh_node_tex_wave_declare(NodeDeclarationBuilder &b)
static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
template float perlin_fbm< float3 >(float3 p, const float detail, const float roughness, const float lacunarity, const bool normalize)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
void register_node_type_sh_tex_wave()
void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *)
void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
void sh_fn_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
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
int RNA_enum_get(PointerRNA *ptr, const char *name)
#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
ccl_device_inline int abs(int x)
Definition util/math.h:120
PointerRNA * ptr
Definition wm_files.cc:4126