Random Position On The Surface Of A Sphere
Ok, so you want to randomly position lots of things on the surface of a sphere? Lets try a few things. I’ll be using THREE.js for these examples but the logic should be transferable.
First try — Random vector with setLength().
function getCartesianPositions(howMany, radius) {
// Create and array to store our vector3 point data
var vectors = [];
// Create new points using random x,y and z properties then setting vector length to radius
for (var i = 0; i < howMany; i += 1) {
var vec3 = new THREE.Vector3();
vec3.x = THREE.Math.randFloatSpread(1);
vec3.y = THREE.Math.randFloatSpread(1);
vec3.z = THREE.Math.randFloatSpread(1);
vec3.setLength(radius);
vectors.push(vec3);
}
return vectors;
}
This method takes two parameters. howMany - the number of points you want and the radius of your sphere. In the loop we generate a new vectors and set their x,y, and z points to random points between -1 and 1. This effectively puts the points inside a cube. Then we use the setLength() method of the vector to push the point out to the surface of a sphere. So what we’ve done is make a tiny cube of points and blow it out to be a large sphere. This method actually works pretty well for smaller numbers of points but when you start to use a lot 100,000 or more you can start to see clustering where the edges of the cube were.

Lets try something else!
Spherical coordinates
function getSphericalPositions(howMany, radius) {
// Create and array to store our vector3 point data
var vectors = [];
// Create a spherical object
var spherical = new THREE.Spherical();
// Set radius of spherical
spherical.radius = radius;
// Create new points using random phi and theta properties of the spherical object
for (var i = 0; i < howMany; i += 1) {
spherical.phi = THREE.Math.randFloat(0, Math.PI); // Phi is between 0 - PI
spherical.theta = THREE.Math.randFloat(0, Math.PI * 2); // Phi is between 0 - 2 PI
var vec3 = new THREE.Vector3().setFromSpherical(spherical);
vectors.push(vec3);
}
return vectors;
}
This time we’ll use a random spherical coordinate and convert it to a cartesian coordinate. Spherical coordinates have three properties. radius, phi and theta. Basically a radius and two different angles — Phi between 0 and PI and Theta between 0 and PI*2. We’ll use our radius and generate two random angles.

Hmm, we’ve got a lot of clustering at the poles. That’s not what we want. Lets try add a little bias into the distribution.
function getSphericalPositionsWithBias(howMany, radius, bias) {
var vectors = [];
var spherical = new THREE.Spherical();
spherical.radius = radius;
for (var i = 0; i < howMany; i += 1) {
spherical.phi = getRndBias(0, Math.PI, Math.PI / 2, bias); // Phi is between 0 - PI
spherical.theta = THREE.Math.randFloat(0, Math.PI * 2); // Theta is between 0 - 2 PI
var vec3 = new THREE.Vector3().setFromSpherical(spherical);
vectors.push(vec3);
}
return vectors;
}
function getRndBias(min, max, bias, influence) {
const rnd = Math.random() * (max - min) + min; // random in range
const mix = Math.random() * influence; // random mixer
return rnd * (1 - mix) + bias * mix; // mix full range and bias
}
We’re going to try bias the distribution to favor the middle of the phi angle.
getSphericalPositionsWithBias(numberOfPoints,radiusOfSphere, 1);
Hmm, now we have too many particles along the equator of our sphere. 🤔

Ok, lets try tweak the bias… Using 0.5.
getSphericalPositionsWithBias(numberOfPoints,radiusOfSphere, 0.5);
Hurrah! This looks pretty good. No, or very little, clustering. Yes!

Bonus
Uniform distribution on a sphere.
function getUniformPositions(howMany, radius) {
var vectors = [];
var inc = Math.PI * (3 - Math.sqrt(5));
var x = 0;
var y = 0;
var z = 0;
var r = 0;
var phi = 0;
for (var k = 0; k < howMany; k++) {
var off = 2 / howMany;
var vec3 = new THREE.Vector3();
y = k * off - 1 + off / 2;
r = Math.sqrt(1 - y * y);
phi = k * inc;
x = Math.cos(phi) * r;
z = (0, Math.sin(phi) * r);
x *= radius;
y *= radius;
z *= radius;
vec3.x = x;
vec3.y = y;
vec3.z = z;
vectors.push(vec3);
}
return vectors;
}
I didn’t write this. I don’t fully understand it either but what is does do is give you a nice uniform distribution over the surface of a sphere. I can’t remember where I found this code. But you recognise it then please let me know and I’ll credit it.
