forked from bartvdbraak/blender
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
This commit is contained in:
parent
a92ebab5da
commit
425e706921
@ -489,6 +489,7 @@ geometry_node_categories = [
|
||||
NodeItem("GeometryNodeAttributeMix"),
|
||||
NodeItem("GeometryNodeAttributeColorRamp"),
|
||||
NodeItem("GeometryNodeAttributeVectorMath"),
|
||||
NodeItem("GeometryNodeAttributeSampleTexture"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_COLOR", "Color", items=[
|
||||
NodeItem("ShaderNodeValToRGB"),
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "BKE_attribute.h"
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_float2.hh"
|
||||
#include "BLI_float3.hh"
|
||||
|
||||
namespace blender::bke {
|
||||
@ -301,11 +302,13 @@ template<typename T> class TypedWriteAttribute {
|
||||
|
||||
using BooleanReadAttribute = TypedReadAttribute<bool>;
|
||||
using FloatReadAttribute = TypedReadAttribute<float>;
|
||||
using Float2ReadAttribute = TypedReadAttribute<float2>;
|
||||
using Float3ReadAttribute = TypedReadAttribute<float3>;
|
||||
using Int32ReadAttribute = TypedReadAttribute<int>;
|
||||
using Color4fReadAttribute = TypedReadAttribute<Color4f>;
|
||||
using BooleanWriteAttribute = TypedWriteAttribute<bool>;
|
||||
using FloatWriteAttribute = TypedWriteAttribute<float>;
|
||||
using Float2WriteAttribute = TypedWriteAttribute<float2>;
|
||||
using Float3WriteAttribute = TypedWriteAttribute<float3>;
|
||||
using Int32WriteAttribute = TypedWriteAttribute<int>;
|
||||
using Color4fWriteAttribute = TypedWriteAttribute<Color4f>;
|
||||
|
@ -1361,6 +1361,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
||||
#define GEO_NODE_ALIGN_ROTATION_TO_VECTOR 1018
|
||||
#define GEO_NODE_POINT_TRANSLATE 1019
|
||||
#define GEO_NODE_POINT_SCALE 1020
|
||||
#define GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE 1021
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -4747,6 +4747,7 @@ static void registerGeometryNodes(void)
|
||||
register_node_type_geo_attribute_color_ramp();
|
||||
register_node_type_geo_point_rotate();
|
||||
register_node_type_geo_align_rotation_to_vector();
|
||||
register_node_type_geo_sample_texture();
|
||||
}
|
||||
|
||||
static void registerFunctionNodes(void)
|
||||
|
@ -3289,6 +3289,13 @@ static void node_geometry_buts_object_info(uiLayout *layout, bContext *UNUSED(C)
|
||||
uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_geometry_buts_attribute_sample_texture(uiLayout *layout,
|
||||
bContext *C,
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
uiTemplateID(layout, C, ptr, "texture", "texture.new", NULL, NULL, 0, ICON_NONE, NULL);
|
||||
}
|
||||
|
||||
static void node_geometry_set_butfunc(bNodeType *ntype)
|
||||
{
|
||||
switch (ntype->type) {
|
||||
@ -3343,6 +3350,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype)
|
||||
case GEO_NODE_OBJECT_INFO:
|
||||
ntype->draw_buttons = node_geometry_buts_object_info;
|
||||
break;
|
||||
case GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE:
|
||||
ntype->draw_buttons = node_geometry_buts_attribute_sample_texture;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8862,6 +8862,19 @@ static void def_geo_point_translate(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static void def_geo_attribute_sample_texture(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "id");
|
||||
RNA_def_property_struct_type(prop, "Texture");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Texture", "Texture to sample values from");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations");
|
||||
}
|
||||
|
||||
static void def_geo_object_info(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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<Tex *>(node.id);
|
||||
const std::string result_attribute_name = params.get_input<std::string>("Result");
|
||||
|
||||
if (texture == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string mapping_name = params.get_input<std::string>("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<float3>(
|
||||
mapping_name, ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
MutableSpan<Color4f> colors = attribute_out->get_span<Color4f>();
|
||||
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<GeometrySet>("Geometry");
|
||||
|
||||
if (geometry_set.has<MeshComponent>()) {
|
||||
execute_on_component(geometry_set.get_component_for_write<MeshComponent>(), params);
|
||||
}
|
||||
if (geometry_set.has<PointCloudComponent>()) {
|
||||
execute_on_component(geometry_set.get_component_for_write<PointCloudComponent>(), 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user