aths
2002-09-10, 14:03:49
Hier lege ich mal meine letzten Gedanken zum Anti-Aliasing dar:
Gute Anti-Aliasing Subpixelmasken sollten folgende Bedingungen erfüllen:
- Mit jeder beliebigen Subpixelzahl bestmögliche Ergebnisse liefern, auch mit "krummen" (unüblichen) Zahlen wie 3 oder 5
- Pseudozufällig sein
Wie erzeugt man "gute" Zufallsmasken?
Bevor man beginnt, muss festgelegt werden, wofür die Maske gut sein soll. Meines Erachtens ist es wichtig, die EER (edge equivalent resolution) maximal zu steigern. Das bedeutet, auf beiden Achsen (X und Y) eine größtmögliche Zahl an Subpixelpostitionen zu haben, die für eine schön gleichmäßige Glättung am besten auch noch gleichmäßige Abstände zueinander aufweisen.
Ein Beispiel mit 5 Subpixeln. Zunächst wird das Pixel in 5^2 Subpixel zerlegt:
http://www.aths.de/files/aa/Bild1.gif
Nun nimmt man sich die erste Zeile vor. Irgendein Subpixel wird zufällig ausgewählt:
http://www.aths.de/files/aa/Bild2.gif
Diese Position wird außerdem vermerkt. In Zweile Nummer Zwei wird wieder ein Subpixel zufällig ausgewählt. Es darf jedoch nicht die Position des ersten einnehmen:
http://www.aths.de/files/aa/Bild3.gif
Um lästige Kontrollen und Wiederholtes "Würfeln" einer Zufallszahl zu meiden, könnte man hier mit Indizes arbeiten. Wir haben also eine Liste: (1 2 3 4 5). Es wird mit einem fünfseitigem Würfel gewürfelt (= eine Zufallszahl von 1..5 bestimmt). Dieses Subpixel wird genommen, in unserem Falle die 4. Diese Position wird aus der Liste entfernt, so dass sie nun auf (1 2 3 5) verkürzt ist. Es wird dann mit einem vierseitigem Würfel gewürfelt. Mit diesem System wird ausgeschlossen, dass bereits genutzte Positionen erneut zum Tragen kommen. Unser fertiges Muster könnte letztlich so aussehen:
http://www.aths.de/files/aa/Bild4.gif
Multisampling
Nun zur Frage, wie man mit so einer Maske Multisampling durchführen möchte. Das ist gar nicht mal so schwer. Zunächst ist das Triangle Setup natürlich mit 5 Zeilen pro sichtbarer Bildschirmzeile zu machen. Pro Pixel und Zeile kann es nur 4 Möglichkeiten geben:
(1) Das Dreieck ist nicht im Pixel. In diesem Falle wird es beim Triangle Setup gar nicht erst behandelt. Diese Möglichkeit braucht also nicht beachtet werden.
(2) und (3) - Das Dreieck beginnt oder endet in diesem Pixel.
(4) Das Dreieck liegt komplett im Pixel.
In Situation 4 muss einfach der übliche Z-Test gemacht werden. In Situation 2 und 3 muss die Start- bzw. End-Position des Dreiecks mit der Subpixelposition verglichen werden. Danach folgt dann u.U. der Z-Test.
Nun ergibt sich aber auch eine Problematik. Und zwar muss für jedes Frame für jede bestimmte Pixelposition die gleiche Subpixelmaske verwendet werden, da sich ansonsten Fehler bei der Berechnung der Überdeckung ergeben. Die Zufallszahl muss also anhand der Pixelposition bestimmt werden. Nach jedem Frame darf (und sollte) sich die Maske ändern.
Um deutlicher zu werden: Zwei nebeneinanderliegende Pixel sollten selbstverständlich unterschiedliche Subpixelmasken aufweisen, sonst wäre der pseudozufällige Effekt dahin. Bis das Frame fertig gerendet ist, muss aber sicher gestellt werden, dass die gleiche Pixelposition immer die gleiche Maske verwendet.
Auswahl der Zufallszahlen
Ein weiteres Problem ergibt sich bei der Erzeugung der Masken. Für jede Pixelposition eine Maske zu erstellen dauert nicht nur recht lange, sondern wäre auch ziemlich Speicherintensiv. Einfach ein paar vorgefertigte Masken zu nehmen, senkt den pseudozufälligen Effekt. Bei diesem 5-er Muster gibt es immerhin 120 unterschiedliche Möglichkeiten. Bei 8 Subpixeln wären es gar über 40000!
Recht zufällige Bitfolgen, die sich als Zufallszahlen verwenden lassen, sind z.B. mit dem RC4-Algorithmus möglich. Dieser ist recht einfach zu implementieren und liefert ausgehend von einem Startmuster (z.B. Datum und Uhrzeit) ein richtig gutes weißes Bitrauschen. Man könnte dort einfach bestimmte Bitmuster heraus schneiden. Nun folgende Idee:
- Pro Frame werden z.B. 16 unterschiedliche Masken "vorgerendert" und gespeichert.
- Es werden aus dem RC4-Bitstream ein paar Werte ermittelt, die für dieses Frame als Konstanten gespeichert werden (sich aber von Frame zu Frame ändern.)
- (Pixelposition MOD 16) XOR "Konstante" liefert einen Zeiger auf ein vorgerendertes Subpixelmuster.
Das kann auch etwas ausgefeilter geschehen, indem z.B. solche Zufalls-Konstanten pro Zeile erzeugt werden.
Jedenfalls bleibt unterm Strich imo ein sehr brauchbares Anti-Aliasing. Durch die Zufälligkeit wird ein leichtes Bildrauschen erzeugt, was den Realitätsgrad allerdings eher erhöhen als verringern sollte.
Gute Anti-Aliasing Subpixelmasken sollten folgende Bedingungen erfüllen:
- Mit jeder beliebigen Subpixelzahl bestmögliche Ergebnisse liefern, auch mit "krummen" (unüblichen) Zahlen wie 3 oder 5
- Pseudozufällig sein
Wie erzeugt man "gute" Zufallsmasken?
Bevor man beginnt, muss festgelegt werden, wofür die Maske gut sein soll. Meines Erachtens ist es wichtig, die EER (edge equivalent resolution) maximal zu steigern. Das bedeutet, auf beiden Achsen (X und Y) eine größtmögliche Zahl an Subpixelpostitionen zu haben, die für eine schön gleichmäßige Glättung am besten auch noch gleichmäßige Abstände zueinander aufweisen.
Ein Beispiel mit 5 Subpixeln. Zunächst wird das Pixel in 5^2 Subpixel zerlegt:
http://www.aths.de/files/aa/Bild1.gif
Nun nimmt man sich die erste Zeile vor. Irgendein Subpixel wird zufällig ausgewählt:
http://www.aths.de/files/aa/Bild2.gif
Diese Position wird außerdem vermerkt. In Zweile Nummer Zwei wird wieder ein Subpixel zufällig ausgewählt. Es darf jedoch nicht die Position des ersten einnehmen:
http://www.aths.de/files/aa/Bild3.gif
Um lästige Kontrollen und Wiederholtes "Würfeln" einer Zufallszahl zu meiden, könnte man hier mit Indizes arbeiten. Wir haben also eine Liste: (1 2 3 4 5). Es wird mit einem fünfseitigem Würfel gewürfelt (= eine Zufallszahl von 1..5 bestimmt). Dieses Subpixel wird genommen, in unserem Falle die 4. Diese Position wird aus der Liste entfernt, so dass sie nun auf (1 2 3 5) verkürzt ist. Es wird dann mit einem vierseitigem Würfel gewürfelt. Mit diesem System wird ausgeschlossen, dass bereits genutzte Positionen erneut zum Tragen kommen. Unser fertiges Muster könnte letztlich so aussehen:
http://www.aths.de/files/aa/Bild4.gif
Multisampling
Nun zur Frage, wie man mit so einer Maske Multisampling durchführen möchte. Das ist gar nicht mal so schwer. Zunächst ist das Triangle Setup natürlich mit 5 Zeilen pro sichtbarer Bildschirmzeile zu machen. Pro Pixel und Zeile kann es nur 4 Möglichkeiten geben:
(1) Das Dreieck ist nicht im Pixel. In diesem Falle wird es beim Triangle Setup gar nicht erst behandelt. Diese Möglichkeit braucht also nicht beachtet werden.
(2) und (3) - Das Dreieck beginnt oder endet in diesem Pixel.
(4) Das Dreieck liegt komplett im Pixel.
In Situation 4 muss einfach der übliche Z-Test gemacht werden. In Situation 2 und 3 muss die Start- bzw. End-Position des Dreiecks mit der Subpixelposition verglichen werden. Danach folgt dann u.U. der Z-Test.
Nun ergibt sich aber auch eine Problematik. Und zwar muss für jedes Frame für jede bestimmte Pixelposition die gleiche Subpixelmaske verwendet werden, da sich ansonsten Fehler bei der Berechnung der Überdeckung ergeben. Die Zufallszahl muss also anhand der Pixelposition bestimmt werden. Nach jedem Frame darf (und sollte) sich die Maske ändern.
Um deutlicher zu werden: Zwei nebeneinanderliegende Pixel sollten selbstverständlich unterschiedliche Subpixelmasken aufweisen, sonst wäre der pseudozufällige Effekt dahin. Bis das Frame fertig gerendet ist, muss aber sicher gestellt werden, dass die gleiche Pixelposition immer die gleiche Maske verwendet.
Auswahl der Zufallszahlen
Ein weiteres Problem ergibt sich bei der Erzeugung der Masken. Für jede Pixelposition eine Maske zu erstellen dauert nicht nur recht lange, sondern wäre auch ziemlich Speicherintensiv. Einfach ein paar vorgefertigte Masken zu nehmen, senkt den pseudozufälligen Effekt. Bei diesem 5-er Muster gibt es immerhin 120 unterschiedliche Möglichkeiten. Bei 8 Subpixeln wären es gar über 40000!
Recht zufällige Bitfolgen, die sich als Zufallszahlen verwenden lassen, sind z.B. mit dem RC4-Algorithmus möglich. Dieser ist recht einfach zu implementieren und liefert ausgehend von einem Startmuster (z.B. Datum und Uhrzeit) ein richtig gutes weißes Bitrauschen. Man könnte dort einfach bestimmte Bitmuster heraus schneiden. Nun folgende Idee:
- Pro Frame werden z.B. 16 unterschiedliche Masken "vorgerendert" und gespeichert.
- Es werden aus dem RC4-Bitstream ein paar Werte ermittelt, die für dieses Frame als Konstanten gespeichert werden (sich aber von Frame zu Frame ändern.)
- (Pixelposition MOD 16) XOR "Konstante" liefert einen Zeiger auf ein vorgerendertes Subpixelmuster.
Das kann auch etwas ausgefeilter geschehen, indem z.B. solche Zufalls-Konstanten pro Zeile erzeugt werden.
Jedenfalls bleibt unterm Strich imo ein sehr brauchbares Anti-Aliasing. Durch die Zufälligkeit wird ein leichtes Bildrauschen erzeugt, was den Realitätsgrad allerdings eher erhöhen als verringern sollte.