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:
- Shape-based generators:
ExtrudeGeometry,TextGeometry,ShapeGeometry- convert 2D shapes to 3D meshes - Parametric generators:
ParametricGeometry,TubeGeometry,LatheGeometry- evaluate mathematical functions to create surfaces - Base infrastructure:
Shape,Path,Curveclasses 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.
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 usinggetPoint()getSpacedPoints(divisions): Returns equi-spaced points using arc lengthcomputeFrenetFrames(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 offsetlineTo(x, y): Adds line segmentquadraticCurveTo(cpX, cpY, x, y): Adds quadratic Bézier curvebezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, x, y): Adds cubic Bézier curvearc(x, y, radius, startAngle, endAngle, clockwise): Adds circular arcellipse(x, y, xRadius, yRadius, startAngle, endAngle, clockwise): Adds elliptical arc
Shape
Extends Path to add hole support:
holes: Array of Path objects representing interior holesextractPoints(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):
| Property | Type | Default | Description |
|---|---|---|---|
| curveSegments | number | 12 | Number of points on curves |
| steps | number | 1 | Number of subdivisions along extrusion depth |
| depth | number | 1 | Depth to extrude the shape |
| bevelEnabled | boolean | true | Enable beveling |
| bevelThickness | number | 0.2 | Depth of bevel into shape |
| bevelSize | number | bevelThickness - 0.1 | Distance bevel extends from outline |
| bevelOffset | number | 0 | Distance from outline where bevel starts |
| bevelSegments | number | 3 | Number of bevel layers |
| extrudePath | Curve | null | 3D spline path for extrusion (disables bevels) |
| UVGenerator | Object | WorldUVGenerator | Custom UV generation functions |
Extrusion Pipeline
ExtrudeGeometry Processing Flow
Key Algorithms
Bevel Vector Calculation
The getBevelVec() function src/geometries/ExtrudeGeometry.js236-357 calculates offset vectors for beveling:
- For each contour vertex, find previous and next vertices
- Compute normalized edge vectors
- Check if edges are collinear (cross product ≈ 0)
- If not collinear: compute line-line intersection of offset parallel edges
- If collinear: use perpendicular offset (straight or spike case)
- 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:
- Sample points along path using
getSpacedPoints(steps) - Compute Frenet frames (tangent, normal, binormal) using
computeFrenetFrames(steps, isClosed) - For each shape vertex, transform by frame to position along path
- 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:
- Back face vertices (z = 0 or at start of extrudePath)
- Intermediate vertices for each step (z = depth * step / steps)
- Front face vertices (z = depth or at end of extrudePath)
- Bevel vertices at front and back (if enabled)
Faces are added using helper functions:
f3(a, b, c): Adds triangle face src/geometries/ExtrudeGeometry.js694-707f4(a, b, c, d): Adds quad as two triangles src/geometries/ExtrudeGeometry.js709-731addVertex(index): Pushes vertex position toverticesArraysrc/geometries/ExtrudeGeometry.js733-739
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 todepthoption)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 ofVector2defining 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 directionstacks: 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 pathnormals: Array of normal vectorsbinormals: 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:
ShapeUtils.isClockWise(vertices): Determines winding order to ensure counter-clockwise contours src/geometries/ExtrudeGeometry.js145-165ShapeUtils.triangulateShape(contour, holes): Ear-clipping triangulation to generate face indices src/geometries/ExtrudeGeometry.js402-453
Vertex Construction Pattern
All procedural generators follow this BufferGeometry construction pattern src/geometries/ExtrudeGeometry.js74-77:
- Build flat vertex position arrays (
Float32ArrayorArray) - Build face index arrays (for indexed geometry)
- Create
BufferAttributeobjects - Call
this.setAttribute('position', new Float32BufferAttribute(verticesArray, 3)) - Call
this.setAttribute('uv', new Float32BufferAttribute(uvArray, 2)) - 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
ExtrudeGeometrywith 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:
- Vertex Attributes:
position,normal,uv(and optionallycolor,tangent) - Draw Groups:
addGroup(start, count, materialIndex)for multi-material support src/geometries/ExtrudeGeometry.js626-650 - Bounding Volumes: Computed via
computeBoundingBox()andcomputeBoundingSphere()
The rendering system (see WebGL Renderer (Legacy) and Modern Renderer Architecture) consumes these attributes to upload data to the GPU and execute draw calls.