Three.js Camera: PerspectiveCamera vs OrthographicCamera

Use PerspectiveCamera for anything meant to look real: it renders with foreshortening, so distant objects appear smaller, the way human vision and photography work. Use OrthographicCamera when you need parallel projection with no foreshortening, for isometric games, CAD-style views, 2D-in-3D UI, or architectural elevations where consistent scale matters more than depth realism.

Last updated . Verified against three.js r181.

Read the FAQJump to code

PerspectiveCamera vs OrthographicCamera

PerspectiveCamera(fov, aspect, near, far) is the default choice. fov is the vertical field of view in degrees (50-75 is a natural-feeling range for most scenes; wider values distort more like a fisheye). aspect should track your canvas's width/height ratio. near/far define the clipping planes: objects closer than near or farther than far aren't rendered.

OrthographicCamera(left, right, top, bottom, near, far) gives parallel projection, so an object's on-screen size doesn't change with distance from the camera. This is what real-time strategy games, architectural walkthroughs and technical/CAD viewers typically use, because consistent scale reads more clearly than a photorealistic vanishing point.

Neither is "better." They solve different problems. A product configurator wants perspective (it should look like a photo); a floor-plan viewer wants orthographic (a wall shouldn't appear to shrink because it's farther away).

Field of view and distortion

A very wide fov (100°+) stretches objects near the frame edges into the fisheye look, sometimes used deliberately for a sense of speed or unease, but usually an accident from setting FOV too high while debugging why an object "looks small." A narrow fov (20-30°) compresses depth, similar to a telephoto lens, flattening the scene. Useful for hero shots where you want less perspective distortion on a subject.

For most product/portfolio work, 45-60° reads as natural without either extreme.

Handling window resize correctly

A camera's aspect (perspective) or left/right/top/bottom (orthographic) must be updated whenever the canvas size changes, or the render will stretch. The pattern: listen for resize, update the camera's aspect/frustum, call camera.updateProjectionMatrix(), and resize the renderer to match. This call is easy to forget, and the render will silently use the stale projection until it's called.

Code

Resize-safe PerspectiveCamera (r181)
1import * as THREE from 'three'
2
3const camera = new THREE.PerspectiveCamera(
4 55, // fov
5 window.innerWidth / window.innerHeight,
6 0.1,
7 100
8)
9camera.position.set(0, 2, 6)
10
11window.addEventListener('resize', () => {
12 camera.aspect = window.innerWidth / window.innerHeight
13 camera.updateProjectionMatrix() // easy to forget, required after any change
14 renderer.setSize(window.innerWidth, window.innerHeight)
15})
OrthographicCamera for a CAD-style view
1// Cameras are identical across WebGL and WebGPU renderers; only the
2// material/shading layer differs. Orthographic setup for a technical view:
3const aspect = window.innerWidth / window.innerHeight
4const frustumSize = 10
5const camera = new THREE.OrthographicCamera(
6 (-frustumSize * aspect) / 2, (frustumSize * aspect) / 2,
7 frustumSize / 2, -frustumSize / 2,
8 0.1, 100
9)
10camera.position.set(10, 10, 10)
11camera.lookAt(0, 0, 0)

Learn this properly

Learn Practical TSL

Your First Node Material

Set up a scene and camera first before styling what the camera sees.

Start the lesson (6 minutes)

Frequently asked questions

Should I use PerspectiveCamera or OrthographicCamera?

PerspectiveCamera for anything meant to look photorealistic since it foreshortens like human vision. OrthographicCamera for isometric games, CAD/technical views, or anywhere consistent scale matters more than depth realism, since it uses parallel projection with no foreshortening.

Why does my Three.js scene look stretched after resizing the browser window?

You need to update camera.aspect (or the orthographic frustum bounds) and call camera.updateProjectionMatrix() on resize. Forgetting the updateProjectionMatrix() call is the most common cause, since the aspect value alone doesn't take effect until then.

What field of view should I use for a Three.js PerspectiveCamera?

45-60 degrees looks natural for most scenes. Higher values (90+) create a fisheye-like distortion at the frame edges; lower values (20-30) compress depth like a telephoto lens.

Keep reading