Imported library

← Imported library
Free sampleMIT licence

Fresnel orb hero background (MeshPhysicalMaterial sphere, additive fresnel shell, orbiting light)

3d scene

3d scene from AleBrito124356/threejs-hero-collection.

From prompt to live site

  1. 01

    Copy the code

    Grab every file as one text, each carrying its licence notice.

  2. 02

    Paste into your AI

    Drop it into Claude, Cursor or v0 — or straight into your own project.

  3. 03

    Launch it live

    Adapt the copy, wire your data, and ship — with the notice kept alongside.

Read the full code
Fresnel orb hero background (MeshPhysicalMaterial sphere, additive fresnel shell, orbiting light)
AleBrito124356/threejs-hero-collection@08e9325ce258 · 1 code file(s)

Licence notice — required by the licence; keep it with this code:

MIT License

Copyright (c) 2026 Alejandro Brito

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

--- orb.html ---
<!DOCTYPE html>
<!--
MIT License

Copyright (c) 2026 Alejandro Brito

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fresnel orb hero — threejs-hero-collection</title>
<style>
  :root {
    --bg: #0A0D14;
    --border: #1E293B;
    --accent: #2563EB;
    --accent-2: #38BDF8;
    --text: #F1F5F9;
    --body: #94A3B8;
    --muted: #64748B;
    --mono: 'Cascadia Code', Consolas, Menlo, monospace;
  }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  html, body { height: 100%; }
  body {
    background: var(--bg);
    color: var(--body);
    font-family: -apple-system, 'Segoe UI', Inter, Roboto, sans-serif;
    line-height: 1.6;
    overflow-x: hidden;
  }
  #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; }

  .site-header {
    position: fixed; top: 0; left: 0; right: 0; z-index: 2;
    display: flex; align-items: baseline; gap: 16px;
    padding: 14px 24px;
    background: rgba(10, 13, 20, 0.72);
    border-bottom: 1px solid var(--border);
  }
  .site-header .repo { font-family: var(--mono); color: var(--accent-2); text-decoration: none; font-weight: 600; }
  .site-header .tag { color: var(--muted); font-size: 0.85rem; flex: 1; min-width: 0;
                      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .site-header nav { display: flex; gap: 14px; }
  .site-header nav a { color: var(--body); text-decoration: none; font-size: 0.85rem; }
  .site-header nav a:hover { color: var(--accent-2); }

  .hero {
    position: relative; z-index: 1;
    min-height: 100vh;
    display: flex; flex-direction: column; justify-content: center; align-items: center;
    text-align: center; padding: 96px 24px 64px;
  }
  .hero h1 {
    color: var(--text);
    font-size: clamp(2rem, 6vw, 3.6rem);
    font-weight: 700; letter-spacing: -0.02em; line-height: 1.1;
    max-width: 720px;
    text-shadow: 0 2px 24px rgba(10, 13, 20, 0.8);
  }
  .hero p {
    margin-top: 18px; max-width: 560px; font-size: 1.05rem;
    text-shadow: 0 1px 12px rgba(10, 13, 20, 0.8);
  }
  .cta {
    margin-top: 32px; display: inline-block;
    padding: 12px 28px; border-radius: 8px;
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    color: #fff; text-decoration: none; font-weight: 600; font-size: 0.95rem;
    transition: filter 0.2s ease, transform 0.2s ease;
  }
  .cta:hover { filter: brightness(1.12); transform: translateY(-1px); }
  a:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 3px; }

  @media (prefers-reduced-motion: reduce) {
    .cta { transition: none; }
    .cta:hover { transform: none; }
  }
  @media (max-width: 480px) {
    .site-header .tag { display: none; }
  }
</style>

<!-- The ONLY external dependency of this repo: three.js, pinned to 0.170.0.
     To self-host, download three.module.js and point this import map at it. -->
<script type="importmap">
{
  "imports": {
    "three": "https://unpkg.com/three@0.170.0/build/three.module.js"
  }
}
</script>
</head>
<body>
<header class="site-header">
  <a class="repo" href="index.html">threejs-hero-collection</a>
  <span class="tag">Drop-in animated hero backgrounds built with Three.js</span>
  <nav aria-label="Repository links">
    <a href="index.html">All heroes</a>
    <a href="https://github.com/AleBrito124356/threejs-hero-collection">GitHub</a>
  </nav>
</header>

<canvas id="scene" aria-hidden="true"></canvas>

<main class="hero">
  <h1>One orb, zero assets</h1>
  <p>A physical-material sphere lit by an orbiting point light, wrapped in an additive fresnel shell — every photon computed, nothing downloaded.</p>
  <a class="cta" href="https://github.com/AleBrito124356/threejs-hero-collection">Grab the file</a>
</main>

<script type="module">
import * as THREE from 'three';

/* =============================== customize =============================== */
const COLORS = {
  background: '#0A0D14',
  orbSurface: '#0F1626',   // the sphere's base color (near-black blue)
  rim:        '#38BDF8',   // fresnel edge glow
  light:      '#60A5FA',   // orbiting point light
  skyFill:    '#1E293B',   // hemisphere fill from above
  groundFill: '#0A0D14',   // hemisphere fill from below
};
const ORB_RADIUS = 1.35;
const ROTATION_SPEED = 0.12;   // radians per second
const ORBIT_SPEED = 0.5;       // of the light, radians per second
const ORBIT_RADIUS = 3.2;
const RIM_STRENGTH = 1.1;      // fresnel shell intensity
/* ========================================================================= */

const canvas = document.getElementById('scene');
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
// DPR cap: see README "Performance notes".
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(window.innerWidth, window.innerHeight);

const scene = new THREE.Scene();
scene.background = new THREE.Color(COLORS.background);

const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 50);
camera.position.set(0, 0.2, 4.6);
camera.lookAt(0, 0, 0);

/* --- The orb -------------------------------------------------------------
   MeshPhysicalMaterial gives us clearcoat: a thin glossy layer over the
   base surface, so the orbiting light draws a tight specular streak across
   the sphere — the "lacquered" look. A touch of transmission lets the rim
   read as glassy without needing an environment map.                     */
const orbGeometry = new THREE.IcosahedronGeometry(ORB_RADIUS, 5); // 5 = smooth silhouette
const orbMaterial = new THREE.MeshPhysicalMaterial({
  color: new THREE.Color(COLORS.orbSurface),
  roughness: 0.22,
  metalness: 0.35,
  clearcoat: 1.0,
  clearcoatRoughness: 0.25,
  transmission: 0.25,   // subtle glassiness; higher values need an env map
  thickness: 1.2,
  ior: 1.4
});
const orb = new THREE.Mesh(orbGeometry, orbMaterial);
scene.add(orb);

/* --- Fresnel shell -------------------------------------------------------
   Fresnel = surfaces reflect more light at grazing angles. We fake it with
   the view/normal angle: dot(view, normal) is ~1 at the sphere's center
   (facing us) and ~0 at the silhouette. pow(1 - dot, 3) therefore glows
   ONLY at the edges. Drawn on a slightly larger sphere with additive
   blending so it reads as atmosphere, not paint.                         */
const shellMaterial = new THREE.ShaderMaterial({
  uniforms: {
    uRim:      { value: new THREE.Color(COLORS.rim) },
    uStrength: { value: RIM_STRENGTH },
  },
  vertexShader: /* glsl */`
    varying vec3 vNormal;
    varying vec3 vView;
    void main() {
      // Both vectors in view space so the rim tracks the camera for free.
      vNormal = normalize(normalMatrix * normal);
      vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
      vView = normalize(-mvPosition.xyz);   // fragment -> camera direction
      gl_Position = projectionMatrix * mvPosition;
    }
  `,
  fragmentShader: /* glsl */`
    uniform vec3 uRim;
    uniform float uStrength;
    varying vec3 vNormal;
    varying vec3 vView;
    void main() {
      float fresnel = pow(1.0 - abs(dot(vNormal, vView)), 3.0);
      gl_FragColor = vec4(uRim, fresnel * uStrength);
    }
  `,
  transparent: true,
  blending: THREE.AdditiveBlending,
  depthWrite: false   // the shell must never occlude the orb beneath it
});
const shell = new THREE.Mesh(new THREE.SphereGeometry(ORB_RADIUS * 1.03, 64, 64), shellMaterial);
scene.add(shell);

/* --- Lights --------------------------------------------------------------
   One orbiting point light does the drama; a dim hemisphere light keeps
   the dark side from collapsing to pure black. A tiny emissive speck rides
   on the light's position so the viewer can SEE the light source.        */
const orbitLight = new THREE.PointLight(new THREE.Color(COLORS.light), 40, 0, 2);
scene.add(orbitLight);

const speck = new THREE.Mesh(
  new THREE.SphereGeometry(0.045, 16, 16),
  new THREE.MeshBasicMaterial({ color: new THREE.Color(COLORS.light) })
);
scene.add(speck);

scene.add(new THREE.HemisphereLight(
  new THREE.Color(COLORS.skyFill), new THREE.Color(COLORS.groundFill), 0.8
));

function update(delta, elapsed) {
  // Slow spin: enough to catch the light differently over time, slow
  // enough to stay out of the reader's way.
  orb.rotation.y = elapsed * ROTATION_SPEED;
  orb.rotation.x = Math.sin(elapsed * 0.07) * 0.15;

  // The light orbits on a tilted ellipse; the vertical bob keeps the
  // specular streak wandering instead of tracing the same circle forever.
  const a = elapsed * ORBIT_SPEED;
  orbitLight.position.set(
    Math.cos(a) * ORBIT_RADIUS,
    Math.sin(a * 0.7) * 1.4,
    Math.sin(a) * ORBIT_RADIUS * 0.6 + 1.2
  );
  speck.position.copy(orbitLight.position);

  // Gentle float sells "weightless" better than any rotation could.
  const bob = Math.sin(elapsed * 0.6) * 0.07;
  orb.position.y = bob;
  shell.position.y = bob;
}

/* --- Render loop: DPR-capped, pauses when hidden, static under
       prefers-reduced-motion. This block is identical in every hero. ------ */
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
let rafId = null;
let last = null;
let elapsed = 0;

function frame(now) {
  if (last === null) last = now;
  const delta = Math.min((now - last) / 1000, 0.1);
  last = now;
  elapsed += delta;

  update(delta, elapsed);
  renderer.render(scene, camera);
  rafId = requestAnimationFrame(frame);
}

function start() {
  if (rafId === null && !reducedMotion.matches && !document.hidden) {
    last = null;
    rafId = requestAnimationFrame(frame);
  }
}
function stop() {
  if (rafId !== null) { cancelAnimationFrame(rafId); rafId = null; }
}

// Reduced motion: place the light at a flattering angle and render once.
function renderStatic() {
  update(0, 1.2);
  renderer.render(scene, camera);
}

document.addEventListener('visibilitychange', () => {
  if (document.hidden) stop(); else start();
});
reducedMotion.addEventListener('change', () => {
  if (reducedMotion.matches) { stop(); renderStatic(); } else { start(); }
});
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  if (reducedMotion.matches) renderStatic();
});

/* SPA embedding? Dispose on unmount: orbGeometry.dispose(),
   orbMaterial.dispose(), shellMaterial.dispose(), renderer.dispose().    */

if (reducedMotion.matches) renderStatic(); else start();
</script>
</body>
</html>
Source and licence

Source: AleBrito124356/threejs-hero-collection@08e9325ce258

Author: 2026 Alejandro Brito

Entry: orb.html

  • loads three.js from unpkg.com via import map (README recommends self-hosting)
  • hero copy links back to github.com/AleBrito124356/threejs-hero-collection
MIT License

Copyright (c) 2026 Alejandro Brito

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Files (1)
  • orb.html (10,810 bytes)

Want the whole library?

Every item's prompt, code and instructions, with a CreativePower subscription.

See plans

More 3d scene templates