<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/controls/OrbitControls.js"></script>

<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/ShaderPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/CopyShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/LuminosityHighPassShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/UnrealBloomPass.js"></script>
<script type="x-shader/x-vertex" id="vertex-shader">
  uniform float time;
  attribute vec3 customColor;
  varying vec3 vColor;
  //	Simplex 4D Noise
  //	by Ian McEwan, Ashima Arts
  //
  vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
  float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));}
  vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
  float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;}

  vec4 grad4(float j, vec4 ip){
    const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
    vec4 p,s;

    p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
    p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
    s = vec4(lessThan(p, vec4(0.0)));
    p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;

    return p;
  }

  float snoise(vec4 v){
    const vec2  C = vec2( 0.138196601125010504,  // (5 - sqrt(5))/20  G4
                          0.309016994374947451); // (sqrt(5) - 1)/4   F4
  // First corner
    vec4 i  = floor(v + dot(v, C.yyyy) );
    vec4 x0 = v -   i + dot(i, C.xxxx);

  // Other corners

  // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
    vec4 i0;

    vec3 isX = step( x0.yzw, x0.xxx );
    vec3 isYZ = step( x0.zww, x0.yyz );
  //  i0.x = dot( isX, vec3( 1.0 ) );
    i0.x = isX.x + isX.y + isX.z;
    i0.yzw = 1.0 - isX;

  //  i0.y += dot( isYZ.xy, vec2( 1.0 ) );
    i0.y += isYZ.x + isYZ.y;
    i0.zw += 1.0 - isYZ.xy;

    i0.z += isYZ.z;
    i0.w += 1.0 - isYZ.z;

    // i0 now contains the unique values 0,1,2,3 in each channel
    vec4 i3 = clamp( i0, 0.0, 1.0 );
    vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
    vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );

    //  x0 = x0 - 0.0 + 0.0 * C
    vec4 x1 = x0 - i1 + 1.0 * C.xxxx;
    vec4 x2 = x0 - i2 + 2.0 * C.xxxx;
    vec4 x3 = x0 - i3 + 3.0 * C.xxxx;
    vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;

  // Permutations
    i = mod(i, 289.0);
    float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);
    vec4 j1 = permute( permute( permute( permute (
                i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
              + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
              + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
              + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));
  // Gradients
  // ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)
  // 7*7*6 = 294, which is close to the ring size 17*17 = 289.

    vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;

    vec4 p0 = grad4(j0,   ip);
    vec4 p1 = grad4(j1.x, ip);
    vec4 p2 = grad4(j1.y, ip);
    vec4 p3 = grad4(j1.z, ip);
    vec4 p4 = grad4(j1.w, ip);

  // Normalise gradients
    vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
    p0 *= norm.x;
    p1 *= norm.y;
    p2 *= norm.z;
    p3 *= norm.w;
    p4 *= taylorInvSqrt(dot(p4,p4));

  // Mix contributions from the five corners
    vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
    vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4)            ), 0.0);
    m0 = m0 * m0;
    m1 = m1 * m1;
    return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
                  + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;

  }
  void main() {
      vColor = customColor;
      vec3 p = position;
      float r = snoise(vec4(p*0.015, time*0.0005));
      p.y += p.y*r*0.1;
      p.x += p.x*r*0.1;
      p.z += p.z*r*0.1;
      vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
      gl_PointSize = 10. * (100.0/-mvPosition.z);
      gl_Position = projectionMatrix * mvPosition;
  }
</script>

<script type="x-shader/x-fragment" id="fragment-shader">
  varying vec3 vColor;
  void main() {
      gl_FragColor = vec4(vColor, 0.1);
  }
</script>
body {
  margin: 0;
  padding: 0;
  height: 100vh;
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #000;
}
View Compiled
const params = {
  exposure: 1,
  bloomStrength: 0.87,
  bloomThreshold: 0,
  bloomRadius: 0.26
};
const { min, PI, sqrt, cos, sin, pow, floor } = Math;
const range = (n) =>
  Array(n)
    .fill(0)
    .map((i, j) => i + j);

const sum = (arr) => arr.reduce((acc, cur) => acc + cur, 0);
const slicedSum = (arr, i) => sum(arr.slice(0, i));
const pointsOnSphere = (n) => {
  const pts = [];
  const inc = PI * (3 - sqrt(5));
  const off = 2 / n;
  range(n).forEach((i) => {
    const y = i * off - 1 + off / 2;
    const r = sqrt(1 - y * y);
    const phi = i * inc;
    const x = cos(phi) * r;
    const z = sin(phi) * r;
    pts.push([x, y, z]);
  });
  return pts;
};

const numMap = (value, sMin, sMax, dMin, dMax) => {
  return dMin + ((value - sMin) / (sMax - sMin)) * (dMax - dMin);
};

const colArray = [0xed2225, 0xf99621, 0xf1eb1b, 0x0c9b49, 0x3954a5, 0x93298e];
colArray.reverse();
let camera, controls, scene, renderer, cloud, composer, bloomPass, meshPlanet;
const uniforms = {
  time: { type: "f", value: 1.0 }
};

let { innerWidth, innerHeight } = window;
let canvasSize = min(innerWidth, innerHeight);

init();
animate();

function init() {
  scene = new THREE.Scene();

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(canvasSize, canvasSize);
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
  camera.position.set(128, 90, 474);

  controls = new THREE.OrbitControls(camera, renderer.domElement);

  const ambientLight = new THREE.AmbientLight(0x666666);
  scene.add(ambientLight);

  const renderScene = new THREE.RenderPass(scene, camera);

  bloomPass = new THREE.UnrealBloomPass(
    new THREE.Vector2(window.innerWidth, window.innerHeight),
    1.5,
    0.4,
    0.85
  );
  bloomPass.threshold = params.bloomThreshold;
  bloomPass.strength = params.bloomStrength;
  bloomPass.radius = params.bloomRadius;
  composer = new THREE.EffectComposer(renderer);
  composer.addPass(renderScene);
  composer.addPass(bloomPass);
  createObjects();
  createGlobe();
  window.addEventListener("resize", onWindowResize, false);
}

function onWindowResize() {
  camera.aspect = 1;
  camera.updateProjectionMatrix();
  innerWidth = window.innerWidth;
  innerHeight = window.innerHeight;
  canvasSize = min(innerWidth, innerHeight);
  composer.setSize(canvasSize, canvasSize);
}

function animate(time) {
  uniforms.time.value = time;
  meshPlanet.rotation.y -= 0.006;
  requestAnimationFrame(animate);
  render();
}

function render() {
  composer.render();
}

function createObjects() {
  const layers = range(6).map((i) => canvasSize * pow(2, i + 1));
  layers.reverse();
  const amount = sum(layers);
  const positions = new Float32Array(amount * 3);
  const colors = new Float32Array(amount * 3);
  const vertex = new THREE.Vector3();
  layers.forEach((layer, layerIndex) => {
    const points = pointsOnSphere(layer);
    points.forEach(([x, y, z], pointIndex) => {
      const index = slicedSum(layers, layerIndex) + pointIndex;
      const color = new THREE.Color(
        colArray[floor(numMap(pointIndex, 0, layer, 0, colArray.length))]
      );
      const radius = 140 + numMap(layerIndex, 0, layers.length, 0, 120);
      vertex.x = radius * x;
      vertex.y = radius * y;
      vertex.z = radius * z;
      vertex.toArray(positions, index * 3);
      color.toArray(colors, index * 3);
    });
  });

  const geometry = new THREE.BufferGeometry();
  geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
  geometry.setAttribute("customColor", new THREE.BufferAttribute(colors, 3));

  const material = new THREE.ShaderMaterial({
    uniforms,
    vertexShader: document.querySelector("#vertex-shader").textContent,
    fragmentShader: document.querySelector("#fragment-shader").textContent,
    blending: THREE.AdditiveBlending,
    depthTest: false,
    transparent: true
  });
  cloud = new THREE.Points(geometry, material);
  scene.add(cloud);
}

function createGlobe() {
  const textureLoader = new THREE.TextureLoader();
  const radius = 100;
  const tilt = 0.409105177;
  const materialNormalMap = new THREE.MeshPhongMaterial({
    specular: 0x333333,
    shininess: 1,
    map: textureLoader.load("https://assets.codepen.io/3685267/earth.jpg"),
    normalScale: new THREE.Vector2(0.85, -0.85)
  });
  const geometry = new THREE.SphereBufferGeometry(radius, 100, 50);
  meshPlanet = new THREE.Mesh(geometry, materialNormalMap);
  meshPlanet.rotation.y = 0;
  meshPlanet.rotation.z = tilt;
  scene.add(meshPlanet);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.