← All elements

Nebula

Particles

A soft drifting cloud of cyan, magenta, and violet points that glows like a nebula.

Usage
Install: three @react-three/fiber @react-three/drei
Drop <Nebula /> inside your own <Canvas>.
Mood
Ambient, cosmic, calm. Deep-space atmosphere behind the content.
Colors
A mix of cyan, magenta, and violet points blended additively so they bloom into soft colored glow.
Motion
The whole cloud drifts and rotates very slowly.
View component source
import { useMemo, useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
import type { Points } from 'three';

const N = 2200;
function rand(seed: number) {
  const x = Math.sin(seed) * 43758.5453;
  return x - Math.floor(x);
}

export default function Nebula({ scale = 1 }: { color?: string; scale?: number }) {
  const ref = useRef<Points>(null);

  const { positions, colors } = useMemo(() => {
    const pos = new Float32Array(N * 3);
    const col = new Float32Array(N * 3);
    const palette = [new THREE.Color('#22e0ff'), new THREE.Color('#ff2fd0'), new THREE.Color('#8a5cff')];
    for (let i = 0; i < N; i++) {
      const r = Math.pow(rand(i * 1.1 + 0.3), 0.6);
      const th = rand(i * 2.3 + 1.1) * Math.PI * 2;
      const ph = Math.acos(2 * rand(i * 3.7 + 2.2) - 1);
      // wide, shallow cloud that reads well behind hero text
      pos[i * 3] = Math.sin(ph) * Math.cos(th) * r * 3.4;
      pos[i * 3 + 1] = Math.sin(ph) * Math.sin(th) * r * 1.9;
      pos[i * 3 + 2] = Math.cos(ph) * r * 2.2;
      const c = palette[Math.floor(rand(i * 5.9 + 0.7) * palette.length) % palette.length];
      col[i * 3] = c.r;
      col[i * 3 + 1] = c.g;
      col[i * 3 + 2] = c.b;
    }
    return { positions: pos, colors: col };
  }, []);

  useFrame((state) => {
    if (ref.current) ref.current.rotation.y = state.clock.elapsedTime * 0.04;
  });

  return (
    <points ref={ref} scale={scale}>
      <bufferGeometry>
        <bufferAttribute attach="attributes-position" args={[positions, 3]} />
        <bufferAttribute attach="attributes-color" args={[colors, 3]} />
      </bufferGeometry>
      <pointsMaterial
        size={0.055}
        sizeAttenuation
        vertexColors
        transparent
        opacity={0.85}
        blending={THREE.AdditiveBlending}
        depthWrite={false}
        toneMapped={false}
      />
    </points>
  );
}