SERIENBEITRAG ·
Ein Schwarzes Loch atmet zur Musik
Wie ein Raymarcher Licht um ein Schwarzes Loch krümmt und zwei live erzeugte Ambient-Stücke Akkretionsscheibe, Sterne, Jets und Kamera dirigieren.

Nach der Partikelmagier-Demo wollte ich herausfinden, ob sich Musik auch ohne Figur erzählen lässt. Keine Hände, die dirigieren, kein Drache als Höhepunkt – nur Licht, Zeit und ein Objekt, dem eigentlich nichts entkommt. So entstand die Ereignishorizont-Demo: ein Schwarzes Loch, dessen Akkretionsscheibe zur Musik pulsiert, dessen Umgebung sich im Build-up zusammenzieht und das am Ende selbst seine leuchtende Scheibe verschluckt.

Der erste Eindruck ist bewusst ruhig. Vor dem Start sind fast nur Sterne zu sehen. Das Loch verrät sich durch ihre Verzerrung, bleibt aber noch eine Ahnung im Dunkeln. Erst mit der Musik zündet die Akkretionsscheibe von innen nach außen. Dunst, Funken und Galaxie erscheinen, während die Kamera aus der Ferne heranfährt. Die Szene beginnt nicht einfach – sie erwacht.
Licht wird zum eigentlichen Material
Ein Schwarzes Loch selbst ist nicht sichtbar. Sichtbar wird nur, was es mit seiner Umgebung macht. Deshalb besteht die zentrale Aufgabe dieser Demo nicht darin, eine dunkle Kugel zu zeichnen, sondern Lichtstrahlen glaubhaft um einen unsichtbaren Schatten zu führen.
Der Shader verfolgt deshalb für jeden Bildpunkt keine gerade Sichtlinie, sondern einen gekrümmten Weg. Ein Lichtstrahl kann die Scheibe dadurch aus ungewohnter Richtung treffen oder nur knapp am Schatten vorbeiziehen. So erscheint die Rückseite der Scheibe gleichzeitig über und unter dem Loch. Auch der dünne Photonenring ist keine aufgesetzte Grafik, sondern entsteht aus Strahlen, die den Schatten besonders eng umrunden.
vec3 pos = uCamPos;
vec3 vel = rd;
float h2 = dot(cross(pos, vel), cross(pos, vel));
for (int i = 0; i < 400; i++) {
if (float(i) >= uSteps) break;
float r = length(pos);
if (r < 1.0) { captured = true; break; }
if (r > 60.0 && dot(pos, vel) > 0.0) break;
float dt = clamp(r < 8.0 ? 0.06 * r : 0.1 * r - 0.32,
0.02, 3.0);
vec3 prev = pos;
vel += (-1.5 * h2 * pos / pow(r, 5.0)) * dt;
pos += vel * dt;
if (prev.y * pos.y < 0.0) {
vec3 hit = mix(prev, pos, prev.y / (prev.y - pos.y));
vec4 disk = diskSample(hit, normalize(vel), travel * uPix);
col += (1.0 - alpha) * disk.rgb;
alpha += (1.0 - alpha) * disk.a;
}
}Die Rechnung ist eine visuelle Näherung, kein astrophysikalischer Simulator. Entscheidend ist, dass sie die charakteristischen Bilder erzeugt: den schwarzen Schatten, die hochgezogene Rückseite der Scheibe und die verzerrte Galaxie dahinter.
Der Weg eines einzelnen Lichtstrahls
Three.js zeichnet zunächst nur ein bildschirmfüllendes Rechteck. Die eigentliche Szene entsteht im Fragment-Shader. JavaScript übergibt Kameraposition, Blickrichtung, Seitenverhältnis und Öffnungswinkel; daraus konstruiert jeder Bildpunkt seinen eigenen Startstrahl. Der Shader verwaltet dafür nur Position und Geschwindigkeit. Eine kleine Beschleunigung verändert die Richtung, anschließend rückt der Strahl um dt vor.
Der Weg endet auf drei Arten. Unterhalb von r = 1 gilt der Strahl als eingefangen. Jenseits von r = 60 darf er abbrechen, sobald er sich wieder vom Loch entfernt. Oder er hat genügend Licht gesammelt und erreicht eine Deckkraft von 0,97. So muss ein Strahl nicht länger gerechnet werden, als sein Ergebnis für das Bild noch einen Unterschied macht.
Die Scheibe ist keine Textur vor dem Schwarzen Loch. Der Shader erkennt, ob ein Schritt die Ebene y = 0 gekreuzt hat, interpoliert den genauen Treffpunkt und fragt dort Dichte, Temperatur, Doppler-Helligkeit und musikalische Wellen ab. Jet, Dunst und der einfallende Stern addieren unterwegs volumetrisches Licht. Nur wenn der Strahl nicht eingefangen wurde, füllt am Ende der Himmel den noch transparenten Rest. Dadurch entstehen Verdeckung, Linsenbild und leuchtende Atmosphäre innerhalb desselben Strahlwegs.
Kamera → gekrümmter Lichtstrahl → Scheibe / Jet / Dunst / Stern
→ Ereignishorizont oder Himmel → Bloom und FarbkorrekturEine Scheibe, die nicht überall gleich leuchtet
Die Akkretionsscheibe besteht aus glühenden, rotierenden Bändern. Ihr Material bewegt sich auf der einen Seite auf die Kamera zu und auf der anderen von ihr weg. Ein vereinfachter Doppler-Effekt macht deshalb eine Hälfte heller und weißer, die andere wärmer und dunkler. Erst diese Asymmetrie gibt der Scheibe ihre räumliche Richtung.
Nahe am Loch werden die Schritte des Raymarchers kleiner. Weiter draußen darf er größere Sprünge machen. Auch in der Nähe der Jets und eines einfallenden Sterns rechnet der Shader feiner. Diese adaptive Schrittweite ist ein Kompromiss: genug Genauigkeit an den Stellen, die das Bild tragen, ohne jeden Strahl über die gesamte Strecke mit maximaler Auflösung zu verfolgen.
Über dem Raymarcher kreisen hunderte Funken nach innen. Sie werden immer schneller und verschwinden im Schatten. Anders als die Galaxie werden sie nicht durch das Gravitationsfeld verzerrt; dafür geben sie der ansonsten sehr glatten Szene eine greifbare Bewegung und zeigen die Richtung des Sogs.
Zwei Stücke entstehen zusammen mit dem Bild
Die Produktionsfassung konzentriert sich auf zwei ruhige Tracks. Beide werden mit Oszillatoren, Filtern, Rauschgeneratoren und Effekten der Web Audio API im Browser erzeugt. Es gibt keine Audiodatei, die lediglich abgespielt wird.
| Track | Tempo | Charakter |
|---|---|---|
| Stille Materie | 80 BPM | Breite Flächen, gestrichene Melodie, E-Piano-Akkorde, Chor im Drop und ein zurückhaltender Herzschlag |
| Lichtbogen | 70 BPM | Weiter Raum, E-Piano-Melodie, langer Build-up, aufsteigende Läufe, Chor und eine warme gestrichene Linie im Drop |
Die Stücke sind absichtlich langsamer als klassische Clubtracks. Das Bild soll nicht auf jedem Sechzehntel hektisch zucken. Es soll atmen. Der Kick ist eher Herzschlag als Schlagzeug, die langen Harmonien lassen Zeit für Kamerafahrten und die leuchtenden Bänder der Scheibe.
Musik wird nicht analysiert, sondern mitkomponiert
Die Demo hört der Musik nicht nachträglich zu. Der Sequencer kennt Takte, Noten und Abschnitte bereits beim Planen des Tons. Neben den eigentlichen Instrumenten legt er Ereignisse wie kick, note, build, drop oder bar in eine Warteschlange. Die Bildregie holt sie passend zur tatsächlichen Audioausgabe ab.
Warum die Audio-Uhr den Takt vorgibt
Der Sequencer arbeitet nicht im Rhythmus von requestAnimationFrame. Ein Timer läuft alle 25 Millisekunden und plant Sechzehntel bis zu 120 Millisekunden im Voraus in die präzise Zeitachse des AudioContext. Derselbe Planungsschritt startet Oszillatoren und Filter und schreibt ein visuelles Ereignis mit identischem Zeitstempel in eine Warteschlange.
const LOOKAHEAD = 0.12;
while (next < audioContext.currentTime + LOOKAHEAD) {
scheduleStep(globalStep, next);
next += secondsPerSixteenth;
}
const playTime = audioContext.currentTime
- (audioContext.outputLatency || 0)
- (audioContext.baseLatency || 0);
while (queue.length && queue[0].t <= playTime) {
director.onEvent(queue.shift());
}Die Bildseite zieht ein Ereignis erst dann aus der Queue, wenn dessen Klang voraussichtlich am Lautsprecher angekommen ist. outputLatency und baseLatency gleichen dabei den Weg durch Browser und Audiogerät aus. Der Renderloop darf dadurch einmal etwas früher oder später laufen, ohne den Drop vor dem hörbaren Einsatz auszulösen. Die Regie übersetzt das Ereignis anschließend in Zustände wie Energie, Hitze, Wellenradius oder Jet-Stärke; erst diese Zustände werden als Shader-Uniforms geglättet an die Grafikkarte weitergegeben.
Track → Sequencer auf der Audio-Uhr ─┬→ Oszillatoren und Filter → Lautsprecher
└→ Ereignis-Queue → Regie → Shader-Uniforms| Musikalisches Ereignis | Wirkung im Bild |
|---|---|
| Kick / Herzschlag | Eine helle Welle läuft durch die Akkretionsscheibe und schiebt ihre Bänder kurz zusammen. |
| Melodieton | Ein Band glüht auf; die Tonhöhe bestimmt seinen Radius. |
| Bass | Scheibe und Dunst atmen langsam. |
| Hats und helle Akzente | Funken und Sterne flackern stärker. |
| Beginn eines Hauptteils | Ein Stern fällt mehrere Takte lang auf einer Spirale nach innen. |
| Build-up | Die Scheibe heizt auf, Sternenlicht wird zum Sog und die Kamera rückt näher. |
| Drop | Jets brechen aus den Polen, eine Gravitationswelle kräuselt das Licht und die Kamera geht in die Nahfahrt. |
Ein Stern fällt genau im richtigen Moment
Zu Beginn wichtiger Abschnitte erscheint ein heller Stern mit einem dünnen Schweif. Seine Bahn ist als Spirale angelegt, deren Radius immer kleiner wird. Während eines Build-ups berechnet die Regie den Start so, dass der Stern genau am Drop im Schatten verschwindet. In diesem Moment läuft ein schmaler Ring am inneren Rand entlang, als würde die Scheibe auf den Einschlag antworten.
Eine zweite, langsamere Bewegung betrifft die Galaxie im Hintergrund. Sie nähert sich dem Loch, wird zur gebogenen Sichel und schließlich fast zum Einsteinring. Danach wird eine neue Galaxie außerhalb des Bildes vorbereitet. Solche Bewegungen sind nicht sofort als Effekt zu erkennen. Sie sorgen eher dafür, dass die Szene auch in ihren ruhigen Phasen nie völlig stillsteht.
Auftakt und Finale gehören zur Komposition
Der Startbildschirm ist kein bloßes Menü vor der eigentlichen Arbeit. Er ist der erste Zustand der Geschichte. Nach der Trackwahl werden Sterne und Licht eingeblendet, die Scheibe entzündet sich und die Kamera kommt näher. Dieser Auftakt dauert ungefähr zehn Sekunden und gibt dem Auge Zeit, das Schwarze Loch zu entdecken.
Im Outro läuft die Bewegung rückwärts, aber nicht einfach als Fade-out. Die Scheibe wird von außen nach innen eingesogen. Funken, Dunst und Galaxie erlöschen, die Kamera fällt in Richtung Schatten und das Bild geht ins Schwarz. Danach kann ein neuer Auftakt beginnen. Auch der Stoppknopf löst dieses Finale aus – nur in einer kurzen, vier Sekunden langen Fassung.
Diese Übergänge waren wichtiger als erwartet. Ohne sie wäre das Schwarze Loch eine eindrucksvolle Endlosschleife. Mit ihnen bekommt es einen Anfang, eine Entwicklung und ein Ende.
Leistung ist Teil der Gestaltung
Raymarching ist rechenintensiv, weil jeder sichtbare Bildpunkt seinen eigenen Weg durch die Szene verfolgt. Auf dem Desktop verwendet die Demo bis zu 170 Schritte pro Strahl und eine Pixeldichte von 1,5. Mobil beginnt sie mit 110 Schritten und geringerer Auflösung. Wenn die Zielbildrate länger unterschritten wird, sinkt die Pixeldichte stufenweise bis 0,5.
In Ruhe rendert die Anwendung mit 30 Bildern pro Sekunde, während Musik und Übergänge auf 60 Bilder zielen. Diese Begrenzung spart Rechenleistung, wenn das Bild kaum Bewegung enthält. Die Qualität ist damit keine feste Zahl, sondern reagiert auf Gerät und Situation.
| Budget | Desktop | Mobil | Wirkung |
|---|---|---|---|
| Schritte pro Lichtstrahl | 170 | 110 | Obergrenze für die Integration des Strahlwegs |
| Start-Pixeldichte | maximal 1,5 | maximal 1,0 × 0,75 | Begrenzt die tatsächlich berechneten Bildpunkte |
| Funken | 700 | 260 | Jeder Funke wird für sein Nachleuchten fünfmal gezeichnet |
| Aktive Bildrate | 60 FPS | 60 FPS | Musik, Übergänge und Interaktion |
| Ruhebildrate | 30 FPS | 30 FPS | Weniger GPU-Last ohne sichtbare Aktion |
Die adaptive Regelung beobachtet nicht nur einen einzelnen langsamen Frame. Liegt ein aktives Bild über längere Zeit oberhalb von 25 Millisekunden und sammelt damit zwei Sekunden Rückstand, reduziert sie die Pixeldichte auf 80 Prozent des vorherigen Werts. Das kann sich bis zur Untergrenze von 0,5 wiederholen. Die Zahl der Raymarching-Schritte bleibt dabei stabil; zuerst wird also räumliche Auflösung geopfert, nicht die Form der Lichtbahnen.
Eine einzelne Welle in der Scheibe kann mehr erzählen als zehn zusätzliche Effekte, wenn sie musikalisch an der richtigen Stelle erscheint.
Was ich aus der Ereignishorizont-Demo mitnehme
Bei der Partikelmagier-Demo war die Figur der Mittelpunkt. Hier musste die Dramaturgie aus viel weniger Elementen entstehen. Gerade deshalb wurden Licht, Timing und Übergänge wichtiger. Eine einzelne Welle in der Scheibe kann mehr erzählen als zehn zusätzliche Effekte, wenn sie musikalisch an der richtigen Stelle erscheint.
Das Experiment hat mir außerdem gezeigt, dass technische Plausibilität und künstlerische Freiheit gut zusammenpassen. Die Lichtablenkung folgt einer nachvollziehbaren Idee, ist aber auf ein Echtzeitbild im Browser zugeschnitten. Musik und Physik sind keine getrennten Demonstrationen. Beide arbeiten an derselben Stimmung: langsam, schwer und unausweichlich.








