No 'Attribute Expand' in Houdini? 4 Ways to Grow Attributes Across Topology
01 Sep 26 (9d ago)
If you spend a lot of time manipulating geometry in SideFX Houdini, you are likely familiar with the Group Expand SOP for stepping selections across adjacent topology. But the moment you look for an Attribute Expand SOP to do the exact same thing with a point attribute or mask, you hit a wall: it doesn't exist natively.
Because Houdini handles attribute data and topological connectivity independently, you don't actually need a dedicated node. Depending on whether you need a smooth gradient falloff, a discrete topological step, or an animated growth loop, here are the four cleanest ways to expand attributes in Houdini.
1. The Attribute Blur Method (Best for Gradients & Soft Spreads)
When dealing with float attributes (like @mask, @weight, or @Cd) that need to bleed smoothly into surrounding geometry, the Attribute Blur SOP is the cleanest approach.
- Setup: Drop an Attribute Blur SOP and set Attributes to your target attribute (e.g.,
mask). - Execution: Increase Blurring Steps and adjust Blur Method (e.g., Proximity or Edge Length). As the blur steps increase, the attribute diffuses outward along connected mesh edges.
- Hard Mask Threshold: If you need a solid expanded boundary rather than a soft blur falloff, append a Point Wrangle SOP directly downstream:
// Snap any diffused values back to full mask strength
if (@mask > 0.001) {
@mask = 1.0;
}
2. The Native VEX Method (neighbour / neighbours)
If you want a lightweight, pure-VEX solution without relying on blur math or multiple node conversions, you can check the maximum value of adjacent connected points directly in a single Point Wrangle SOP.
// Run over: Points
// Finds the highest value among connected neighbors along edge topology
float max_val = @mask;
int connected_pts[] = neighbours(0, @ptnum);
foreach (int p; connected_pts) {
float neighbor_val = point(0, "mask", p);
if (neighbor_val > max_val) {
max_val = neighbor_val;
}
}
@mask = max_val;
Tip: Stacking this wrangle or putting it in a loop will step the attribute outward by exactly one edge ring per iteration.
3. The Group Conversion Bridge (Best for Hard Integer/Boolean Masks)
If you specifically want the exact geometric calculation performed by the Group Expand SOP—complete with stepped edge rings, boundary limits, and disconnected piece isolation—simply round-trip the data through a group.
- Convert to Group: Drop a Group Expression SOP or a Point Wrangle SOP:
// Creates a temporary group from your attribute condition
if (@mask > 0.5) {
setpointgroup(0, "expand_target", @ptnum, 1);
}
- Expand: Drop a Group Expand SOP. Set the group to
expand_targetand tune the Step Count to your desired edge distance. - Convert back to Attribute: Drop an Attribute Wrangle SOP to push the group membership back into your attribute data:
@mask = inpointgroup(0, "expand_target", @ptnum) ? 1.0 : 0.0;
4. The Solver SOP Loop (Best for Frame-by-Frame Growth)
If you are setting up dynamic procedural propagation (like an infection spread, dissolving edge, or a procedural rigging mask spreading across a deforming mesh over time), run the expansion inside a Solver SOP.
Inside the Solver SOP network:
- Connect the
Prev_Frameinput to an Attribute Promote SOP. - Promote your attribute from Point to Primitive, setting the Promotion Method to Maximum.
- Chain a second Attribute Promote SOP immediately after, promoting it back from Primitive to Point (again using Maximum).
- Connect the result to the solver output.
Because adjacent primitives share points across shared edges, promoting back and forth naturally propagates the highest attribute value outwards to all touching vertices by exactly one polygon ring per frame.