
The dash relief
WebGL, 3D, Hover
Free
A minimal-style WebGL animation: a single sphere drawn in one bit, with square dots of ink like a newspaper halftone, lit by a light that follows the pointer. Parallels and meridians turn slowly, the shadow slides away from the light and only the highlight turns blue.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Nadir</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/jost@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- one sphere drawn in one bit: a WebGL shader lights it like a ball and an 8x8 Bayer matrix turns the light into
big square dots of ink; the light follows the pointer, and when nobody moves it, it walks around the sphere -->
<main class="pagina" data-pagina>
<canvas class="tela" aria-hidden="true" data-tela></canvas>
<header class="testa">
<p class="marchio" data-entra>Nadir</p>
<p class="testa__nota" data-entra>A study of light</p>
</header>
<p class="nota" data-entra data-nota>Move the light</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
16 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The dithered sphere” from Animorio and fit it into my siteThe whole page is a WebGL canvas with a single square covering it (two triangles in a TRIANGLE_STRIP) and a fragment shader that decides the colour of each pixel. The pixel is not worked out for itself: it is rounded to its halftone cell, floor(gl_FragCoord.xy / u_dot), and the sum is done at the centre of the cell. So every pixel in a cell comes out the same and the halftone dots are squares DOT CSS pixels wide, even with devicePixelRatio at 2.
In the cell we look at the distance from the centre of the sphere in radii: if it is less than one, the surface normal is (x, y, the square root of 1 minus x² minus y²). The light is a direction: the pointer gives x and y in sphere radii and LIGHT_HEIGHT gives z. Lambert light is the dot product of normal and light, the highlight is Blinn-Phong, the normal against the halfway vector between light and eye raised to SHINE. The grey is a number from 0 (black) to 1 (paper).
The grey becomes a dot or no dot by comparing it with a threshold that changes from cell to cell according to the 8x8 Bayer matrix, worked out in the shader with a recursive formula: bayer2 on a.x and a.y, then bayer4 and bayer8 that add the same formula at half scale. With 64 different thresholds a mid grey becomes a checkerboard, a light one a dot here and there. The strongest highlight, above its own threshold, turns blue instead of paper.
The normal is turned around the vertical axis by an angle that grows with the round, and its longitude and latitude are taken: where either falls near a whole number there is a line. The line darkens the grey where the sphere is lit and lightens it where it is in shadow, so it shows on both sides. Outside the sphere there is a flattened ellipse beneath it, moved to the side away from the light, which darkens the paper on a soft curve: the shadow goes through the halftone too.
An object of numbers, fase and nasce, is animated by GSAP: fase goes from 0 to 1 in LIGHT_SPEED seconds in a repeating timeline, and from it come the light's round when nobody moves the pointer, the turning of the meridians and the breathing of the radius, all with periods that come back whole. The real light chases its point with a measured spring on GSAP's ticker; after 2.4 seconds without a pointer it goes back to the round. An IntersectionObserver switches everything off when the page is not visible. Without WebGL the same sum is done in JavaScript on a 2D canvas.
| Name | File | Default | What it changes |
|---|---|---|---|
DOT | script.js | 4 | The side of a halftone dot, in px: bigger shows more grain. |
BAYER_SIZE | script.js | 8 | The Bayer matrix, 2, 4 or 8: bigger gives more shades of grey. |
RADIUS | script.js | 0.3 | The radius of the sphere, as a share of the page's shorter side. |
LIGHT_SPEED | script.js | 14 | How many seconds the light takes for a full round on its own. |
LIGHT_HEIGHT | script.js | 0.9 | How far in front of the sphere the light sits: higher, less shadow. |
SHINE | script.js | 26 | How tight the blue highlight is: higher, smaller. |
LINES | script.js | 12 | How many meridians (the parallels are half as many). |
BREATH | script.js | 0.012 | How much the sphere's radius breathes. |
SHADOW | script.js | 0.5 | How dark the shadow under the sphere is. |
As the opening of an observatory, a lab, a photography or print studio, a product about light, energy or space; as the landing page of a data app or a developer tool when you want a strong image made with very little; as the background of a page for a conference on graphics.
The same animation: the sphere is sized on the shorter side (a little bigger on narrow screens), a finger that touches and drags moves the light, and as soon as it lifts the light goes back to its round.
The sphere is already developed and still, with the light at the top left: no round, no breathing, no turning meridians. The name and the small lines fade in.
GSAP 3.15.0, Jost (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.5 KB; the libraries: GSAP 28 KB.
Tested on 21 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.