Shape Attributes
Sets per-vertex and per-path attributes on shape data, either from a spatial field or a uniform value. Enables per-path coloring, opacity, and stroke width in DrawShape.
Category: Shape Ops Menu path: Shape Ops > Shape Attributes
Ports
| Port | Type | Direction | Description |
|---|---|---|---|
shape_in | shape | input | Source shape |
field_in | scalarField | input | Spatial field to sample at each vertex (also accepts vectorField and colorField) |
out | shape | output | Shape with attributes set |
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
target | enum | Color | Which attribute to write: Color, StrokeWidth, Opacity, Rotation, Index, or Custom |
source | enum | Field | Field (use field_in or uniform value), Value (always uniform), Tangent (Rotation only — use per-vertex tangent), Index (sample the ramp by per-path normalized index), Random (sample the ramp at a fixed random value per path) |
value | scalar | 1.0 | Uniform value (used when source is Field with no connection, or source is Value) |
colorValue | color | white | Color value (used when target is Color and source is Field/Value) |
customAttribute | string | custom | Attribute key name (used when target is Custom) |
tangentOffset | scalar | 0 | Degrees added to the computed tangent (only when target=Rotation, source=Tangent) |
indexCurve | CurveRamp | 0→1 linear | Ramp sources (Index / Random) + scalar target: the curve is sampled at t and its value written. Shown as the Curve widget in the Output section |
indexColorRamp | GradientRamp | black→white | Ramp sources + Color target: the gradient is sampled at t. Shown as the Color Ramp widget in the Output section |
groupAttribute | string | (empty) | Source=Index only. Optional path attribute name. When set, paths sharing the same value form a group and share the sampled value — essential for text workflows (use glyphIndex) so multi-contour glyphs stay consistent. |
indexCycle | scalar, keyframeable | 0 | Offsets t before the repeat mode — animate it to scroll the ramp across the paths |
indexRepeatMode | enum | Clamp | What happens outside 0–1 after cycling: Clamp, Repeat, Mirror |
randomSeed | scalar | 0 | Source=Random. Changes which fixed random value each path gets |
outputMin | scalar | 0 | Lerp the [0,1] ramp / field output into [outputMin, outputMax]. Hidden for Color target and for source=Tangent or source=Value. Default 0/1 is identity |
outputMax | scalar | 1 | See outputMin |
applyRotation | boolean | false | Rotation target only. Off (default): write the rotation attribute for downstream consumers (ShapeToPoints → DrawPoints / CloneToPoints, tangent orientation). On: bake the rotation into the shape geometry — each path rotates around its own centre, and paths sharing a glyphIndex (text glyph counters like "o"/"a") rotate together as one unit. Angle is in radians (drive a field through Output Min/Max, or a value / Math node). |
How It Works
ShapeAttributes evaluates per vertex. For each vertex in the input shape:
- If a field is connected to
field_in, it is sampled at the vertex's position (origin-centered comp-pixel coordinates). - If no field is connected, the
valueorcolorValueparam is used uniformly for all vertices.
Attributes are written at two levels:
- Per-vertex (
shape.points.attributes) -- used by DrawShape's per-vertex color pipeline for smooth GPU-interpolated gradients across triangles. - Per-path (
path.attributes, using the first vertex's value) -- used by DrawShape's grouped rendering for per-path color, opacity, and stroke width.
| Target | Attribute key | Effect in DrawShape |
|---|---|---|
| Color | color | Per-vertex: smooth GPU-interpolated gradients. Per-path: uniform path color. |
| StrokeWidth | strokeWidth | Multiplier on DrawShape's strokeWidth param per path |
| Opacity | opacity | Per-path alpha multiplier |
| Index | index | Variant selection downstream: CloneToPoints / DrawInstances "Point Index" selection reads shapeIndex falling back to index (route through ShapeToPoints to reach a points input); also DrawInstances' default offsetAttribute for time offsets |
| Custom | user-defined | Available for custom pipelines (consumer nodes decide what to do) |
Custom target output type: The Custom target follows the field type of the connected input:
- ColorField -> Vec4 per vertex (and per path, from first vertex)
- VectorField (alone) -> Vec2 per vertex (bipolar [-1,1])
- ScalarField or uniform value -> Scalar per vertex
This mirrors PointAttributes' Custom target, so the same convention applies across points and shape vertices.
DrawShape rendering priority: When per-vertex color attributes are present, DrawShape automatically uses its DrawShapeVertexColor pipeline for smooth gradient fills. When only per-path attributes exist, it uses grouped rendering (one draw call per unique color/opacity/strokeWidth group). When neither is set, it uses a single uniform-color draw call.
Usage Examples
Basic: Gradient-colored shape
Rectangle -> SubdivideShape (gridSize: 10) -> ShapeAttributes (target: Color, field: Gradient.colorField) -> DrawShape. The rectangle fills with a smooth color gradient interpolated across its subdivided mesh.
Per-path stroke width
Grid -> CloneToPoints (shape: Circle) -> ShapeAttributes (target: StrokeWidth, field: Noise.scalarField) -> DrawShape. Each cloned circle gets a different stroke width based on its position in the noise field.
Opacity fade
EditableShape -> ShapeAttributes (target: Opacity, field: DistanceField.scalarField) -> DrawShape. Parts of the shape closer to another shape fade out.
Per-letter text coloring (Index source + glyphIndex grouping)
Text("HELLO") -> TextToShape -> ShapeAttributes (target: Color, source: Index, groupAttribute: "glyphIndex", indexColorRamp: red->blue) -> DrawShape. Each letter gets a distinct color sampled along the ramp; multi-contour glyphs like "O" keep their outer and inner paths the same color thanks to glyphIndex grouping.
Per-path progressive stroke width
A shape with N paths -> ShapeAttributes (target: StrokeWidth, source: Index, indexCurve: 0 -> 2). The first path has strokeWidth multiplier 0, the last has 2, linearly.
Random colour per instance (Random source)
PointSolver -> CloneToPoints (shape: Circle) -> ShapeAttributes (target: Color, source: Random, Color Ramp: a palette with Step interpolation) -> DrawShape. Every cloned circle picks one palette entry and keeps it for its whole life — the value is a hash of the path's identity, not of where it sits, so it does not flicker as the particle moves. randomSeed reshuffles the picks.
Rotate each letter from a field (Plain-Effector style)
Text("HELLO") -> TextToShape -> ShapeAttributes (target: Rotation, source: Field, field: Gradient.scalarField, Output Min/Max: 0 / 6.28, Rotate Geometry: on) -> DrawShape. Each letter rotates by the field value sampled at its centre; multi-contour glyphs like "O" rotate as one unit (outer + counter together) because paths are grouped by glyphIndex. Turn Rotate Geometry off to instead export the angle as a rotation attribute (e.g. for ShapeToPoints → CloneToPoints orientation).
Tips
- For smooth color gradients, the shape needs interior vertices -- use SubdivideShape upstream to create a mesh with enough resolution for the gradient
- StrokeWidth is a multiplier on DrawShape's
strokeWidthparam, not an absolute value -- a value of 2.0 doubles the base stroke width - ShapeAttributes only writes attribute data and does not change vertex positions -- except when target=Rotation with Rotate Geometry on, which bakes the rotation into the geometry (grouped by
glyphIndex). For other position changes use ShapeDeform. - You can chain multiple ShapeAttributes nodes for different targets (e.g., one for Color, another for StrokeWidth)
- Properties: the literal value rows show for Field / Value / Tangent; the Curve or Color Ramp plus Cycle / Repeat show for Index and Random; Group By is Index-only and Seed is Random-only
- Random here is per path, fixed for the path's life. For per-vertex randomness that changes with position, sample a Random field instead
Related Nodes
- PointAttributes -- same concept for points instead of shape vertices, with Age / Speed sources for particles
- SubdivideShape -- create interior mesh vertices for smooth per-vertex gradients
- DrawShape -- reads color, strokeWidth, and opacity attributes
- CloneToPoints -- creates multi-path shapes ideal for per-path attributes
- Gradient -- colorField source for spatial color mapping
- DistanceField -- scalarField source for proximity-based attributes