diff options
author | Charlie Jolly <charlie> | 2021-10-18 12:12:22 +0300 |
---|---|---|
committer | Charlie Jolly <mistajolly@gmail.com> | 2021-10-18 16:24:14 +0300 |
commit | 729b2d026d1379de92908b16e7492a509721c796 (patch) | |
tree | 7cd9396e59006f9bbd5135e6c4556df25040bae5 /source/blender/nodes/shader | |
parent | de6bf5d4d2f1f832f8305c519fc88d8896ea9a0b (diff) |
Geometry Nodes: Add shader Musgrave texture node
Port shader node musgrave texture
Differential Revision: https://developer.blender.org/D12701
Diffstat (limited to 'source/blender/nodes/shader')
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc | 410 |
1 files changed, 408 insertions, 2 deletions
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc index 23f150d8135..61c26d07e2f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc @@ -19,12 +19,14 @@ #include "../node_shader_util.h" +#include "BLI_noise.hh" + namespace blender::nodes { static void sh_node_tex_musgrave_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").hide_value(); + b.add_input<decl::Vector>("Vector").hide_value().implicit_field(); b.add_input<decl::Float>("W").min(-1000.0f).max(1000.0f); b.add_input<decl::Float>("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f); b.add_input<decl::Float>("Detail").min(0.0f).max(16.0f).default_value(2.0f); @@ -124,11 +126,414 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod node_sock_label(outFacSock, "Height"); } +namespace blender::nodes { + +class MusgraveFunction : public fn::MultiFunction { + private: + const int dimensions_; + const int musgrave_type_; + + public: + MusgraveFunction(const int dimensions, const int musgrave_type) + : dimensions_(dimensions), musgrave_type_(musgrave_type) + { + BLI_assert(dimensions >= 1 && dimensions <= 4); + BLI_assert(musgrave_type >= 0 && musgrave_type <= 4); + static std::array<fn::MFSignature, 20> signatures{ + create_signature(1, SHD_MUSGRAVE_MULTIFRACTAL), + create_signature(2, SHD_MUSGRAVE_MULTIFRACTAL), + create_signature(3, SHD_MUSGRAVE_MULTIFRACTAL), + create_signature(4, SHD_MUSGRAVE_MULTIFRACTAL), + + create_signature(1, SHD_MUSGRAVE_FBM), + create_signature(2, SHD_MUSGRAVE_FBM), + create_signature(3, SHD_MUSGRAVE_FBM), + create_signature(4, SHD_MUSGRAVE_FBM), + + create_signature(1, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + create_signature(2, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + create_signature(3, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + create_signature(4, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + + create_signature(1, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + create_signature(2, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + create_signature(3, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + create_signature(4, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + + create_signature(1, SHD_MUSGRAVE_HETERO_TERRAIN), + create_signature(2, SHD_MUSGRAVE_HETERO_TERRAIN), + create_signature(3, SHD_MUSGRAVE_HETERO_TERRAIN), + create_signature(4, SHD_MUSGRAVE_HETERO_TERRAIN), + }; + this->set_signature(&signatures[dimensions + musgrave_type * 4 - 1]); + } + + static fn::MFSignature create_signature(const int dimensions, const int musgrave_type) + { + fn::MFSignatureBuilder signature{"Musgrave"}; + + 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>("Dimension"); + signature.single_input<float>("Lacunarity"); + if (ELEM(musgrave_type, + SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, + SHD_MUSGRAVE_HYBRID_MULTIFRACTAL, + SHD_MUSGRAVE_HETERO_TERRAIN)) { + signature.single_input<float>("Offset"); + } + if (ELEM(musgrave_type, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL)) { + signature.single_input<float>("Gain"); + } + + signature.single_output<float>("Fac"); + + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + auto get_vector = [&](int param_index) -> const VArray<float3> & { + return params.readonly_single_input<float3>(param_index, "Vector"); + }; + auto get_w = [&](int param_index) -> const VArray<float> & { + return params.readonly_single_input<float>(param_index, "W"); + }; + auto get_scale = [&](int param_index) -> const VArray<float> & { + return params.readonly_single_input<float>(param_index, "Scale"); + }; + auto get_detail = [&](int param_index) -> const VArray<float> & { + return params.readonly_single_input<float>(param_index, "Detail"); + }; + auto get_dimension = [&](int param_index) -> const VArray<float> & { + return params.readonly_single_input<float>(param_index, "Dimension"); + }; + auto get_lacunarity = [&](int param_index) -> const VArray<float> & { + return params.readonly_single_input<float>(param_index, "Lacunarity"); + }; + auto get_offset = [&](int param_index) -> const VArray<float> & { + return params.readonly_single_input<float>(param_index, "Offset"); + }; + auto get_gain = [&](int param_index) -> const VArray<float> & { + return params.readonly_single_input<float>(param_index, "Gain"); + }; + + auto get_r_factor = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output_if_required<float>(param_index, "Fac"); + }; + + int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &detail = get_detail(param++); + const VArray<float> &dimension = get_dimension(param++); + const VArray<float> &lacunarity = get_lacunarity(param++); + + switch (musgrave_type_) { + case SHD_MUSGRAVE_MULTIFRACTAL: { + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_RIDGED_MULTIFRACTAL: { + const VArray<float> &offset = get_offset(param++); + const VArray<float> &gain = get_gain(param++); + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_HYBRID_MULTIFRACTAL: { + const VArray<float> &offset = get_offset(param++); + const VArray<float> &gain = get_gain(param++); + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_FBM: { + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_HETERO_TERRAIN: { + const VArray<float> &offset = get_offset(param++); + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + } + break; + } + } + } +}; // namespace blender::nodes + +static void sh_node_musgrave_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &node = builder.node(); + NodeTexMusgrave *tex = (NodeTexMusgrave *)node.storage; + builder.construct_and_set_matching_fn<MusgraveFunction>(tex->dimensions, tex->musgrave_type); +} + +} // namespace blender::nodes + void register_node_type_sh_tex_musgrave(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, 0); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, 0); ntype.declare = blender::nodes::sh_node_tex_musgrave_declare; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); node_type_init(&ntype, node_shader_init_tex_musgrave); @@ -136,6 +541,7 @@ void register_node_type_sh_tex_musgrave(void) &ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage); node_type_gpu(&ntype, node_shader_gpu_tex_musgrave); node_type_update(&ntype, node_shader_update_tex_musgrave); + ntype.build_multi_function = blender::nodes::sh_node_musgrave_build_multi_function; nodeRegisterType(&ntype); } |