From 425e706921a8f986921b8b9c429874fed98e9a10 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 21 Jan 2021 16:47:03 +0100 Subject: Geometry Nodes: new Attribute Sample Texture node This node allows sampling a texture for every vertex based on some mapping attribute. Typical attribute names are the name of a uv map (e.g. "UVMap") and "position". However, every attribute that can be converted to a vector implicitly is supported. It should be noted that as of right now, uv map attributes can only be accessed after a Point Distribute node. Ref T82584. Differential Revision: https://developer.blender.org/D10121 --- source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_geometry.h | 1 + source/blender/nodes/NOD_geometry_exec.hh | 2 + source/blender/nodes/NOD_static_types.h | 1 + .../nodes/node_geo_attribute_sample_texture.cc | 107 +++++++++++++++++++++ 5 files changed, 112 insertions(+) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc (limited to 'source/blender/nodes') diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 9057e4c6be8..d796c7c309c 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -146,6 +146,7 @@ set(SRC geometry/nodes/node_geo_attribute_fill.cc geometry/nodes/node_geo_attribute_math.cc geometry/nodes/node_geo_attribute_mix.cc + geometry/nodes/node_geo_attribute_sample_texture.cc geometry/nodes/node_geo_attribute_randomize.cc geometry/nodes/node_geo_attribute_vector_math.cc geometry/nodes/node_geo_boolean.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 523d0cfa24d..1b3a8200beb 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -47,6 +47,7 @@ void register_node_type_geo_attribute_mix(void); void register_node_type_geo_attribute_color_ramp(void); void register_node_type_geo_point_rotate(void); void register_node_type_geo_align_rotation_to_vector(void); +void register_node_type_geo_sample_texture(void); #ifdef __cplusplus } diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 3820c0f0009..454c9e96246 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -32,6 +32,8 @@ using bke::BooleanReadAttribute; using bke::BooleanWriteAttribute; using bke::Color4fReadAttribute; using bke::Color4fWriteAttribute; +using bke::Float2ReadAttribute; +using bke::Float2WriteAttribute; using bke::Float3ReadAttribute; using bke::Float3WriteAttribute; using bke::FloatReadAttribute; diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index e91b385a87e..4c300916357 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -289,6 +289,7 @@ DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_VECTOR_MATH, def_geo_attribute_vector_m DefNode(GeometryNode, GEO_NODE_ALIGN_ROTATION_TO_VECTOR, def_geo_align_rotation_to_vector, "ALIGN_ROTATION_TO_VECTOR", AlignRotationToVector, "Align Rotation to Vector", "") DefNode(GeometryNode, GEO_NODE_POINT_SCALE, def_geo_point_scale, "POINT_SCALE", PointScale, "Point Scale", "") DefNode(GeometryNode, GEO_NODE_POINT_TRANSLATE, def_geo_point_translate, "POINT_TRANSLATE", PointTranslate, "Point Translate", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE, def_geo_attribute_sample_texture, "ATTRIBUTE_SAMPLE_TEXTURE", AttributeSampleTexture, "Attribute Sample Texture", "") /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc new file mode 100644 index 00000000000..66495bfa53b --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc @@ -0,0 +1,107 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_compiler_attrs.h" + +#include "DNA_texture_types.h" + +#include "BKE_texture.h" + +#include "RE_texture.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_attribute_sample_texture_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Mapping")}, + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_sample_texture_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +namespace blender::nodes { + +static void execute_on_component(GeometryComponent &component, const GeoNodeExecParams ¶ms) +{ + const bNode &node = params.node(); + Tex *texture = reinterpret_cast(node.id); + const std::string result_attribute_name = params.get_input("Result"); + + if (texture == nullptr) { + return; + } + + const std::string mapping_name = params.get_input("Mapping"); + if (!component.attribute_exists(mapping_name)) { + return; + } + + OutputAttributePtr attribute_out = component.attribute_try_get_for_output( + result_attribute_name, ATTR_DOMAIN_POINT, CD_PROP_COLOR); + if (!attribute_out) { + return; + } + + Float3ReadAttribute mapping_attribute = component.attribute_get_for_read( + mapping_name, ATTR_DOMAIN_POINT, {0, 0, 0}); + + MutableSpan colors = attribute_out->get_span(); + for (const int i : IndexRange(mapping_attribute.size())) { + TexResult texture_result = {0}; + const float3 position = mapping_attribute[i]; + /* For legacy reasons we have to map [0, 1] to [-1, 1] to support uv mappings. */ + const float3 remapped_position = position * 2.0f - float3(1.0f); + BKE_texture_get_value(nullptr, texture, remapped_position, &texture_result, false); + colors[i] = {texture_result.tr, texture_result.tg, texture_result.tb, texture_result.ta}; + } + attribute_out.apply_span_and_save(); +} + +static void geo_node_attribute_sample_texture_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + + if (geometry_set.has()) { + execute_on_component(geometry_set.get_component_for_write(), params); + } + if (geometry_set.has()) { + execute_on_component(geometry_set.get_component_for_write(), params); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_sample_texture() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, + GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE, + "Attribute Sample Texture", + NODE_CLASS_ATTRIBUTE, + 0); + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + node_type_socket_templates( + &ntype, geo_node_attribute_sample_texture_in, geo_node_attribute_sample_texture_out); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_sample_texture_exec; + nodeRegisterType(&ntype); +} -- cgit v1.2.3