Listen up. If you're building modern applications, understanding The Camera in Three.js 3D WebGL is non-negotiable. This is where simple logic turns into intelligent behavior.
1The Camera as Your Eyes
Welcome to the Camera lesson! If the Scene is your universe, the Camera is your eyes. Without it, you cannot see anything in the Scene ā the renderer needs a camera to know what viewpoint to project the 3D world from.
A THREE.PerspectiveCamera doesn't live inside the scene by default the way a mesh does; it's simply passed alongside the scene into renderer.render(scene, camera) each frame. Its position, rotation, and field of view together define exactly what ends up visible on screen.
const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);3D Scene rendered. Objects: 4, Draw Calls: Optimized.
2Perspective vs Orthographic Cameras
There are two main types of cameras in Three.js: PerspectiveCamera and OrthographicCamera. We almost always use Perspective, since it mimics how human vision actually works ā objects shrink as they move further away.
OrthographicCamera instead uses parallel projection, so object size stays constant regardless of distance from the camera. This makes it the standard choice for isometric games, architectural blueprints, and 2D-style overlays layered on top of a 3D scene, where consistent scale matters more than realistic depth perception.
// Perspective: Things get smaller as they get further away (like human eyes)
// Orthographic: Things stay the same size regardless of distance (used in Sim City / isometric games)3D Scene rendered. Objects: 4, Draw Calls: Optimized.
3The Four PerspectiveCamera Arguments
Let's break down the 4 arguments of the PerspectiveCamera: Field of View (FOV), Aspect Ratio, Near clipping plane, and Far clipping plane ā every PerspectiveCamera you create needs all four to fully define its viewing frustum.
Together these four numbers describe a pyramid-shaped volume of space (the 'frustum') that the camera can see. Anything outside that frustum ā too close, too far, or outside the field-of-view angle ā is clipped and never rendered, no matter how it's positioned in the scene.
new THREE.PerspectiveCamera( fov, aspect, near, far );3D Scene rendered. Objects: 4, Draw Calls: Optimized.
4FOV and Aspect Ratio
FOV is the angle of your vision. 75 degrees is standard. Aspect ratio should almost always be your screen width divided by your screen height.
Getting the aspect ratio wrong is a classic bug source: if it doesn't match the actual canvas dimensions, everything renders stretched or squashed. This is also why camera.aspect needs to be updated (followed by camera.updateProjectionMatrix()) whenever the window or canvas is resized ā a hardcoded aspect ratio breaks the moment the viewport size changes.
const fov = 75;
const aspect = window.innerWidth / window.innerHeight;
// Near: Anything closer than this won't be rendered.
// Far: Anything further than this won't be rendered.3D Scene rendered. Objects: 4, Draw Calls: Optimized.
5Near and Far Clipping Planes
If you set the 'far' clipping plane to 100, any object placed beyond Z = -100 from the camera becomes completely invisible ā not blurry, not faded, simply not rendered at all, since it falls outside the viewing frustum.
The near and far values also determine depth-buffer precision: a near value set too close to zero combined with a very large far value can cause z-fighting (flickering overlap artifacts) on distant objects, because the available depth precision gets spread across an unnecessarily huge range. Keep the near/far ratio as tight as your scene allows.
const camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 100);3D Scene rendered. Objects: 4, Draw Calls: Optimized.
6Automatic Camera Setup in R3F
In React Three Fiber, the Canvas creates a PerspectiveCamera for you automatically! You can position it using the camera prop on the Canvas, passing an object with position, fov, near, and far as needed.
R3F also handles the aspect-ratio-on-resize problem automatically ā it observes the Canvas element's size and updates camera.aspect plus calls updateProjectionMatrix() for you, which eliminates one of the more common manual bugs from vanilla Three.js setups.
<Canvas camera={{ position: [0, 0, 5], fov: 75 }}>
{/* Scene */}
</Canvas>3D Scene rendered. Objects: 4, Draw Calls: Optimized.
7High FOV: The Fish-Eye Effect
Let's see what happens when we change the FOV. Watch this cube. A high FOV creates a 'fish-eye' effect, exaggerating perspective distortion the same way a wide-angle camera lens does.
High FOV values (100+) widen the visible frustum angle dramatically, which makes nearby objects appear larger relative to the frame and bends straight lines near the screen edges. This can be a deliberate stylistic choice, but it also makes objects near the camera look unnaturally stretched if overused.
const App = () => {
return (
<Canvas camera={{ position: [0, 0, 3], fov: 120 }}>
<color attach="background" args={["#222"]} />
<ambientLight intensity={1} />
<mesh>
<boxGeometry />
<meshStandardMaterial color="hotpink" wireframe />
</mesh>
</Canvas>
);
};
render(<App />);3D Scene rendered. Objects: 4, Draw Calls: Optimized.
8Low FOV: The Zoom/Telephoto Effect
Now let's change the FOV to a very low number, like 20. Notice how zoomed in it feels, like using a sniper scope ā a low FOV narrows the frustum angle, compressing perspective the way a telephoto camera lens does.
Low FOV values flatten the sense of depth between objects at different distances, which is why telephoto-style shots in film feel more 'compressed' than wide shots. In games, low FOV is often used deliberately for aiming-down-sights or binocular-zoom mechanics.
const App = () => {
return (
<Canvas camera={{ position: [0, 0, 8], fov: 20 }}>
<color attach="background" args={["#222"]} />
<ambientLight intensity={1} />
<mesh>
<boxGeometry />
<meshStandardMaterial color="hotpink" wireframe />
</mesh>
</Canvas>
);
};
render(<App />);3D Scene rendered. Objects: 4, Draw Calls: Optimized.
9Choosing FOV for the Right Feel
To create a 'fish-eye' lens effect, you increase the FOV; to create a zoomed-in, telephoto feel, you decrease it. There's no single 'correct' value ā the right FOV depends entirely on what your application needs to communicate.
Most general-purpose 3D applications settle somewhere between 45 and 75 degrees, since this range roughly matches natural human perception without introducing noticeable distortion. Values outside that range are typically reserved for deliberate stylistic or gameplay effects rather than default camera setups.
<Canvas camera={{ fov: ??? }}>3D Scene rendered. Objects: 4, Draw Calls: Optimized.
10Camera Fundamentals Complete
Great job! You've mastered how to view the world. Remember, without a camera, the 3D scene exists, but no one is there to observe it ā the scene and the camera are two independent, equally necessary halves of what ends up on screen.
In the next lesson, we'll look at the Renderer ā the piece that actually takes this Scene and Camera pairing and turns it into pixels drawn to the canvas, closing the loop on the Holy Trinity.
// šø Camera ready!3D Scene rendered. Objects: 4, Draw Calls: Optimized.
11Step-by-Step Breakdown
Welcome to the Camera lesson! If the Scene is your universe, the Camera is your eyes. Without it, you cannot see anything in the Scene.
There are two main types of cameras in Three.js: PerspectiveCamera and OrthographicCamera. We almost always use Perspective.
Which camera type mimics how the human eye perceives depth (objects further away appear smaller)?
- āOrthographic
- āPerspective
- āStereo
Let's break down the 4 arguments of the PerspectiveCamera: Field of View (FOV), Aspect Ratio, Near clipping plane, and Far clipping plane.
FOV is the angle of your vision. 75 degrees is standard. Aspect ratio should almost always be your screen width divided by your screen height.
If you set the 'far' clipping plane to 100, what happens to an object placed at Z = -150?
- āIt renders very small
- āIt becomes invisible
- āIt renders blurry
In React Three Fiber, the Canvas creates a PerspectiveCamera for you automatically! You can position it using the camera prop on the Canvas.
Let's see what happens when we change the FOV. Watch this cube. A high FOV creates a 'fish-eye' effect.
Now let's change the FOV to a very low number, like 20. Notice how zoomed in it feels, like using a sniper scope.
To create a 'fish-eye' lens effect, should you increase or decrease the FOV (Field of View)?
- āIncrease
- āDecrease
Great job! You've mastered how to view the world. Remember, without a camera, the 3D scene exists, but no one is there to observe it.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Provide Alternative Navigation for Camera-Controlled 3D Views
A 3D scene that requires mouse-drag or scroll to orbit the camera excludes users who navigate by keyboard alone ā pair OrbitControls-style interaction with keyboard-accessible alternatives (preset view buttons, arrow-key rotation) so the same content isn't locked behind a mouse-only interaction.
<button onClick={() => setCameraPreset('front')}>Front View</button>SEO Implications
- 1
Camera Configuration Has No Direct SEO Weight, but the Concepts Do
A specific FOV value or camera position is runtime state with no crawlable footprint ā what does have SEO value is written, indexable explanation of FOV, clipping planes, and perspective vs. orthographic projection, since these are genuine, frequently-searched Three.js concepts.
Best Practices
Keep the near/far Clipping Range as Tight as Your Scene Allows
An unnecessarily large gap between near and far (e.g., 0.001 to 100000) spreads depth-buffer precision too thin, causing z-fighting artifacts on distant or overlapping geometry. Set both values based on your scene's actual smallest and largest relevant distances.
Always Update camera.aspect and Call updateProjectionMatrix() on Resize
A PerspectiveCamera's aspect ratio is baked into its projection matrix at creation time and does not update automatically when the canvas resizes. In vanilla Three.js, listen for resize events and call updateProjectionMatrix() afterward; React Three Fiber's Canvas handles this automatically.
Frequent Bugs
Changing camera.fov, camera.near, camera.far, or camera.aspect directly but seeing no visual change take effect.
These camera properties only take effect after calling camera.updateProjectionMatrix() ā Three.js caches the computed projection matrix for performance and does not recalculate it automatically just because a property changed.
Real-World Examples
Cinematic Camera Transitions in Product Showcases
Interactive product pages often animate the camera's FOV and position together ā briefly widening the FOV for a dramatic 'zoom out to reveal' moment before settling back to a standard 50-degree view for normal browsing, all controlled by tweening camera properties over a few frames.
gsap.to(camera, { fov: 50, duration: 1.2, onUpdate: () => camera.updateProjectionMatrix() });