What normalize() does (and why Three.js raycasting needs it)

Published: (February 12, 2026 at 11:26 AM EST)
2 min read
Source: Dev.to

Source: Dev.to

What normalize() does

normalize() makes a vector exactly 1 unit long while keeping its direction unchanged.

const rayDirection = new THREE.Vector3(10, 0, 0); // length = 10
rayDirection.normalize();                         // → (1, 0, 0)

Mathematically, normalization divides a vector by its length:

[ \text{normalized} = \frac{v}{|v|} ]

const v = new THREE.Vector3(10, 0, 0);
console.log(v.length()); // 10

v.normalize();

console.log(v.length()); // 1

The direction stays the same; only the magnitude changes.

Why Three.js raycasting needs a normalized direction

Distance calculations assume unit length

When a ray hits something, Three.js computes how far along the ray the intersection occurs. Those distance values are meaningful only if the direction vector has length 1. If the direction were length 10, the internal math would scale everything incorrectly, and distances would no longer correspond to world units.

Intersection formulas assume a unit vector

Many ray‑geometry intersection formulas (and the Three.js documentation) require the direction vector to be a unit vector. Skipping normalization leads to undefined behavior, even if it sometimes appears to work.

How to use normalize() correctly

Typical ray‑casting setup

const rayOrigin    = new THREE.Vector3(-3, 0, 0);
const rayDirection = new THREE.Vector3(10, 0, 0);

rayDirection.normalize();               // ensure unit length

const raycaster = new THREE.Raycaster(rayOrigin, rayDirection);
  • Origin: starts at x = -3
  • Direction: points straight right along the X axis, now normalized

Calling:

raycaster.intersectObjects(scene.children);

will return intersection distances that are correct and consistent.

Preserve the original vector (if needed)

const original  = new THREE.Vector3(10, 0, 0);
const direction = original.clone().normalize(); // original stays unchanged

Controlling the ray’s range

Do not scale the direction vector to limit range. Instead set the raycaster’s near and far properties:

raycaster.near = 0;
raycaster.far  = 100; // limit to 100 world units

Keep the direction normalized; let the raycaster handle the distance limits.

Visual analogy

Think of a direction vector as a compass needle.

  • Before normalization: a 10‑meter‑long arrow.
  • After normalization: a 1‑meter‑long arrow pointing the same way.

Three.js raycasting expects the 1‑meter version so that all distance calculations remain clean and predictable.

0 views
Back to Blog

Related posts

Read more »

Descent, Ported to the Web

Article Descent, Ported to the Webhttps://mrdoob.github.io/three-descent/ Discussion Hacker News thread – 36 points, 7 commentshttps://news.ycombinator.com/ite...

Descent, ported to the web

Article Descent, ported to the webhttps://mrdoob.github.io/three-descent/ Discussion Hacker News discussion ID 47017545https://news.ycombinator.com/item?id=470...

A Beginner’s Guide to ThreeJs

markdown ! https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2...