Different Shapes

Boxes and spheres are fine, but what if you want something more interesting — an arrow, a star, a bottle, or a triangle? Three.js gives you a few different tools for building custom shapes, and which one you use depends on what kind of shape you're making.
making an arrow with lines
If you want a simple outline of a shape (like a wireframe arrow), use BufferGeometry with setFromPoints:
const points = [];
points.push(new THREE.Vector3(-10, 0, 0));
points.push(new THREE.Vector3(0, 10, 0));
points.push(new THREE.Vector3(10, 0, 0));
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: 0x0000ff });
const line = new THREE.Line(geometry, material);
scene.add(line);
This creates a V-shaped arrow using just three points connected by lines.
Good for: Wireframes, arrows, diagrams, measurements.
making a star with Shape
If you want a solid, filled 2D shape — like a star that you can texture or extrude into 3D — use THREE.Shape. It works like drawing on a canvas with moveTo and lineTo:
const shape = new THREE.Shape();
const outerRadius = 10;
const innerRadius = 4;
const spikes = 5;
for (let i = 0; i spikes * 2; i++) {
const radius = i % 2 === 0 ? outerRadius : innerRadius;
const angle = (i / (spikes * 2)) * Math.PI * 2 - Math.PI / 2;
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
if (i === 0) {
shape.moveTo(x, y);
} else {
shape.lineTo(x, y);
}
}
shape.closePath();
const geometry = new THREE.ShapeGeometry(shape);
const material = new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
});
const star = new THREE.Mesh(geometry, material);
scene.add(star);
Good for: Stars, badges, icons, any 2D shape with straight or curved edges.
making a bottle with LatheGeometry
For shapes that are round but not simple spheres — like a bottle, a vase, or a chess piece — use LatheGeometry. It works by taking a 2D profile (a set of points) and revolving it around an axis, like spinning clay on a pottery wheel.
const points = [];
const height = 20;
const radius = 8;
const neckHeight = 6;
const neckRadius = 2;
// Profile of the bottle — trace one side
points.push(new THREE.Vector2(0, 0)); // center of base
points.push(new THREE.Vector2(radius * 0.8, 0)); // base edge
points.push(new THREE.Vector2(radius, 1)); // start of body
// Body
points.push(new THREE.Vector2(radius, height - neckHeight - 2));
points.push(new THREE.Vector2(radius * 0.9, height - neckHeight - 1));
// Neck
points.push(new THREE.Vector2(neckRadius + 1, height - neckHeight));
points.push(new THREE.Vector2(neckRadius, height - neckHeight + 1));
// Top
points.push(new THREE.Vector2(neckRadius, height));
points.push(new THREE.Vector2(0, height)); // center of top
const geometry = new THREE.LatheGeometry(points, 32);
const material = new THREE.MeshStandardMaterial({
color: 0x4488aa,
side: THREE.DoubleSide,
});
const bottle = new THREE.Mesh(geometry, material);
scene.add(bottle);
Good for: Bottles, vases, lamp shades, goblets, pillars — anything with rotational symmetry.
making a triangle with Shape
Here's the simplest solid shape — a triangle:
const shape = new THREE.Shape();
shape.moveTo(-10, -10);
shape.lineTo(10, -10);
shape.lineTo(0, 10);
shape.closePath();
const geometry = new THREE.ShapeGeometry(shape);
const material = new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
});
const triangle = new THREE.Mesh(geometry, material);
scene.add(triangle);
which approach should you use?
| You want to... | Use this |
|---|---|
| Draw lines or wireframes | Line + setFromPoints |
| Make a solid 2D shape (star, triangle) | ShapeGeometry |
| Make a rotated object (bottle, vase) | LatheGeometry |
| Build any shape from scratch (custom) | BufferGeometry |
Each is useful for different things. Start with Shape for flat shapes and LatheGeometry for anything round and symmetrical.
