Random Point on Sphere Surface in Three.js

Generating a pseudo-random point on the surface of a sphere is a common requirement in 3D graphics, often used for positioning particles, spawning objects, or calculating lighting effects. This article demonstrates how to achieve a uniform distribution on a sphere’s surface using Three.js, covering both the quick modern shorthand method and the manual mathematical approach using Three.js utility functions.

The easiest and most efficient way to get a random point on a unit sphere (a sphere with a radius of 1) is to use the built-in randomDirection() method of the THREE.Vector3 class. This method automatically calculates a random, uniformly distributed unit vector.

import * as THREE from 'three';

// Create a vector to store the coordinates
const point = new THREE.Vector3();

// Generate a random point on a sphere of radius 1
point.randomDirection();

// Scale the point if you need a specific sphere radius (e.g., radius of 5)
const radius = 5;
point.multiplyScalar(radius);

console.log(`X: ${point.x}, Y: ${point.y}, Z: ${point.z}`);

Method 2: Manual Spherical Coordinates with THREE.MathUtils

If you are using an older version of Three.js that lacks randomDirection(), or if you need to restrict the point generation to a specific portion of the sphere (like a dome or hemisphere), you can calculate the point manually using spherical coordinates and THREE.MathUtils.

To ensure the points are uniformly distributed across the surface without clumping at the poles, you must distribute the cosine of the polar angle (\(\phi\)) rather than the angle itself.

import * as THREE from 'three';

function getRandomSpherePoint(radius) {
    const point = new THREE.Vector3();

    // Generate uniform random variables between 0 and 1
    const u = Math.random();
    const v = Math.random();

    // Theta is the azimuthal angle (around the Y axis)
    const theta = u * 2.0 * Math.PI;

    // Phi is the polar angle (from the positive Y axis)
    // Using acos ensures uniform distribution across the surface area
    const phi = Math.acos(2.0 * v - 1.0);

    // Set coordinates using Three.js built-in spherical converter
    point.setFromSphericalCoords(radius, phi, theta);

    return point;
}

// Example usage
const targetRadius = 10;
const randomPoint = getRandomSpherePoint(targetRadius);

Understanding the Mathematics

In Method 2, simply picking a random angle for \(\phi\) between \(0\) and \(\pi\) results in “polar crowding,” where points bunch up at the top and bottom poles of the sphere. By mapping a flat random value \(v\) to Math.acos(2.0 * v - 1.0), you compensate for the narrowing circumference of the sphere near the poles, resulting in an mathematically perfect, uniform distribution.