VIDEOMONTAZHERDAVINCI RESOLVE · VIDEO · AI

FUSION · NODE REFERENCE

CustomVertex3D

Programmable per-vertex processing with image lookups and staged expressions

CustomVertex3D programs scene3d vertex attributes—Position, normals, vertex color, UVW, tangents and velocity—using three optional image inputs, user controls, LUTs and staged Setup/Intermediate expressions.

Fusion 3DAdvanced

CustomVertex3D

Overview

What CustomVertex3D does

Resolve 21 describes CustomVertex3D as an advanced custom node for per-vertex manipulation. It can modify Position, normals, vertex color, texture coordinates, environment coordinates, UV tangents and velocity. Unlike Transform3D, it executes rules on vertex attributes rather than merely transforming the whole object.

The node has four inputs. Orange SceneInput is required and accepts classic scene3d. ImageInput1, ImageInput2 and ImageInput3 are optional 2D image inputs available to the expression system for image lookup. The old one-input description was incomplete.

Position defaults to px/py/pz. Crucially, changing vertex Position does not recompute normals or tangents. Blackmagic explicitly recommends a downstream ReplaceNormals node when a deformed surface needs a rebuilt shading basis.

Not every geometry source carries every attribute. Resolve 21 notes that normal Fusion geometry often lacks vertex color, while particles and some imported FBX/Alembic meshes may provide it; environment coordinates are normally absent; velocity is characteristic of particles. Missing streams use documented defaults.

Documented defaults are tangentU=(1,0,0), tangentV=(0,1,0), normal=(0,0,1), vertexColor=(1,1,1,1), velocity=(0,0,0), envcoord=(0,0,0), and texcoord=(0,0,0). A non-trivial expression can create a missing attribute stream from that default baseline.

Numbers 1–8 are animatable variables n1…n8 and the current reference also documents n#_at(t). Points 1–8 expose p#x/p#y/p#z plus time-sampled forms. These Points are node controls, not vertices from the source mesh.

LUTs 1–4 provide four lookup splines, getlut1(x)…getlut4(x), for nonlinear remapping. The manual contains a legacy line mentioning lut1…lut8, but both the Inspector and documented functions expose four LUTs, so this article does not invent LUT 5–8.

Setup and Intermediate have different evaluation scopes. Setup runs once per frame; Intermediate runs once per vertex. Resolve 21 is internally inconsistent here: the heading says Setups 1–8, but the result-variable sentence lists only s1…s4, while Intermediate explicitly lists i1…i8. Do not promise s5…s8 without a live target-build check.

Image inputs can be sampled from expressions with normalized image coordinates: (0.5, 0.5) is the image center. Fusion documents get[ch][#]b/d/w families: b returns 0 out of bounds, d uses the edge pixel, and w wraps; the number selects image 1, 2 or 3. Therefore getr1d(tu,tv) is meaningful only when the source UVs are in the expected 0…1 space.

Fusion expression math has another important rule: sin/cos/tan use degrees, so sin(90)=1; formulas copied from radian-based languages need conversion. The current Inspector capture also exposes Apply in Source Coordinates, whose exact target-build behavior remains a live Resolve 21/21.1 A/B item rather than something inferred from its label.

CustomVertex3D output remains scene3d. Connecting images or modifying vertex color never turns the node into an RGBA image; Renderer3D is still required before MediaOut and normal 2D effects.

Bundled captures verify the Vertex, Numbers, Points, LUTs, Setup, Intermediate and Config tabs. Core semantics were cross-checked against the Resolve 21 reference; live Resolve 21/21.1 execution was not run for this package, so target-build edge cases remain pending.

Mesh density is part of the algorithm. CustomVertex3D moves existing vertices and does not create topology, so the same expression on a 10×10 plane and a 200×200 plane produces radically different geometric detail.

For wave/displacement work, debug the formula first in wireframe or with a simple matte material. A polished shader can hide insufficient subdivisions, stale normals, or an overly sharp derivative.

Image lookup and material texturing are separate roles. ImageInput1–3 are numerical sample sources for the expression system; they are not assigned to the object as materials and do not appear in the render by themselves.

Indexed getr/getg/getb/geta functions sample pixels in normalized image coordinates. If the source geometry lacks useful UVs, an expression using tu/tv may repeatedly sample one point or the documented default texcoord (0,0,0).

The lookup boundary suffix matters at UV edges: b returns black/zero out of bounds, d holds the edge pixel, and w wraps coordinates. This can completely change a seam with the same texture.

Treat Numbers and Points as the public API of a procedural rig. Complex math stays inside expressions while the artist sees amplitude, frequency, center, radius, and other meaningful controls.

Time-sampled n#_at(t) and point variants can read a control at another time. They enable temporal procedural logic but can also make expressions expensive and harder to diagnose.

LUT 1–4 work well as artist-friendly transfer functions: a distance or sampled texture can become a falloff, threshold-like response, or easing curve without a long chain of conditional math.

Keep Setup independent of the current vertex. If the expression needs px, py, pz, normals, or UVs from a specific vertex, that calculation belongs in Intermediate/Vertex rather than Setup.

Intermediate reduces duplicated per-vertex math. A radius can be computed once and then reused by Position, Vertex Color, and other attributes.

Writing Vertex Color does not guarantee that the renderer/material will display it. Confirm the downstream shader path actually reads the vertex-color stream.

Environment coordinates are usually absent from classic Fusion geometry. The existence of eu/ev/ew names in the expression language does not prove that a given mesh carries meaningful envcoord data.

Velocity streams are primarily associated with particles. Writing vx/vy/vz on ordinary geometry can create a stream, but its usefulness depends on a downstream tool that consumes it.

Tangent U/V only make sense together with consistent UVs, normals, and the intended material workflow. Arbitrary tangent edits can break normal/bump shading even when the geometry shape looks correct.

Random Seed and Reseed only matter when an expression actually uses a seed-dependent random/noise mechanism. Reseeding need not change a deterministic expression with no random component.

Config controls decide which Numbers, Points, Images, and LUTs are exposed and how they are named. This is control packaging, not an additional vertex-processing pass.

For a production template, first make the rig work with technical n1/p1/getlut1 names, then expose only the controls that matter and rename them for the artist.

CustomVertex3D can become expensive on dense geometry because Intermediate and Vertex expressions execute for every vertex. Cost rises with vertex count, formula complexity, and image lookups.

Profile before optimizing. Reducing mesh density where acceptable, moving frame-global work into Setup, and reusing Intermediate values are usually more meaningful than merely shortening expression text.

Final QC should happen through Renderer3D with the real material and lighting, not only in the 3D Viewer. Normal, tangent, and attribute-stream errors often appear only during shading.

When to use it

  • Procedural waves and deformation on dense meshes

  • Image-driven vertex displacement through ImageInput1–3

  • Custom Point + LUT falloff rigs

  • Procedural UV remapping and texture-coordinate animation

  • Technical normal/tangent/vertex-color manipulation

  • Particle/velocity attribute experiments

  • Reusable artist controls built from Numbers/Points/Config