---
name: r3f-geometry
description: React Three Fiber geometry - built-in shapes, BufferGeometry, instancing with Drei. Use when creating 3D shapes, custom meshes, point clouds, lines, or optimizing with instanced rendering.
---
# React Three Fiber Geometry
## Quick Start
```tsx
import { Canvas } from '@react-three/fiber'
function Scene() {
return (
)
}
```
## Built-in Geometries
All Three.js geometries are available as JSX elements. The `args` prop passes constructor arguments.
### Basic Shapes
```tsx
// BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
// SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
// High quality
// Hemisphere
// PlaneGeometry(width, height, widthSegments, heightSegments)
// Subdivided for displacement
// CircleGeometry(radius, segments, thetaStart, thetaLength)
// Semicircle
// CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded)
// Cone
// Hexagonal prism
// ConeGeometry(radius, height, radialSegments, heightSegments, openEnded)
// TorusGeometry(radius, tube, radialSegments, tubularSegments, arc)
// TorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q)
// RingGeometry(innerRadius, outerRadius, thetaSegments, phiSegments)
```
### Advanced Shapes
```tsx
// CapsuleGeometry(radius, length, capSegments, radialSegments)
// Polyhedrons
// radius, detail
// Higher detail = more subdivisions
// Approximates sphere
```
### Path-Based Shapes
```tsx
import * as THREE from 'three'
// LatheGeometry - revolve points around Y axis
function LatheShape() {
const points = [
new THREE.Vector2(0, 0),
new THREE.Vector2(0.5, 0),
new THREE.Vector2(0.5, 0.5),
new THREE.Vector2(0.3, 1),
new THREE.Vector2(0, 1),
]
return (
)
}
// TubeGeometry - extrude along a curve
function TubeShape() {
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-2, 0, 0),
new THREE.Vector3(-1, 1, 0),
new THREE.Vector3(1, -1, 0),
new THREE.Vector3(2, 0, 0),
])
return (
)
}
// ExtrudeGeometry - extrude a 2D shape
function ExtrudedShape() {
const shape = new THREE.Shape()
shape.moveTo(0, 0)
shape.lineTo(1, 0)
shape.lineTo(1, 1)
shape.lineTo(0, 1)
shape.lineTo(0, 0)
const extrudeSettings = {
steps: 2,
depth: 0.5,
bevelEnabled: true,
bevelThickness: 0.1,
bevelSize: 0.1,
bevelSegments: 3,
}
return (
)
}
```
## Drei Shape Helpers
@react-three/drei provides convenient shape components.
```tsx
import {
Box, Sphere, Plane, Circle, Cylinder, Cone,
Torus, TorusKnot, Ring, Capsule, Dodecahedron,
Icosahedron, Octahedron, Tetrahedron, RoundedBox
} from '@react-three/drei'
function DreiShapes() {
return (
<>
{/* All shapes accept mesh props directly */}
{/* RoundedBox - box with rounded edges */}
>
)
}
```
## Custom BufferGeometry
### Basic Custom Geometry
```tsx
import { useMemo, useRef } from 'react'
import * as THREE from 'three'
function CustomTriangle() {
const geometry = useMemo(() => {
const geo = new THREE.BufferGeometry()
// Vertices (3 floats per vertex: x, y, z)
const vertices = new Float32Array([
-1, -1, 0, // vertex 0
1, -1, 0, // vertex 1
0, 1, 0, // vertex 2
])
// Normals (pointing toward camera)
const normals = new Float32Array([
0, 0, 1,
0, 0, 1,
0, 0, 1,
])
// UVs
const uvs = new Float32Array([
0, 0,
1, 0,
0.5, 1,
])
geo.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
geo.setAttribute('normal', new THREE.BufferAttribute(normals, 3))
geo.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
return geo
}, [])
return (
)
}
```
### Indexed Geometry
```tsx
function CustomQuad() {
const geometry = useMemo(() => {
const geo = new THREE.BufferGeometry()
// 4 vertices for a quad
const vertices = new Float32Array([
-1, -1, 0, // 0: bottom-left
1, -1, 0, // 1: bottom-right
1, 1, 0, // 2: top-right
-1, 1, 0, // 3: top-left
])
// Indices to form 2 triangles
const indices = new Uint16Array([
0, 1, 2, // triangle 1
0, 2, 3, // triangle 2
])
const normals = new Float32Array([
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
])
const uvs = new Float32Array([
0, 0, 1, 0, 1, 1, 0, 1,
])
geo.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
geo.setAttribute('normal', new THREE.BufferAttribute(normals, 3))
geo.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
geo.setIndex(new THREE.BufferAttribute(indices, 1))
return geo
}, [])
return (
)
}
```
### Dynamic Geometry
```tsx
import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
function WavyPlane() {
const meshRef = useRef()
useFrame(({ clock }) => {
const positions = meshRef.current.geometry.attributes.position
const time = clock.elapsedTime
for (let i = 0; i < positions.count; i++) {
const x = positions.getX(i)
const y = positions.getY(i)
positions.setZ(i, Math.sin(x * 2 + time) * Math.cos(y * 2 + time) * 0.5)
}
positions.needsUpdate = true
meshRef.current.geometry.computeVertexNormals()
})
return (
)
}
```
## Drei Instancing
Efficient rendering of many identical objects.
### Instances Component
```tsx
import { Instances, Instance } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'
import { useRef } from 'react'
function InstancedBoxes() {
const count = 1000
return (
{Array.from({ length: count }, (_, i) => (
))}
)
}
function AnimatedInstance({ index }) {
const ref = useRef()
// Random initial position
const position = useMemo(() => [
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
], [])
const color = useMemo(() =>
['red', 'blue', 'green', 'yellow', 'purple'][index % 5],
[index])
useFrame(({ clock }) => {
const t = clock.elapsedTime
ref.current.rotation.x = t + index
ref.current.rotation.y = t * 0.5 + index
})
return (
)
}
```
### Merged Geometry
For static instances, merge geometry for best performance:
```tsx
import { Merged } from '@react-three/drei'
import { useMemo } from 'react'
import * as THREE from 'three'
function MergedMeshes() {
// Create geometries to merge
const meshes = useMemo(() => ({
Sphere: new THREE.SphereGeometry(0.5, 32, 32),
Box: new THREE.BoxGeometry(1, 1, 1),
Cone: new THREE.ConeGeometry(0.5, 1, 32),
}), [])
return (
{({ Sphere, Box, Cone }) => (
<>
>
)}
)
}
```
## Points (Particle Systems)
### Basic Points
```tsx
import { Points, Point, PointMaterial } from '@react-three/drei'
function ParticleField() {
const count = 5000
return (
{Array.from({ length: count }, (_, i) => (
))}
)
}
```
### Buffer-Based Points (High Performance)
```tsx
import { useMemo, useRef } from 'react'
import { useFrame } from '@react-three/fiber'
import * as THREE from 'three'
function BufferParticles() {
const count = 10000
const pointsRef = useRef()
const { positions, colors } = useMemo(() => {
const positions = new Float32Array(count * 3)
const colors = new Float32Array(count * 3)
for (let i = 0; i < count; i++) {
positions[i * 3] = (Math.random() - 0.5) * 10
positions[i * 3 + 1] = (Math.random() - 0.5) * 10
positions[i * 3 + 2] = (Math.random() - 0.5) * 10
colors[i * 3] = Math.random()
colors[i * 3 + 1] = Math.random()
colors[i * 3 + 2] = Math.random()
}
return { positions, colors }
}, [])
useFrame(({ clock }) => {
pointsRef.current.rotation.y = clock.elapsedTime * 0.1
})
return (
)
}
```
## Lines
### Basic Line
```tsx
import { Line } from '@react-three/drei'
function BasicLine() {
const points = [
[0, 0, 0],
[1, 1, 0],
[2, 0, 0],
[3, 1, 0],
]
return (
)
}
```
### Curved Line
```tsx
import { CatmullRomLine, QuadraticBezierLine, CubicBezierLine } from '@react-three/drei'
function CurvedLines() {
return (
<>
{/* Smooth curve through points */}
{/* Quadratic bezier */}
{/* Cubic bezier */}
>
)
}
```
### Dashed Line
```tsx
```
## Edges and Wireframe
```tsx
import { Edges } from '@react-three/drei'
function BoxWithEdges() {
return (
15 degrees
color="black"
/>
)
}
// Wireframe material
function WireframeBox() {
return (
)
}
```
## Text Geometry
### Using Drei Text3D
```tsx
import { Text3D, Center } from '@react-three/drei'
function Text3DExample() {
return (
Hello R3F
)
}
```
## Geometry Utilities
### Center Geometry
```tsx
import { Center } from '@react-three/drei'
function CenteredModel() {
return (
)
}
// With options
{/* Align to top-left */}
// Get bounding info
{
console.log('Dimensions:', width, height, depth)
}}>
```
### Compute Bounds
```tsx
import { useBounds, Bounds } from '@react-three/drei'
function FitToView() {
return (
)
}
function SelectToZoom() {
const bounds = useBounds()
return (
{
e.stopPropagation()
bounds.refresh(e.object).fit()
}}
>
)
}
```
## Performance Tips
1. **Reuse geometries**: Same geometry instance = better batching
2. **Use Instances**: For many identical objects
3. **Merge static meshes**: Use `` for static scenes
4. **Appropriate segment counts**: Balance quality vs performance
5. **Dispose unused geometry**: R3F handles this automatically
```tsx
// Good segment counts
// Standard quality
// High quality
// Performance mode
// Reuse geometry
const sharedGeometry = useMemo(() => new THREE.BoxGeometry(), [])
```
## See Also
- `r3f-fundamentals` - JSX elements and refs
- `r3f-materials` - Materials for meshes
- `r3f-shaders` - Custom vertex manipulation