Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/nodeitems_builtins.py3
-rw-r--r--source/blender/functions/FN_multi_function_params.hh16
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.cc159
3 files changed, 177 insertions, 1 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index b4619c2c949..aea9cbc5c62 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -604,6 +604,9 @@ geometry_node_categories = [
NodeItem("FunctionNodeFloatToInt"),
NodeItem("GeometryNodeSwitch"),
]),
+ GeometryNodeCategory("GEO_TEXTURE", "Texture", items=[
+ NodeItem("ShaderNodeTexNoise", poll=geometry_nodes_fields_poll),
+ ]),
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
NodeItem("ShaderNodeVectorCurve"),
NodeItem("ShaderNodeSeparateXYZ"),
diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh
index fe4d2b90d80..d187985de9d 100644
--- a/source/blender/functions/FN_multi_function_params.hh
+++ b/source/blender/functions/FN_multi_function_params.hh
@@ -272,6 +272,22 @@ class MFParams {
return span;
}
+ /**
+ * Same as #uninitialized_single_output, but returns an empty span when the output is not
+ * required.
+ */
+ template<typename T>
+ MutableSpan<T> uninitialized_single_output_if_required(int param_index, StringRef name = "")
+ {
+ return this->uninitialized_single_output_if_required(param_index, name).typed<T>();
+ }
+ GMutableSpan uninitialized_single_output_if_required(int param_index, StringRef name = "")
+ {
+ this->assert_correct_param(param_index, name, MFParamType::SingleOutput);
+ int data_index = builder_->signature_->data_index(param_index);
+ return builder_->mutable_spans_[data_index];
+ }
+
template<typename T>
const VVectorArray<T> &readonly_vector_input(int param_index, StringRef name = "")
{
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc
index de8e0916f4d..c0deb232b2d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc
@@ -19,6 +19,8 @@
#include "../node_shader_util.h"
+#include "BLI_noise.hh"
+
/* **************** NOISE ******************** */
static bNodeSocketTemplate sh_node_tex_noise_in[] = {
@@ -90,18 +92,173 @@ static void node_shader_update_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
nodeSetSocketAvailability(sockW, tex->dimensions == 1 || tex->dimensions == 4);
}
+namespace blender::nodes {
+
+class NoiseFunction : public fn::MultiFunction {
+ private:
+ int dimensions_;
+
+ public:
+ NoiseFunction(int dimensions) : dimensions_(dimensions)
+ {
+ BLI_assert(dimensions >= 1 && dimensions <= 4);
+ static std::array<fn::MFSignature, 4> signatures{
+ create_signature(1),
+ create_signature(2),
+ create_signature(3),
+ create_signature(4),
+ };
+ this->set_signature(&signatures[dimensions - 1]);
+ }
+
+ static fn::MFSignature create_signature(int dimensions)
+ {
+ fn::MFSignatureBuilder signature{"Noise"};
+
+ if (ELEM(dimensions, 2, 3, 4)) {
+ signature.single_input<float3>("Vector");
+ }
+ if (ELEM(dimensions, 1, 4)) {
+ signature.single_input<float>("W");
+ }
+
+ signature.single_input<float>("Scale");
+ signature.single_input<float>("Detail");
+ signature.single_input<float>("Roughness");
+ signature.single_input<float>("Distortion");
+
+ signature.single_output<float>("Fac");
+ signature.single_output<ColorGeometry4f>("Color");
+
+ return signature.build();
+ }
+
+ void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
+ {
+ int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4);
+ const VArray<float> &scale = params.readonly_single_input<float>(param++, "Scale");
+ const VArray<float> &detail = params.readonly_single_input<float>(param++, "Detail");
+ const VArray<float> &roughness = params.readonly_single_input<float>(param++, "Roughness");
+ const VArray<float> &distortion = params.readonly_single_input<float>(param++, "Distortion");
+
+ MutableSpan<float> r_factor = params.uninitialized_single_output_if_required<float>(param++,
+ "Fac");
+ MutableSpan<ColorGeometry4f> r_color =
+ params.uninitialized_single_output_if_required<ColorGeometry4f>(param++, "Color");
+
+ const bool compute_factor = !r_factor.is_empty();
+ const bool compute_color = !r_color.is_empty();
+
+ switch (dimensions_) {
+ case 1: {
+ const VArray<float> &w = params.readonly_single_input<float>(0, "W");
+ if (compute_factor) {
+ for (int64_t i : mask) {
+ const float position = w[i] * scale[i];
+ r_factor[i] = noise::perlin_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ }
+ }
+ if (compute_color) {
+ for (int64_t i : mask) {
+ const float position = w[i] * scale[i];
+ const float3 c = noise::perlin_float3_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
+ }
+ }
+ break;
+ }
+ case 2: {
+ const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
+ if (compute_factor) {
+ for (int64_t i : mask) {
+ const float2 position = vector[i] * scale[i];
+ r_factor[i] = noise::perlin_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ }
+ }
+ if (compute_color) {
+ for (int64_t i : mask) {
+ const float2 position = vector[i] * scale[i];
+ const float3 c = noise::perlin_float3_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
+ }
+ }
+ break;
+ }
+ case 3: {
+ const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
+ if (compute_factor) {
+ for (int64_t i : mask) {
+ const float3 position = vector[i] * scale[i];
+ r_factor[i] = noise::perlin_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ }
+ }
+ if (compute_color) {
+ for (int64_t i : mask) {
+ const float3 position = vector[i] * scale[i];
+ const float3 c = noise::perlin_float3_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
+ }
+ }
+ break;
+ }
+ case 4: {
+ const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
+ const VArray<float> &w = params.readonly_single_input<float>(1, "W");
+ if (compute_factor) {
+ for (int64_t i : mask) {
+ const float3 position_vector = vector[i] * scale[i];
+ const float position_w = w[i] * scale[i];
+ const float4 position{
+ position_vector[0], position_vector[1], position_vector[2], position_w};
+ r_factor[i] = noise::perlin_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ }
+ }
+ if (compute_color) {
+ for (int64_t i : mask) {
+ const float3 position_vector = vector[i] * scale[i];
+ const float position_w = w[i] * scale[i];
+ const float4 position{
+ position_vector[0], position_vector[1], position_vector[2], position_w};
+ const float3 c = noise::perlin_float3_fractal_distorted(
+ position, detail[i], roughness[i], distortion[i]);
+ r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
+ }
+ }
+ break;
+ }
+ }
+ }
+};
+
+static void sh_node_noise_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder)
+{
+ bNode &node = builder.node();
+ NodeTexNoise *tex = (NodeTexNoise *)node.storage;
+ builder.construct_and_set_matching_fn<NoiseFunction>(tex->dimensions);
+}
+
+} // namespace blender::nodes
+
/* node type definition */
void register_node_type_sh_tex_noise(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
node_type_socket_templates(&ntype, sh_node_tex_noise_in, sh_node_tex_noise_out);
node_type_init(&ntype, node_shader_init_tex_noise);
node_type_storage(
&ntype, "NodeTexNoise", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_noise);
node_type_update(&ntype, node_shader_update_tex_noise);
+ ntype.build_multi_function = blender::nodes::sh_node_noise_build_multi_function;
nodeRegisterType(&ntype);
}