diff options
author | Charlie Jolly <charlie> | 2021-10-15 17:03:14 +0300 |
---|---|---|
committer | Charlie Jolly <mistajolly@gmail.com> | 2021-10-15 17:03:21 +0300 |
commit | d4f1bc5f39b219466978a1c9e74618ff8fa27433 (patch) | |
tree | 75bfa27b694e031b7e1d65cda8b689f58718eb94 /source/blender/nodes/shader | |
parent | 78b5050ff46646af748272bddd7a78506defab11 (diff) |
Geometry Nodes: Port shader gradient texture node
Reviewed By: HooglyBoogly, JacquesLucke
Differential Revision: https://developer.blender.org/D12717
Diffstat (limited to 'source/blender/nodes/shader')
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc | 111 |
1 files changed, 108 insertions, 3 deletions
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc index e0520ee49d3..4796af02361 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc @@ -23,7 +23,8 @@ namespace blender::nodes { static void sh_node_tex_gradient_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Vector>("Vector").hide_value(); + b.is_function_node(); + b.add_input<decl::Vector>("Vector").hide_value().implicit_field(); b.add_output<decl::Color>("Color").no_muted_links(); b.add_output<decl::Float>("Fac").no_muted_links(); }; @@ -55,17 +56,121 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_tex_gradient", in, out, GPU_constant(&gradient_type)); } -/* node type definition */ +namespace blender::nodes { + +class GradientFunction : public fn::MultiFunction { + private: + int gradient_type_; + + public: + GradientFunction(int gradient_type) : gradient_type_(gradient_type) + { + static fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"GradientFunction"}; + signature.single_input<float3>("Vector"); + signature.single_output<ColorGeometry4f>("Color"); + signature.single_output<float>("Fac"); + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + + MutableSpan<ColorGeometry4f> r_color = + params.uninitialized_single_output_if_required<ColorGeometry4f>(1, "Color"); + MutableSpan<float> fac = params.uninitialized_single_output<float>(2, "Fac"); + + const bool compute_color = !r_color.is_empty(); + + switch (gradient_type_) { + case SHD_BLEND_LINEAR: { + for (int64_t i : mask) { + fac[i] = vector[i].x; + } + break; + } + case SHD_BLEND_QUADRATIC: { + for (int64_t i : mask) { + const float r = std::max(vector[i].x, 0.0f); + fac[i] = r * r; + } + break; + } + case SHD_BLEND_EASING: { + for (int64_t i : mask) { + const float r = std::min(std::max(vector[i].x, 0.0f), 1.0f); + const float t = r * r; + fac[i] = (3.0f * t - 2.0f * t * r); + } + break; + } + case SHD_BLEND_DIAGONAL: { + for (int64_t i : mask) { + fac[i] = (vector[i].x + vector[i].y) * 0.5f; + } + break; + } + case SHD_BLEND_RADIAL: { + for (int64_t i : mask) { + fac[i] = atan2f(vector[i].y, vector[i].x) / (M_PI * 2.0f) + 0.5f; + } + break; + } + case SHD_BLEND_QUADRATIC_SPHERE: { + for (int64_t i : mask) { + /* Bias a little bit for the case where input is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + const float r = std::max(0.999999f - vector[i].length(), 0.0f); + fac[i] = r * r; + } + break; + } + case SHD_BLEND_SPHERICAL: { + for (int64_t i : mask) { + /* Bias a little bit for the case where input is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + fac[i] = std::max(0.999999f - vector[i].length(), 0.0f); + } + break; + } + } + if (compute_color) { + for (int64_t i : mask) { + r_color[i] = ColorGeometry4f(fac[i], fac[i], fac[i], 1.0f); + } + } + } +}; + +static void sh_node_gradient_tex_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &node = builder.node(); + NodeTexGradient *tex = (NodeTexGradient *)node.storage; + builder.construct_and_set_matching_fn<GradientFunction>(tex->gradient_type); +} + +} // namespace blender::nodes + void register_node_type_sh_tex_gradient(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, 0); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, 0); ntype.declare = blender::nodes::sh_node_tex_gradient_declare; node_type_init(&ntype, node_shader_init_tex_gradient); node_type_storage( &ntype, "NodeTexGradient", node_free_standard_storage, node_copy_standard_storage); node_type_gpu(&ntype, node_shader_gpu_tex_gradient); + ntype.build_multi_function = blender::nodes::sh_node_gradient_tex_build_multi_function; nodeRegisterType(&ntype); } |