Skip to content

Procedural Geometries

This page documents procedural geometry generators in three.js, focusing on ExtrudeGeometry, TextGeometry, and parametric surface generators. These classes create 3D geometries at runtime from 2D shapes, mathematical functions, or 3D curves without requiring external model files.

Procedural generators differ from primitive geometries (box, sphere, cylinder) which are covered in Geometry System. For loading pre-made 3D models, see GLTF Import & Export and Additional Format Loaders. For serializing procedural geometries, see Scene Serialization.

Overview

Procedural geometry generators create complex 3D shapes from parametric descriptions:

  1. Shape-based generators: ExtrudeGeometry, TextGeometry, ShapeGeometry - convert 2D shapes to 3D meshes
  2. Parametric generators: ParametricGeometry, TubeGeometry, LatheGeometry - evaluate mathematical functions to create surfaces
  3. Base infrastructure: Shape, Path, Curve classes define 2D contours for extrusion

All procedural geometries extend BufferGeometry and populate position, normal, and uv attributes programmatically. The primary workflow is: define 2D shape → configure extrusion/generation parameters → generate BufferGeometry.

Shape and Path System

The foundation for procedural geometry is the 2D shape system, which defines contours and holes using curves and paths.

SVG
100%

Class Hierarchy for 2D Shape Definition

Curve

Base class providing interpolation methods. Key methods:

  • getPoint(t): Returns a vector for parameter t ∈ [0,1]
  • getPoints(divisions): Returns array of points using getPoint()
  • getSpacedPoints(divisions): Returns equi-spaced points using arc length
  • computeFrenetFrames(segments, closed): Computes tangent, normal, binormal frames (used for path extrusion)

Path

Extends CurvePath to provide a drawing API similar to HTML5 Canvas 2D:

  • moveTo(x, y): Sets drawing offset
  • lineTo(x, y): Adds line segment
  • quadraticCurveTo(cpX, cpY, x, y): Adds quadratic Bézier curve
  • bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, x, y): Adds cubic Bézier curve
  • arc(x, y, radius, startAngle, endAngle, clockwise): Adds circular arc
  • ellipse(x, y, xRadius, yRadius, startAngle, endAngle, clockwise): Adds elliptical arc

Shape

Extends Path to add hole support:

  • holes: Array of Path objects representing interior holes
  • extractPoints(divisions): Returns {shape: Vector2[], holes: Vector2[][]} with tessellated points

ExtrudeGeometry

ExtrudeGeometry converts 2D shapes into 3D geometry by extruding along the Z-axis or along a custom 3D path. It supports beveling edges for smooth transitions.

Constructor and Options

// Signature
new ExtrudeGeometry(shapes, options)

Options Object (ExtrudeGeometry~Options):

PropertyTypeDefaultDescription
curveSegmentsnumber12Number of points on curves
stepsnumber1Number of subdivisions along extrusion depth
depthnumber1Depth to extrude the shape
bevelEnabledbooleantrueEnable beveling
bevelThicknessnumber0.2Depth of bevel into shape
bevelSizenumberbevelThickness - 0.1Distance bevel extends from outline
bevelOffsetnumber0Distance from outline where bevel starts
bevelSegmentsnumber3Number of bevel layers
extrudePathCurvenull3D spline path for extrusion (disables bevels)
UVGeneratorObjectWorldUVGeneratorCustom UV generation functions

Extrusion Pipeline

SVG
100%

ExtrudeGeometry Processing Flow

Key Algorithms

Bevel Vector Calculation

The getBevelVec() function src/geometries/ExtrudeGeometry.js236-357 calculates offset vectors for beveling:

  1. For each contour vertex, find previous and next vertices
  2. Compute normalized edge vectors
  3. Check if edges are collinear (cross product ≈ 0)
  4. If not collinear: compute line-line intersection of offset parallel edges
  5. If collinear: use perpendicular offset (straight or spike case)
  6. Clamp offset magnitude to prevent excessive spikes (max length √2)

This produces smooth bevels at corners by offsetting vertices perpendicular to the average edge direction.

Overlapping Point Removal

mergeOverlappingPoints() src/geometries/ExtrudeGeometry.js170-202 removes adjacent vertices closer than a scaled threshold:

THRESHOLD_SQ = 1e-10 * max(|x|, |y|)²

This prevents degenerate triangles from floating-point precision issues.

Triangulation

Uses ShapeUtils.triangulateShape(contour, holes) src/geometries/ExtrudeGeometry.js402-453 to generate face indices. When beveling is enabled, uses contracted contour vertices and expanded hole vertices to create proper cap geometry.

Path Extrusion

When extrudePath is specified src/geometries/ExtrudeGeometry.js106-125:

  1. Sample points along path using getSpacedPoints(steps)
  2. Compute Frenet frames (tangent, normal, binormal) using computeFrenetFrames(steps, isClosed)
  3. For each shape vertex, transform by frame to position along path
  4. Bevels are disabled (incompatible with arbitrary paths)

The shape is swept along the 3D curve, maintaining orientation using the Frenet frame.

UV Generation

WorldUVGenerator src/geometries/ExtrudeGeometry.js808-864 provides default UV mapping:

  • Top UV (generateTopUV): Uses X,Y coordinates of vertices in world space
  • Side wall UV (generateSideWallUV): Uses X or Y (whichever varies more) and 1-Z for vertical mapping

Custom UV generators can be provided via the UVGenerator option.

Vertex and Face Construction

The geometry is built in layers src/geometries/ExtrudeGeometry.js460-560:

  1. Back face vertices (z = 0 or at start of extrudePath)
  2. Intermediate vertices for each step (z = depth * step / steps)
  3. Front face vertices (z = depth or at end of extrudePath)
  4. Bevel vertices at front and back (if enabled)

Faces are added using helper functions:

Sources: src/geometries/ExtrudeGeometry.js460-560 src/geometries/ExtrudeGeometry.js574-683 src/geometries/ExtrudeGeometry.js694-747

TextGeometry

TextGeometry extends ExtrudeGeometry to create 3D text from font data editor/js/libs/tern-threejs/threejs.js1222-1228

new TextGeometry(text, parameters)

Parameters include standard ExtrudeGeometry options plus font-specific properties:

  • font: Font data object (typically loaded from JSON font files)
  • size: Font size (default 100)
  • height: Extrusion depth (maps to depth option)
  • curveSegments: Curve tessellation (default 12)
  • bevelEnabled: Enable beveling (default true)
  • bevelThickness: Bevel depth (default 10)
  • bevelSize: Bevel offset (default 8)

The font system uses FontUtils (or the font loader) to convert text strings into Shape objects, which are then extruded using the standard ExtrudeGeometry pipeline.

LatheGeometry

LatheGeometry creates axially symmetric surfaces by rotating a 2D profile around the Y-axis. This is a procedural generator for surfaces of revolution.

const points = [
    new Vector2(0, 0),
    new Vector2(10, 0),
    new Vector2(10, 20),
    new Vector2(5, 30)
];
const geometry = new LatheGeometry(points, segments, phiStart, phiLength);

Parameters:

  • points: Array of Vector2 defining the 2D profile (rotated around Y-axis)
  • segments: Number of circumferential segments (default: 12)
  • phiStart: Starting angle in radians (default: 0)
  • phiLength: Sweep angle in radians (default: 2π for full rotation)

Common use cases: vases, bottles, bowls, architectural columns, lamp shades.

Parametric Geometries

ParametricGeometry

ParametricGeometry generates geometry from a parametric surface function editor/js/libs/tern-threejs/threejs.js1154-1160:

function surfaceFunction(u, v, target) {
    // u, v ∈ [0, 1]
    // Set target.x, target.y, target.z
}

const geometry = new ParametricGeometry(surfaceFunction, slices, stacks);

The function is evaluated on a grid of (u,v) coordinates:

  • slices: Number of subdivisions in u direction
  • stacks: Number of subdivisions in v direction

Each grid cell becomes two triangles, creating a tessellated surface.

TubeGeometry

TubeGeometry extrudes a circular cross-section along a 3D curve editor/js/libs/tern-threejs/threejs.js1246-1269:

const path = new CatmullRomCurve3(points);
const geometry = new TubeGeometry(path, tubularSegments, radius, radialSegments, closed);

Properties:

  • tangents: Array of tangent vectors along path
  • normals: Array of normal vectors
  • binormals: Array of binormal vectors

The Frenet frame vectors define the orientation of the circular cross-section at each point along the path.

ShapeGeometry

ShapeGeometry creates flat (2D) geometry from shapes without extrusion editor/js/libs/tern-threejs/threejs.js1190-1200:

const shape = new Shape();
shape.moveTo(0, 0);
shape.lineTo(0, 10);
shape.lineTo(10, 10);
shape.lineTo(10, 0);
shape.lineTo(0, 0);

const geometry = new ShapeGeometry([shape], options);

This is effectively ExtrudeGeometry with depth: 0 and bevelEnabled: false, but optimized for 2D use cases. It triangulates the shape and adds only a single set of vertices (no extrusion layers).

Internal Utilities and Patterns

Procedural geometry generators use common internal utilities from ShapeUtils and follow standard attribute construction patterns.

ShapeUtils

Used internally by ExtrudeGeometry for 2D shape processing:

Vertex Construction Pattern

All procedural generators follow this BufferGeometry construction pattern src/geometries/ExtrudeGeometry.js74-77:

  1. Build flat vertex position arrays (Float32Array or Array)
  2. Build face index arrays (for indexed geometry)
  3. Create BufferAttribute objects
  4. Call this.setAttribute('position', new Float32BufferAttribute(verticesArray, 3))
  5. Call this.setAttribute('uv', new Float32BufferAttribute(uvArray, 2))
  6. Call this.computeVertexNormals() to auto-generate normals

Example from ExtrudeGeometry:

this.setAttribute('position', new Float32BufferAttribute(verticesArray, 3));
this.setAttribute('uv', new Float32BufferAttribute(uvArray, 2));
this.computeVertexNormals();

Internal helper functions like scalePt2() src/geometries/ExtrudeGeometry.js222-228 mergeOverlappingPoints() src/geometries/ExtrudeGeometry.js170-202 and getBevelVec() src/geometries/ExtrudeGeometry.js236-357 demonstrate geometry manipulation patterns used throughout procedural generation.

Serialization

Procedural geometries support JSON serialization through the toJSON() and fromJSON() pattern.

ExtrudeGeometry Serialization

The toJSON() method src/geometries/ExtrudeGeometry.js763-772 serializes:

  • Shape UUIDs (shapes must be serialized separately)
  • Options object
  • ExtrudePath (if present) is serialized via its own toJSON()

The fromJSON() static method src/geometries/ExtrudeGeometry.js782-804 reconstructs:

  • Looks up shapes by UUID in provided shapes array
  • Reconstructs extrudePath using curve type and Curves[extrudePath.type]
  • Creates new ExtrudeGeometry with restored parameters

This pattern is consistent across all procedural geometries, allowing scenes to be serialized and deserialized with full geometry reconstruction. See Scene Serialization for details.

Integration with Rendering System

All procedural geometries produce BufferGeometry instances that integrate with the rendering pipeline:

  1. Vertex Attributes: position, normal, uv (and optionally color, tangent)
  2. Draw Groups: addGroup(start, count, materialIndex) for multi-material support src/geometries/ExtrudeGeometry.js626-650
  3. Bounding Volumes: Computed via computeBoundingBox() and computeBoundingSphere()

The rendering system (see WebGL Renderer (Legacy) and Modern Renderer Architecture) consumes these attributes to upload data to the GPU and execute draw calls.