Logo: Strunz Seitenlogo: Strunz-Design
Auswahl
 Begrüßung
\/Programmieren
 Galerie
 Sonstiges

Coding
 Übersicht
 Albengenerator
\/Demoeffekte
 ICPC
 Links

Demoeffekte
 Übersicht
->Zoomer
 Lasershow
 Vectorballs
 Delayvectors
 

Tutorial & Download "Drehzoomer"

Beschreibung des Effektes

Wo zu sehen?

Dies ist einer meiner Lieblingseffekte, zu sehen in Demos wie Lasse Reinbong von Cubic Team (1995) oder Headache von Statix / Psychic Link. (1996).
Dieser Effekt ist recht rechenaufwendig (In damaligen Dimensionen muss man sagen). Man kann aber schon mit wenigen weiteren Modifikationen (z.B. Palette ändern, Text statt sich bewegender Punkte) sehr unterschiedliche, sehr schön anzusehende Bildersequenzen erzeugen.

Wie wird's gemacht?

Es handelt sich dabei um einen Rückkopplungseffekt, der stark an eine vor einem Fernseher gestellte Videokamera erinnert. Die Idee ist es, einen Ausschnitt des aktuelle Schirmbildes wieder auf Vollbild aufzublähen. Anschliessend geht man mit einem schnellen Weichzeichner (Mittelwertbilder) darüber, um die echigen Pixel, die nach dem Zoomen sichtbar werden, abzurunden. Der Weichzeichner ist zusätzlich noch so eingestellt, daß er bei jedem Schritt die Farbe des Bildes etwas in Richtung Hintergrundfarbe abdunkelt. So entsteht der verschmierende Nebeleffekt. Wenn man nun vor dem Weichzeichner in einem Zwischenschritt eine Figur zeichnet - zum Beispiel einen Pixelschwarm, ein Logo oder ein Drahtgittermodell - dann sieht es aus, als ob das Logo unendlich oft auf dem Bildschirm erscheint, dabei noch brennt und sehr schnell rotiert.
Es erinnert wirklich an die Rückkopplung einer TV-Kamera vor einen Fernseher, wobei man noch Figuren vor den Fernseher halten kann.

Der Effekt gliedert sich in drei voneinander unabhängige Abschnitte, den

  • Zoomer - Stauchung, Streckung, Drehung -> Allgemein die komplette Rückkopplung
  • Weichzeichner - Weichzeichnung des aktuellen Ausschnittes incl. der Farbabdunklung
  • und den Pixelsturm - rückzukoppelndes Objekt. Hier hat man den größten Spielraum zum Experimentieren

Der Pixelsturm

Der Pixelsturm ist der einfachste Teileffekt. Es handelt sich dabei einfach um 100 voneinander unabhängiger Punkte, die auf ellipsenförmigen Bahnen über den Bildschirm bewegt werden.

Ein einfaches Array aus 100 Pixeln (X- und Y-Koordinaten eintragen) in Verbindung mit etwas Sinus-Kosinusspielerei wirkt hier schon Wunder. Wie ein sich bewegender Mückenschwarm.
Man bewegt die Punkte nun in jedem neuen zu zeichnenden Bild ein Stückchen weiter und zeichnet sie dann auf dem Schirm. Fertig! Sehr gut machen sich auch einfache Textscroller oder einfach nur über den Bildschirm bewegte Grafiken.

Der Weichzeichner

Dieses Hilfsmittel entspringt in dieser Form einem anderen Effekt, der als "brennender Bildschirm" bekannt ist. Um den Farbwert eines Pixels zu bestimmen, nimmt man einfach den Mittelwert der vier (oder besser: acht) direkt benachbarten Pixel. Die erhaltene Zahl wird noch um eins reduziert, und schon ist der abdunkelnde Weichzeichner fertig.

Vom Prinzip her einfach zu realisieren, jedoch entpuppt es sich als die größte Bremse im Programm. Verbraucht pro Pixel vier Addition von vier Farbwerten (jeweils ein Byte pro Pixel) und eine Division, die aber durch den Assembler-Befehl "Shift-Right um 2" laufzeitlich entschärf wurde.

Der Rückkoppler

Dieser Effekt ist sehr schwierig zu erklären, und ist das Ergebnis vieler verschiedener Ansätze und Mißversuche. Die Grundidee war, ein beliebiges Rechteck in den Bildschirm zu legen, und dieses genau auf Bildschirmgröß auszudehnen. War aber leider zu unflexiebel. Andere Ansätze sahen dann zwar besser aus, waren aber zu langsam. Es sollte dabei ja keine Diashow, sondern ein in Echtzeit ablaufender Effekt herauskommen.

Die optimale Lösung war dann die Verwendung einer Abbildungsmatrix. Dies funktioniert sehr schnell, und bietet alle Möglichkeiten, um den Zoomeffekt in Echtzeit zu modifizieren. Eine Matrix kann problemlos skalieren (hineinzoomen, herauszoomen) und rotieren. Die Matrix ist konstant für alle Bildpunkte, und braucht nur einmal pro Frame berechnet zu werden. Die Kernschleifen können mit Hilfe von inkrementellen Ansätzen stark optimiert werden.
Mit Hilfe einer solchen Matrix kann man aus jedem Bildpunkt (1.Vektor in Form einer x- und y-Koordinate) einen neuen Bildpunkt (2.Vektor) berechnen. Dieser liegt irgendwo auf dem "alten" Bild, das im letzten Frame berechnet wurde. Dort liest man einen Farbwert und kopiert diesen in das neue Bild an die aktuelle Position.

Alle weiteren Schritte beziehen sich auf auf den sogenannten MCGA-Modus (bekannt als Mode-13hex) mit 320x200 Pixeln und 256 Farben.

Man geht also durch seinen Zielpuffer (Beispielsweise der Bildschirmspeicher beginnend ab mem[$a000:0]), mit der Koordinate (0,0) in der linken, oberen Ecke. Zu Bearbeiten hat man 200 Zeilen mit jeweils 320 Pixeln, was 64000 Matrix-Vektor-Verknüpfungen entspricht. Zu jeder Koordinate erhält man durch die Verknüpfung mit der Matrix eine neue Koordinate, die Quellbildkoordinate.
An dieser Stelle findet man den gesuchten Pixel des Ursprungsbildes. Dieser wird nun einfach ausgelesen und an die aktuelle Position im Zielpuffer geschrieben. Danach kommt der nächste Punkt dran.

Optimierungen
Genau so funktioniert der Effekt, jedoch in einer stark optimierten Form. Hauptansatz nei der Optimierung ist die Matrix-Vektor-Multiplikation. 64000 Vektoren pro Frame sind eine Menge, um sie "zu Fuß" auszurechnen! (Was natürlich ohne Probleme funktioniert! Ist nur recht langsam.).
Die Matrix-Vektor-Verknüpfung bedeutet nichts anderes als:


        x' = a*x + b*y
        y' = c*x + d*y

        mit a,b,c,d   = Matrixelemente (Konstant pro Frame)
        und x  ,y     = Zielbildkoordinaten (akt. Position auf Schirm)
        und x' ,y'    = gesuchte Quellbildkoordinaten (in altem Bild)

  1. Die Matrix ist für alle Koordinaten konstant
  2. Die identischen Ergebnisse der Multiplikationen a*x und c*x tauchen in jeder Zeile für gleiches x wieder auf. (selbe Spalten!)
  3. Die identischen Ergebnisse der Multiplikationen b*y und c*y tauchen in jeder Spalte für gleiches y wieder auf. (selbe Zeilen!)

Warum also keine vorgekauten Tabellen verwenden?
Mache einmal pro Frame:

  1. Berechne a*x für alle x von 0 bis 319; Speichere Ergebnis in Array A[x]
  2. Berechne c*x für alle x von 0 bis 319; Speichere Ergebnis in Array C[x]
  3. Berechne b*y für alle y von 0 bis 199; Speichere Ergebnis in Array B[y]
  4. Berechne d*y für alle y von 0 bis 199; Speichere Ergebnis in Array D[y]
Speicher- und vorallem Rechenaufwand sind hierbei minimal.
Dafür vereinfacht sich aber die Hauptschleife sehr stark:

        x'=A[x] + B[y];
        y'=C[x] + D[y];

Es gibt keine Multiplikationen mehr, und bei zeilenweisem Vorgehen brauchen B[y] und D[y] nur einmal pro Zeile ausgelesen werden (Da y pro zeile ja konstant ist).
Ausserdem liegen die Elemente der Arrays A[x] und C[x] linear (also direkt) hintereinander im Speicher, und können sehr schnell durch einfaches inkrementieren der Speicheradresse ausgelesen werden.

Durch einfache Manipulation der Abbildungsmatrix kann nun die sich fliessend Ändernde Bewegung des Schirmbildes erreicht werden. Auch hierfür bieten sich wieder Sinus-Kosinusspielereien an. Ich verweise dazu aber auf die Quellcodes.
Viel Spass bei Anschauen und Experimentieren...

Programmablauf pro Frame

  1. Zeiche neue "Figur" über vorhandenen Bild in Bildpuffer DEST
  2. Weichzeichnung und umkopieren des Puffers DEST in Bildpuffer SOURCE
  3. Warten auf vertikalen Retrace (Synchonisation mit Elektronenstrahl) und anschliessendes Kopieren von Puffer SOURCE auf den Bildschirm nach mem[$a000:0]
  4. Manipulation der Matrix, Berechnung der Transformationstabellen A[x],B[y],C[x],D[y]
  5. Zoome (Rückkoppler) SOURCE mit Hilfe der Transformationstabellen nach Speicherbereich DEST.
  6. weiter mit Schritt 1.
Anmerkung zu den Puffern SOURCE, DEST und mem[$a000:0]

Es ist viel schneller, aus dem RAM des PC zu lesen, als von der Grafikkarte ab mem[$a000:0]. Es war daher sinnvoll, zwei eigene Puffer im RAM (SOURCE und DEST) zu verwenden, und auf mem[$a000:0] nur einmal pro Frame schreibend zuzugreifen! Genauere Infos in den Quellcodes.

Programminfo

Turbo Pascal (7.0) für Dos, incl. der Kommentare 346 LoC (Lines of Code)
Videomodus: Standard Mode 13h, 320x200 Pixel bei 256 Farben (Palettenmodus)
Großteil des Programmes in Assembler, es wird aber kein externer Assembler-Compiler benötigt.
Geschwindigkeit:
AMD K6-233 mit Synchronisation : 35 Frames pro Sekunde (fps)
AMD K6-233 ohne Synchronisation : 57 Frames pro Sekunde (Max-fps)

Download

Download als ZIP-File: zoomer.zip (9552 Bytes)
Das Paket enthält das ausführbare EXE-File und den Quellcode. Wer also Angst vor Viren hat, kann sich die Programme durch Turbo-Pascal nochmals selbst übersetzen lassen.

Screenshots

Bild des Effektes
Wer hat die Videokamera vor den Fernseher gestellt?
Es ist schwierig, von diesen Screenshots auf die Bilderflut zu schliessen ;-)
Eine Variation mit einer anderen Farbauswahl (Nicht im Paket anthalten)


Seitenanfang

Inhalt und Design von Florian Evers, florian-evers@gmx.de