[Bf-blender-cvs] [fc4f82d2004] master: Geometry Nodes: support Noise Texture node

Jacques Lucke noreply at git.blender.org
Mon Sep 20 13:12:33 CEST 2021


Commit: fc4f82d2004c843691d81afff0f7abb38caace0a
Author: Jacques Lucke
Date:   Mon Sep 20 13:12:25 2021 +0200
Branches: master
https://developer.blender.org/rBfc4f82d2004c843691d81afff0f7abb38caace0a

Geometry Nodes: support Noise Texture node

This makes the Noise Texture node available in geometry nodes.
It should behave the same as in shader node, with the exception
that it does not have an implicit position input yet. That will
be added separately.

Differential Revision: https://developer.blender.org/D12467

===================================================================

M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/functions/FN_multi_function_params.hh
M	source/blender/nodes/shader/nodes/node_shader_tex_noise.cc

===================================================================

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);
 }



More information about the Bf-blender-cvs mailing list