If you’ve seen this line in raycasting examples:
rayDirection.normalize();
and thought “yeah yeah, makes it normal… whatever that means” — here’s what it actually does and why it matters.
The short version
normalize() makes a vector exactly 1 unit long while keeping it pointing in the same direction.
That’s it.
If you start with this:
const rayDirection = new THREE.Vector3(10, 0, 0);
You have a vector pointing along the positive X axis, but its length is 10.
After this:
rayDirection.normalize();
It becomes:
(1, 0, 0)
Same direction. Length is now exactly 1.
What normalization really means
Mathematically, normalization just divides a vector by its length:
normalized = v / |v|
So if the length is 10, every component gets divided by 10.
You can see it directly:
const v = new THREE.Vector3(10, 0, 0);
console.log(v.length()); // 10
v.normalize();
console.log(v.length()); // 1
The direction didn’t change. Only the magnitude did.
Here's a handy diagram to visualize it:

(credit: from a Medium article on text analysis, but it fits perfectly here)
Why Three.js raycasting needs this
The important part: Raycaster expects the direction to be normalized.
There are two main reasons.
Distance calculations assume unit length
When a ray hits something, Three.js calculates how far along the ray the intersection happened.
Those distance values only make sense if the direction vector has length 1.
If your direction vector had length 10, the internal math would scale everything incorrectly. Distances would no longer match world units properly.
A normalized vector makes 1 unit of direction = 1 unit in the scene.The math assumes it
Many ray–geometry intersection formulas assume the direction vector is a unit vector. The docs explicitly state that the direction must be normalized.
So even if things seem to work without it, you're relying on undefined behavior.
What your ray code is actually doing
const rayOrigin = new THREE.Vector3(-3, 0, 0);
const rayDirection = new THREE.Vector3(10, 0, 0);
rayDirection.normalize();
const raycaster = new THREE.Raycaster(rayOrigin, rayDirection);
This creates:
A ray starting at x = -3
Shooting straight right along the X axis
With a properly normalized direction
Now when you call:
raycaster.intersectObjects(scene.children);
The intersection distances will be correct and consistent.
Important detail: normalize() mutates
One thing people miss:
vector.normalize();
This changes the original vector.
If you need the original untouched:
const direction = original.clone().normalize();
How to control ray length (don’t scale the direction)
If you want to limit how far the ray checks for intersections, don’t multiply the direction.
Do this instead:
raycaster.far = 100;
raycaster.near = 0;
Keep the direction normalized. Let the raycaster handle range.
Quick mental model
Think of a direction vector like a compass needle.
Before normalization, it might be a 10-meter long arrow.
After normalization, it’s a 1-meter arrow pointing the same way.
Raycasting wants the 1-meter version so all distance math stays clean and predictable.
One sentence explanation
normalize() makes your direction vector exactly 1 unit long while keeping it pointing the same way — and Three.js raycasting depends on that.
Top comments (0)