npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@junhoyeo/blackhole

v1.0.2

Published

Real-time Schwarzschild blackhole visualization with gravitational lensing

Downloads

85

Readme

Blackhole

npm version npm downloads

Real-time Schwarzschild blackhole visualization demo with gravitational lensing, accretion disk, and relativistic effects.

Blackhole Demo

Installation

npm install @junhoyeo/blackhole three

Features

  • Gravitational Lensing: Ray marching along Schwarzschild geodesics
  • Accretion Disk: Thin disk model with temperature gradient and texture support
  • Relativistic Doppler Shift: Color shift based on relative velocity
  • Relativistic Beaming: Intensity boost from approaching matter
  • Lorentz Transform: Light aberration from observer motion
  • Orbital Camera: Stable circular orbit around the black hole
  • Bloom Effect: Integrated post-processing for realistic glow
  • React Support: Drop-in React components

Usage

Vanilla Three.js

import { BlackholeRenderer } from '@junhoyeo/blackhole';

const renderer = new BlackholeRenderer({
  canvas: document.getElementById('canvas'),
  quality: 'medium',
  cameraDistance: 10,
  fieldOfView: 90,
  enableOrbit: true,
  showAccretionDisk: true,
  useDiskTexture: true,
  enableLorentzTransform: true,
  enableDopplerShift: true,
  enableBeaming: true,
  bloomStrength: 0.5,
  bloomRadius: 0.3,
  bloomThreshold: 0.8,
  // Optional textures
  backgroundTextureUrl: '/assets/milkyway.jpg',
  starTextureUrl: '/assets/star_noise.png',
  diskTextureUrl: '/assets/accretion_disk.png',
});

renderer.start();

React

Basic Background

import { BlackholeBackground } from '@junhoyeo/blackhole';

function App() {
  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <BlackholeBackground
        quality="medium"
        cameraDistance={10}
        enableOrbit={true}
        backgroundTextureUrl="/assets/milkyway.jpg"
      />
    </div>
  );
}

Full-screen Section

The package exports a helper HeroSection component for easily creating full-screen sections.

import { HeroSection } from '@junhoyeo/blackhole';

function LandingPage() {
  return (
    <HeroSection
      blackholeProps={{
        quality: 'high',
        enableOrbit: true,
      }}
    >
      <div className="content">
        <h1>Welcome to the Event Horizon</h1>
        <p>Experience gravity like never before.</p>
      </div>
    </HeroSection>
  );
}

Next.js

For Next.js, use dynamic imports with SSR disabled (the renderer requires browser APIs):

import dynamic from 'next/dynamic';

const BlackholeBackground = dynamic(
  () => import('@junhoyeo/blackhole').then((mod) => mod.BlackholeBackground),
  { ssr: false }
);

export default function Page() {
  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <BlackholeBackground
        quality="medium"
        enableOrbit={true}
        backgroundTextureUrl="/milkyway.jpg"
      />
    </div>
  );
}

Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | quality | 'low' \| 'medium' \| 'high' \| 'ultra' | 'medium' | Ray marching quality preset | | cameraDistance | number | 10 | Distance from black hole (Schwarzschild radii) | | fieldOfView | number | 90 | Camera FOV in degrees | | enableOrbit | boolean | true | Enable orbital camera motion | | orbitSpeed | number | 0.15 | Orbital angular velocity (rad/s) | | showAccretionDisk | boolean | true | Show accretion disk | | useDiskTexture | boolean | true | Use texture for disk instead of procedural blackbody | | enableLorentzTransform | boolean | true | Enable light aberration | | enableDopplerShift | boolean | true | Enable Doppler color shift | | enableBeaming | boolean | true | Enable relativistic beaming | | bloomStrength | number | 0.5 | Bloom post-process strength | | bloomRadius | number | 0.3 | Bloom radius | | bloomThreshold | number | 0.8 | Bloom threshold | | backgroundTextureUrl | string | "" | URL for background environment map | | starTextureUrl | string | "" | URL for star field data texture | | diskTextureUrl | string | "" | URL for accretion disk texture | | resolutionScale | number | 1.0 | Resolution scale factor (0.5 for half res) |

Development

git clone https://github.com/junhoyeo/blackhole.git
cd blackhole
npm install
npm run dev

Physics Background

Schwarzschild Metric

The Schwarzschild solution describes spacetime geometry around a non-rotating, uncharged black hole:

ds² = -(1 - rs/r)dt² + (1 - rs/r)⁻¹dr² + r²dΩ²

where rs = 2GM/c² is the Schwarzschild radius.

Geodesic Ray Marching

Light follows null geodesics in curved spacetime. The effective potential for photon orbits:

V_eff(r) = (1 - rs/r) * L²/r²

The photon sphere exists at r = 1.5 * rs where light can orbit the black hole.

Relativistic Effects

  • Doppler Factor: δ = 1 / (γ(1 - β·n)) where β = v/c
  • Beaming: Intensity scales as δ⁴ for isotropic emission
  • Aberration: Light direction transforms under Lorentz boost

References

Papers & Textbooks

  1. Schwarzschild, K. (1916). "Über das Gravitationsfeld eines Massenpunktes nach der Einsteinschen Theorie"
  2. Luminet, J.-P. (1979). "Image of a spherical black hole with thin accretion disk". Astronomy and Astrophysics, 75, 228-235
  3. Misner, C. W., Thorne, K. S., & Wheeler, J. A. (1973). "Gravitation". W. H. Freeman
  4. James, O., et al. (2015). "Gravitational lensing by spinning black holes in astrophysics, and in the movie Interstellar". Classical and Quantum Gravity, 32(6)

Online Resources

Inspiration

This project was inspired by vlwkaos/threejs-blackhole. This is a clean-room Apache 2.0 licensed reimplementation based on the same underlying physics (which is public domain knowledge), with independently written code.

License

Apache License 2.0 - See LICENSE for details.

Author

Junho Yeo