Aller au contenu

Custom Vertex 3D Node

By Kriss Norde

The most advanced node in the 3D category: manipulate every vertex of a mesh with math expressions (position, normals, UVs, colors, velocity). Ideal for creating waves, flags, spirals or any procedural effect.

Overview

Custom Vertex 3D applies a math expression to every vertex of an input mesh. Unlike Bender 3D (which applies a predefined deformation) or Displace 3D (which uses an image), here you write the formula yourself - typically a sin(), a cos(), a combination of coordinates or a lookup table access.

The node is designed for users who are comfortable with fuse / script style expressions. It borrows concepts from the "deformation shader" nodes you find in Nuke or Houdini.

Prerequisite: the input mesh must be subdivided enough. A Shape 3D plane with 2 subdivisions will only give a rough wave; go up to 30-50 for a smooth result.

Where to find this node

  • Effects Library: Tools > 3D > Custom Vertex 3D
  • Quick add: right-click in the Node Editor → Add Tool > 3D > Custom Vertex 3D

Inputs

  • SceneInput (orange) - required. Accepts any 3D geometry or scene whose vertices will be manipulated.
  • ImageInput1 (green) - optional 2D image, available in expressions to sample RGB values by UV coordinate.
  • ImageInput2 (magenta) - optional second image, useful for example to combine a heightmap and a mask.
  • ImageInput3 (teal) - third image for multi-channel workflows.

Setup

Insert Custom Vertex 3D between your mesh and the Merge 3D. Expressions must return a number (float) - they can use the coordinates of the current vertex (px, py, pz), the normals (nx, ny, nz), time (time) and the animated variables n1-n8.

Vertex tab

This is the core tab: one expression field per vertex attribute. All calculations happen in world space.

Position (px, py, pz)
Vertex coordinates. Example: py + sin(px * 2 + time) * 0.1 applies a wave on the Y axis based on the X coordinate.
Normals (nx, ny, nz)
Normal direction. Change them if you move the geometry so the lighting stays consistent.
Vertex Color (vcr, vcg, vcb, vca)
Per-vertex color. Useful to procedurally color a mesh based on its height or its distance to a point.
Texture Coordinates (tu, tv, tw)
Current UVs of the vertex. Rewriting them lets you distort a texture applied downstream.
Environment Coordinates (eu, ev, ew)
Coordinates used for environment mapping (reflection / refraction).
UV Tangents & Velocity
Tangents for normal mapping and the velocity vector for motion blur. Only change them if you need a precise correction.

Numbers & Points Tabs

Eight number sliders n1-n8 and eight animatable 3D points p1-p8, available in every expression.

  • n1, n2, … current value at the frame.
  • n1_at(t), n2_at(t), … value at an arbitrary frame t (useful for trail effects).
  • p1x, p1y, p1z, … components of point p1. Same with _at(t).

Rename these controls in the Config tab to keep the Inspector readable - n1 becomes, for example, Wave Amplitude.

LUT tab

Four editable splines lut1-lut4. Accessible through getlut1(x), getlut2(x), … where x is between 0 and 1.

Example: to color a vertex based on its normalized height, vcr = getlut1((py + 1) / 2) samples LUT1 using the vertex Y position mapped from -1..1 to 0..1. It is the equivalent of a color curve applied per vertex.

Setup & Intermediate Tabs

These two tabs save you from recomputing the same values in every expression of the Vertex tab.

Setup (s1-s8, once per frame)
Expressions evaluated only once per frame, before any per-vertex operation. Perfect for computing a matrix, a center of gravity or a local time. Results are stored in s1-s8.
Intermediate (i1-i8, once per vertex)
Expressions evaluated once per vertex, after Setup but before the Vertex tab expressions. Useful to precompute a factor shared by several components (for example a distance to the center reused in px/py/pz).

Config tab

Random Seed
Seed used by rand() and rands(). Click Reseed to pick a new random seed.
Number / Point Controls
Checkboxes to show or hide each of the eight sliders n1-n8 and the eight points p1-p8. Rename fields next to them let you name each control.

Practical examples

1. Wave on a plane

Start from a Shape 3D plane with Subdivision X = 40, Subdivision Y = 40. In the Vertex tab, on py:

py + sin(px * 5 + time * 2) * n1

n1 drives the amplitude, and time rolls the wave automatically.

2. Animated flag

Same plane, but a 2D wave that fades out toward the pole (X axis = 0):

py + sin(px * 3 + time * 4) * cos(pz * 2) * px * 0.2

3. Spiral

On a subdivided plane or cylinder:

px = px * cos(py * n1) - pz * sin(py * n1)
pz = px * sin(py * n1) + pz * cos(py * n1)

Twist the geometry around the Y axis based on its height (n1 = twist strength).

4. Coloring by height

With LUT1 set to a blue→white gradient, then in the Vertex tab:

vcr = getlut1(py * 0.5 + 0.5)

High vertices turn white, low ones blue - useful for a procedural "snowy terrain".

Tips & best practices

  • Always work on a mesh that is subdivided enough - the quality of the effect depends directly on the number of vertices.
  • Use the Setup tab for any global calculation: a significant performance gain on dense scenes.
  • Rename your n1-n8 controls as soon as you have decided what they do - it saves you the "what was n3 again?" moment two weeks later.
  • If you deform the geometry heavily, change the normals too so the lighting follows. A wave with frozen normals will look "flat" under any light.
  • This node is CPU-bound: on a large scene, prefer a Bender 3D or a Displace 3D if the effect can be done with them.