(gelöst) Glare-Algorithmus

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Ich pfeife auf die schönen Stacheln und das oszillieren. Jaa, es wirkt in Bewegung super, aber es gibt unüberwindbare Hindernisse (weil das Paper nicht nur bei den Wrap-Arounds arg geschönt ist). Und irgendwann muss ich auch mal weiterkommen. Es bleibt also bei einem statischen Blur mit einer Kernelgröße von 2048² Pixeln … enttäuschend, aber immernoch hübsch anzusehen. Ich warte noch die Klärung einiger Performance-Fragen ab, damit ich die Implementierung endlich abschließen kann … bis dahin gibt es nur ein paar Screenshots der Full-HD-Version mit halbaufgelöstem Blur:
gl.png
mondsichel.png
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Schrompf »

Das sieht absolut geil aus. Großen Glückwunsch! Bei Deinem letzten Jammer-Beitrag dachte ich noch, Du hast das Programmieren komplett hingeschmissen :-)
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Schrompf hat geschrieben:Bei Deinem letzten Jammer-Beitrag dachte ich noch, Du hast das Programmieren komplett hingeschmissen :-)
Ich auch. Es ist auch eigentlich nichts anderes als ständige Frustration mehr:
  • Der VC-Compiler verkackt meinen Shader-Cache
  • der HLSL-Compiler ist so lahm dass jede kleine Korrektur minutenlanges Warten erfordert
  • Die Grafikkarte nutzt nur 12–25 % der zur Verfügung stehenden Bandbreite, und wenn sich das nicht ändert, kann ich den Scheiß gleich in die Tonne kloppen weil die Performance wie 2007 ist
  • Herausfinden, ob es ein Fehler im Compiler, Treiber oder by Design ist kann ich nicht, weil die HLSL-Opcode-Spezifikation Verschlusssache ist
  • Bei Microsoft und AMD antwortet mir niemand
  • Compute Shader ist so mies dokumentiert dass man alles einmal ausprobiert haben muss, egal, wie abwegig es aussieht, bevor man weiß, wie man es machen muss
  • Zum Benchen und optimieren muss ich immer alles schließen, weil Flash, Aero und andere ungeklärte Ursachen 10–70 % der GPU fressen
  • Benchen ist eh für den Popo weil sich dank der Bandbreitenlimitation alles völlig unberechenbar verhält
  • AMDs Stream Profiler stürzt ab
  • AMDs Treiber stürzt ab einer gewissen Shaderkomplexität ab
  • Der HLSL-Compiler stürzt ab, sobald der Application Verifier eingeschaltet ist
  • Der PC stürzt ab, wenn meine Engine von einem anderen Fenster verdeckt wird
  • Der PC friert ein, wenn ich versehentliche eine Shader-Endlosschleife gebaut oder einen negativen Dispatch-Parameter übergeben habe
  • ntdll stürzt manchmal ab, wenn es Abhängigkeiten meiner Engine lädt
  • Gimp benutzt zum Überblenden meiner Ebenen zu geringe Farbtiefe; kann meine Texturen nicht feinabstimmen
Ich will diese verdammte Selbstgeißelung einfach nur noch hinter mir haben. Naja … im Gegenlicht sieht alles gleich schöner aus … mal sehen, wie lange es sich noch hinzieht.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Ich nutze die Gelegenheit ausgedehnter Farbübergänge einfach mal dafür, wieder Werbung für Dithering zu machen:
without dithering.png
with dithering.png
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4254
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Glare-Algorithmus

Beitrag von Chromanoid »

Video pls :) ich weiß das oszillieren und so ist raus aber ich würde es trotzdem mal gerne sehen...
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Wenn …
  • … es fertig ist (Shader für 20 FFTs in je drei verschiedenen Auflösungen zu entwickeln, zu prüfen und zu optimieren braucht seine Zeit),
  • … ich mit der visuellen Qualität zufrieden bin,
  • … es optimiert ist (500 MiB VRAM für einen Nachbearbeitungseffekt sind eben zu viel),
  • … ATI neue Treiber rausgebracht hat (sollte sich der Leistungseinbruch als deren Fehler herausstellen),
  • … ich es auf anderen Karten als der HD 5770 getestet habe und
  • … der Shader-Cache um herstellerspezifische Optimierungen erweitert ist,
dann gibt es eine aktualisierte Sternendemo.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Und ich mache nochmal auf einen weiteren Fallstrick aufmerksam: Aliasing und Flimmern.

Nehmen wir diesen Glare, der später auf das Ausgangsbild aufaddiert wird:
moongl.png
Er resultiert aus der Mondsichel. Die sieht ohne Glare so aus:
moon.png
Es lässt sich abzählen, wie wenige Pixel der Mond abdeckt – nur etwa 30 bis 40. Trotzdem sind diese 30 bis 40 Pixel für den Großteil der Helligkeit der restlichen zwei Millionen Pixel verantwortlich.

Wenn sich der Mond nun bewegt – das muss nicht durch programmierten Tagesrhythmus geschehen, sondern kann schon ganz banal durch Kamerabewegung hervorgerufen werden – bleibt die Gesamthelligkeit der Pixel nicht konstant, weil immer mal wieder ein paar Pixel überspringen. Die Gesamthelligkeit aller Mondpixel springt um gute fünf Prozent. Und damit springt auch ein Großteil der Gesamthelligkeit des fertigen Bildes von Frame zu Frame. Und alles flackert und flimmert wie Sau.

Ich habe das Glück, von Anfang an mit viel Antialiasing gerendert (und die Gestirne ja sogar auf möglichst glattes Aussehen optimiert) zu haben; das kommt mir jetzt zugute – ich brauche „nur“ mit 8×AA rendern und muss darauf achten, vor den FFTs alle Samples aufzulösen. Das kostet zwar 6 ms in Full-HD, aber die Leistung ist ja eh schon ruiniert. Das Flimmern ist zwar immer noch da, aber nicht mehr so stark, dass es direkt ins Auge fällt.

Der Punkt ist: Wenn ihr Glare implementiert, dann achtet darauf, dass kleine Lichtquellen möglichst weich sind oder lasst sie komplett weg. Sonst habt ihr nur noch Stroboskoplicht.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Weil mir die ganze Sache langsam zu viel wird, fange ich schonmal mit meiner Zusammenfassung an (was ’n Schluss, nä? Höhö). Beginnen wir damit, worüber wir hier eigentlich die ganze Zeit reden und ziehen in zukünftigen Beiträgen weiter zu Fallstricken und Optimierungen.

Es geht hier um dieses Paper, das ich zu implementieren versucht habe: Temporal Glare: Real-Time Dynamic Simulation of the Scattering in the Human Eye.

Weil hier auch die Profis ihre Probleme hatten zu verstehen, was vor sich geht, ein Überriss:

• Konventionelle Filter werden bei großen Kerneln furchtbar ineffizient – man setzt auch heute noch sehr lokale Kernel (zweistellige Pixelzahl) für Blur ein. Weiterhin benutzt man einen Gaussfilter. Der hat zwar im Fall von Glare wenig damit gemein, was wir in der Realität sehen, ist dafür aber effizient berechenbar weil er sich in zwei Durchläufe über X und Y zerlegen lässt. (Das ist nur mit sehr wenigen Funktionen möglich!) Möchte man komplexere Kernel – z.B. für einen Sternfilter – macht man entweder pro Streifenrichtung einen Durchlauf oder rendert den fertigen Kernel in eine Textur, in der man die Intensität nachschlägt statt sie zu berechnen. Hier ist man nun in Regionen, die auch mit modernen Karten unmöglich in Echtzeit realisierbar sind, sobald der Kernel nicht mehr in den Cache passt.

• Weitaus intelligenter lässt sich das Problem mit der Fourier-Transformation lösen: Man berechnet die FT des Bildes und des Kernels, multipliziert beide und führt dann eine inverse Fourier-Transformation aus. Das Ergebnis ist ein Bild, bei dem der Kernel auf jeden einzelnen Pixel angewandt wurde. Da sowohl die Daten als auch der Kernel dieselbe Größe haben müssen, ist es für die Leistung egal, wie groß der Kernel ist – ein 4×4-Gaussfilter ist genau so schnell wie ein 2048² Pixel weiter Sternfilter. Die Fourier-Transformation (und auch ihre Inverse) realisiert man üblicherweise als Fast Fourier Transformation, die sich enorm gut parallelisieren lässt. Über schnelle Implementierungen gibt es jede Menge Paper; ich habe mich an diesem orientiert: High Performance Discrete Fourier Transforms on Graphics Processors.

• In der Essenz basiert nun der Glare-Algorithmus darauf, die Punktspreizfunktion (Point Spread Function) des Auges zu berechnen – also das Abbild, das ein einziger Pixel nach Streuung und Beugung auf der Netzhaut hinterlässt – und die dann als Kernel auf alle Pixel des Frames anzuwenden.

• Die PSF entsteht durch die Fokussierung der Linse sowie durch Beugung an der Iris, den Wimpern, Partikeln im Glaskörper u.v.m. Diese Beugung lässt sich durch das Beugungsintegral einer Abbildung des Auges berechnen (im Paper unter dem englischen Titel Fresnel Diffraction referenziert). Für so kurze Brennweiten wie im menschlichen Auge lässt sich das wiederum zufälligerweise als Fourier-Transformation ausdrücken, was die Sache enorm vereinfacht.

• Der Ablauf besteht nun also daraus,
  • eine Innenansicht des Auges zu rendern.
  • Daraus lässt sich nach Multiplikation mit einer Linsenformel (Fresnel Term im Paper) per Fourier-Transformation die PSF berechnen. (Normalerweise müsste das für jede Wellenlänge geschehen, aber man kann das Ergebnis annähern indem man sie nur für grünes Licht (mittlere Wellenlänge) berechnet und viele leicht skalierte und dem Lichtsprektrum entsprechend gefärbte Kopien aufaddiert).
  • PSF und Szene werden jeweils Fourier-transformiert und miteinander multipliziert.
  • Die iFT des Ergebnisses wird berechnet und ist das Ergebnis: das Eingangsbild mit angewandtem Glare.
eXile hat die entsprechende mathematische Repräsentation hier aufgeschrieben.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Nun komme ich zum ersten Fallstrick, über den ich gestolpert bin: Den Aufwand zu unterschätzen.
  • Eine FFT kann am besten auf Zweierpotenzen durchgeführt werden. Das bedeutet, dass die Bildausmaße auf die nächsthöheren Zweierpotenzen aufgerundet werden müssen. (Es ist zwar möglich, FFTs auch auf die Potenzen von anderen Primzahlen durchzuführen, aber das lässt die Code-Basis explodieren.)
  • Eine FFT sieht das Signal als zyklisch an; so auch die PSF. Das bedeutet konkret, dass ein helles Licht am einen Bildrand am gegenüberliegenden Bildrand ebenfalls Glare produziert. Wenn man Glück hat, ist der Kernel kleiner als der Verschnitt, den man durch das Aufrunden auf die nächste Zweierpotenz produziert, und wird von diesem verschluckt. Da die PSF über das gesamte Auge geht und Glare kaum lokal eingrenzbar ist, hat man hier Pech und muss die Bildausmaße verdoppeln.
  • Multisampling lässt sich nicht transformieren. Glare muss im linearen Farbraum berechnet werden; Multisampling darf erst im gammakorrigierten Farbraum aufgelöst werden. Darum ist der Algorithmus grundsätzlich nicht kompatibel zu Multisampling – was umso schwerer wiegt, weil Aliasing durch Glare äußerst stark hervorgehoben wird. Man kann das nur umgehen, indem man die Mitte der PSF schwärzt (damit sie den Originalwert auslöscht) und das entstehende Bild auf die ursprüngliche, immernoch gemultisamplete, Szene aufaddiert, die man vorher mit dem ursprünglichen Wert in der Mitte der PSF multipliziert.
  • Man muss alle Berechnungen in 32-Bit-Gleitkommapräzision durchführen; auf kleinere Formate lässt sich nicht ausweichen.
  • Spätestens beim Fresnel Term der PSF kommen in der Eingabe der FT komplexe Zahlen vor; die üblichen FFT on Real Values-Optimierungen sind hier nicht mehr anwendbar. Disregard that … wenn die PSF steht sind es ja wieder nur reelle Werte und die Szene ist ebenfalls reell … hier kann ich wohl wirklich noch was rausholen
Rechnen wir die Sache mal exemplarisch für einen Frame in Full-HD mit 8×AA durch (habe ich so nicht implementiert, mehr dazu später in den Optimierungen). Um Wrap-Arounds zu vermeiden muss die Auflösung verdoppelt werden, um FFT zu nutzen muss sie zur nächsthöheren Zweierpotenz gerundet werden – für die sichtbaren 1920×1080 Pixel muss man also intern in 4096×4096 Pixeln rechnen:
  • Für die PSF muss eine Innenansicht des Auges berechnet werden. Das braucht man nur für einen Kanal zu machen; die Sum of Scaled Copies wird später die Farben hinzufügen. Da man hier bereits den Fresnel Term einbeziehen muss, muss alles in komplexen Zahlen geschehen. Speicherverbrauch: 4096×4096×2×4 B = 128 MiB; Bandbreite (angenommen, man kann die Ansicht im Shader aus relativ kleinen Texturen zusammenkomponieren): 4096×4096×2×4 B = 128 MiB schreibend.
  • Per FFT – horizontal und vertikal – muss die PSF berechnet werden. Wir nehmen an, dass sich die FFT komplett im Gruppenspeicher des Shaders realisieren lässt, also keine Zwischenergebnisse in globalen Speicher wandern – mit den 32 KiB Gruppenspeicher von Compute Shader 5.0 ist das möglich, mit den 16 KiB von Cuda nicht mehr. Man könnte dann auch das Ergebnis in dieselbe Textur schreiben, aus der gelesen wurde, aber Compute Shader haben damit Probleme und der gesparte Speicher resultiert in einem 4× geringeren Speicherdurchsatz (Erklärung nach der Liste). Darum legen wir hier eine Kopie des Puffers an und schreiben in einem Ping-Pong-Muster. Da wir von der PSF nur den Realteil benötigen, schreiben wir auch nur die realen Werte. Speicherverbrauch: 4096×4096×2×4 B = 128 MiB; Bandbreite: 2×4096×4096×2×4 B = 256 MiB lesend, 4096×4096×2×4 + 4096×4096×4 B = 192 MiB schreibend; FFTs: 2×4096.
  • Die Sum of Scaled Copies macht aus der monotonen PSF eine farbige PSF mit Brechungen. Für ein befriedigendes Ergebnis braucht man 16 übereinandergelegte Kopien, die bei mir zu drei Vierteln im Cache lagen. Wir lesen einkanalig und schreiben in drei Kanäle (RGB) mit Reellwerten. Speicherverbrauch: 3×4096×4096×4 B = 112 MiB; Bandbreite: 16/4×4096×4096×4 B = 256 MiB lesend, 3×4096×4096×4 B = 448 MiB schreibend.
  • Die FFT der PSF muss berechnet werden. Bisher haben wir für die PSF nur eine reellwertige RGB-Textur, also brauchen wir wieder zwei (Ping-Pong!) komplexe RGB-Texturen. Speicherverbrauch: 2×3×4096×4096×2×4 B = 768 MiB; Bandbreite: 2×3×4096×4096×2×4 B = 768 MiB lesend; 2×3×4096×4096×2×4 B = 768 MiB schreibend; FFTs: 2×4096.
  • 1920×1080 Pixel 12-Byte-RGB mit den Pixeln der Szene (die man aber auch ohne Glare hätte) müssen mit je acht Samples in einen als FFT-Eingabe lesbaren Puffer aufgelöst werden. (GPUs können nur das 128-Bit-RGBA-Format verarbeiten, aber der Alphakanal ist hier vernachlässigbar.) Speicherverbrauch: 1920×1080×12 B = 24300 KiB; Bandbreite: 1920×1080×12×8 B = 194400 KiB lesend, 1920×1080×12 B = 24300 KiB schreibend.
  • Die FFT der Szene muss in RGB berechnet werden. Für das Ping-Pong können wir einen Puffer der PSF-FFT-Berechnung wiederverwenden, brauchen aber noch einen für das Ergebnis. Wir lesen ausschließlich reelle Werte, schreiben aber komplexe. Speicherverbrauch: 3×4096×4096×2×4 B = 384 MiB; Bandbreite: 3×4096×4096×4 + 3×4096×4096×2×4 B = 576 MiB lesend; 2×3×4096×4096×2×4 B = 768 MiB schreibend; FFTs: 2×4096.
  • Die Ergebnisse der Fourier-Transformationen müssen miteinander multipliziert werden. Dann wird die inverse FFT ausgeführt. (Diese Schritte können miteinander kombiniert werden. Theoretisch könnte man die vertikale Fourier-Transformation des vorherigen Schritts auch mit der dieses Schritts zusammenlegen und sich das Schreiben und Lesen eines Zwischenergebnisses sparen – praktisch wird die Shader-Komplexität dann aber so groß, dass der HLSL-Compiler mir bei Seitenlängen über 1024² keine gültigen Programme mehr generiert und die Leistung durch hunderte Scratch-Register eh im Keller wäre.) Wir benutzen die Puffer aus den vorherigen Schritten für Zwischenergebnisse und schreiben am Ende nur reelle Zahlen, weil uns der komplexe Teil der Szene nicht interessiert. Bandbreite: 3×4096×4096×4 + 3×4096×4096×2×4 B = 576 MiB lesend; 2×3×4096×4096×2×4 B = 768 MiB schreibend; FFTs: 2×4096
In der Summe müssen wir also 32.768 FFTs auf je 4096 Samples durchführen, lesen dabei 2,5 GiB, schreiben 3 GiB und benötigen 1,5 GiB zusätzlichen Grafikspeicher. Das sind globale Werte; zum Glück wird ja am meisten mit gruppenlokalen Werten gerechnet (die aber auch nicht latenzfrei sind!). Und das alles mindestens 25× pro Sekunde.

Jeder Wert an sich kratzt, obgleich recht optimistisch gerechnet, bereits an der Leistungsgrenze aktueller GPUs. Manche lassen sich durch gute Optimierung aber noch drücken. Die 1,5 GiB VRAM jedoch sind kaum zu reduzieren und sind das Totschlagargument gegen Full-HD-Glare. Man könnte sie fast halbieren, indem man statt dem Ping-Pong-Muster in dieselbe Textur schreibt, aus der man liest; dem steht allerdings etwas im Weg:

ATI-Karten haben zwei Speicherpfade – den FastPath, der nur 32-/64-/128-Bit-Werte schreibt und 80 % der theoretischen Spitzenbandbreite erreicht und den CompletePath, der jeden Speicherzugriff durch einen lokalen Puffer führt und 4–8× langsamer ist als FastPath. CompletePath ist dazu da, „ungerade“ Speichergrößen zu schreiben (z.B. einzelne Bytes), atomare Operationen durchzuführen und Speicherzugriffe sofort global sichtbar zu machen. Welchen Speicherpfad der Shader benutzt ist davon abhänhig, wie man die Daten deklariert hat:
  • RWBuffer<float>: CompletePath
  • RWStructuredBuffer<float>: FastPath
  • RWTexture?D<float>: CompletePath
  • Texture?D<float>: FastPath
Mir persönlich sieht das bereits völlig sinnlos aus, weil RWBuffer ein RWStructuredBuffer ohne Synchronisierung oder Unterstützung nicht-nativer Elemente ist, und deshalb eigentlich schneller sein sollte, nicht 8× langsamer. Wiedemauchsei: versucht man, aus einer Textur sowohl zu lesen als auch zu schreiben, muss man RWTexture2D benutzen, das ist langsam. Rendert man hingegen in einem Ping-Pong-Muster und liest die vorherige Textur als Texture2D, ist das schneller – viel schneller. Nachdem ich die Sum of Scaled Copies auf Ping-Pong umgestellt hatte, hat sich die Leistung verachtfacht (ja, der Sprung von einer HD 2xxx auf eine HD 6xxx). Die Gesamtlaufzeit des kompletten Algorithmus hat sich geviertelt.
Das war das lesen; aber schreibend führt noch immer kein Weg am langsamen RWTexture2D vorbei. RWStructuredBuffer ist keine Option, weil es durch die Auslegung im Speicher bei vertikalen FFTs und wahlfreiem Zugriff noch langsamer ist. Auf die Frage nach dem Sinn und der Schuld haben mir weder AMD noch Microsoft geantwortet, also muss ich mich vorerst einfach damit abfinden. Immerhin kann man den Schreibdurchsatz um zehn Prozent erhöhen, wenn man bei komplexen Zahlen Real- und Imaginärteil in einem Rutsch schreibt statt getrennt.

Das zu tun ist nicht selbstverständlich – wenn man nämlich getrennt schreibt, kann man einige Texturen sowohl für reelle als auch für komplexe Zahlen benutzen und damit das eine oder andere Texturobjekt sparen. Aber die Leistung ist eben schlechter.

Der Datenmenge, mit der man hier hantiert, sollte man sich halbwegs bewusst sein.

Als Nächstes geht es dann an ein paar grundsätzliche, aber unvorhergesehene Schwächen des Konzepts und dann um Optimierungen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Lynxeye
Establishment
Beiträge: 145
Registriert: 27.02.2009, 16:50
Echter Name: Lucas
Wohnort: Hildesheim
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Lynxeye »

Krishty hat geschrieben: [*]Eine FFT sieht das Signal als zyklisch an; so auch die PSF. Das bedeutet konkret, dass ein helles Licht am einen Bildrand am gegenüberliegenden Bildrand ebenfalls Glare produziert. Wenn man Glück hat, ist der Kernel kleiner als der Verschnitt, den man durch das Aufrunden auf die nächste Zweierpotenz produziert, und wird von diesem verschluckt. Da die PSF über das gesamte Auge geht und Glare kaum lokal eingrenzbar ist, hat man hier Pech und muss die Bildausmaße verdoppeln.
Ich weiß es ist physikalisch wahrscheinlich absolut nicht korrekt mit so einem Hammer da ran zu gehen, aber hast du mal über eine Windowfunktion vor der FFT nachgedacht? Das würde zwar den Einfluss von Lichtquellen am Bildrand ziemlich killen, würde es dir aber wahrscheinlich erlauben bei FullHD die FFT mit einer Auflösung von 2048² auszuführen. Konkret schwirrt mir da gerade so etwas wie die Tukey Funktion im Kopf herum.

Ich bin mir nicht sicher, in wie fern das die Bildqualität beeinträchtigt und mit deinem physikalisch korrekten Ansatz zu verbinden ist, aber bevor du ganz aufgibst wollte ich das noch mal schnell in die Runde werfen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Lynxeye hat geschrieben:Ich weiß es ist physikalisch wahrscheinlich absolut nicht korrekt mit so einem Hammer da ran zu gehen, aber hast du mal über eine Windowfunktion vor der FFT nachgedacht? Das würde zwar den Einfluss von Lichtquellen am Bildrand ziemlich killen, würde es dir aber wahrscheinlich erlauben bei FullHD die FFT mit einer Auflösung von 2048² auszuführen. Konkret schwirrt mir da gerade so etwas wie die Tukey Funktion im Kopf herum.
Oha; von Fensterfunktionen höre ich jetzt das erste Mal. Wenn ich das richtig verstehe, schwächt man das Signal (nicht den Kernel) zum Rand hin ab?

Ganz so einfach ist es nicht, weil die Helligkeit 14 Dekaden abdeckt. Wenn etwas am linken Bildrand auftaucht, was acht Dekaden heller ist als der Rest (z.B. der Mond vor den Sternen), streut das trotz winziger Randwerte noch wie Sau. Schwächerer Glare, wie der der Sterne wäre dann nur relativ weit vom Bildrand entfernt überhaupt bemerkbar (ich gehe bei dem Kernel von einer viertel Bildschirmbreite deutlichem Radius aus; also wäre der Glare nur auf einem Viertel der Bildschirmfläche (halbe Breite × halbe Höhe abgedeckt) so hell sichtbar, wie er sein sollte) … ich muss das testweise implementieren und dann abwägen, wie gut es aussieht.

(Btw rechne ich momentan alles in halber Seitenlänge aus um von 4096² auf 2048² zu kommen; der Glare ist so schön niederfrequent, dass das nichts ausmacht.)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Schrompf »

Ich muss mal sagen: es sieht echt cool aus. Und ich finde es super, dass Du Dir soviel Mühe machst, Deine Erfahrungen hier so umfangreich zu beschreiben. Ich fand es jedenfalls interessanten Lesestoff, und dank Tante Google werden auch andere noch davon profitieren. Danke!
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
hagbard
Beiträge: 66
Registriert: 05.08.2010, 23:54

Re: Glare-Algorithmus

Beitrag von hagbard »

@Krishty: Danke für deine Mühen das ganze nieder zu schreiben. Jetzt hab auch ich als Nicht-Grafikprogrammierer eine Chance das Gesamtkonzept zu verstehen. :mrgreen:
starvald
Beiträge: 31
Registriert: 16.04.2010, 17:20
Wohnort: Heppenheim

Re: Glare-Algorithmus

Beitrag von starvald »

Sehr geil von Dir hier alles mit uns zu teilen. Hut ab und weiterhin viel Spass und Erfolg beim coden!
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Dankt mir erst, wenn ich durch bin … DO habe ich wieder Zeit, hier über die Schwächen zu schwadronieren.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Soooo … kommen wir jetzt mal zu dem Grund, warum ich von der Glare-Erzeugung durch Beugungsberechnung losgelassen habe …

… die Fresnel Term, also die Funktion, die das Bild fokussieren soll, war das Problem. Wenn wir einen runden Kreis – die Öffnung des Auges – in ein Rechteckfenster – die Textur für die PSF – packen und das Beugungsmuster berechnen (das ja im Grunde nicht mehr als eine Fourier-Transformation ist), bekommen wir je nach Größenverhältnis ein Muster in der PSF.

Geht die Iris über das ganze Auge, bildet sich ein Muster, das wie ein Balkenkreuz aussieht:
2011-01-05-16-50 stars with glare.png
Dieser Effekt bleibt etwa so lange bestehen, bis der Irisdurchmesser den halben PSF-Durchmesser unterschreitet. Allerdings werden mit schrumpfendem Durchmesser auch die für Lochblenden bekannten Ringe stärker:
2011-01-09-22-40 old star luminance.png
Beides kommt in „echtem“ Glare nicht vor (Ringe schon, allerdings so schwach, dass nur ein Primärring sichtbar ist, nicht fünf).

Die Fresnel Term sollte das scheinbar kompensieren, allerdings habe ich das einfach nicht hingekriegt. Keine Ahnung ob ich was falsch gemacht habe oder das ein grundsätzliches Problem ist, aber ganz egal, welchen Parameter ich der Fresnel Term übergeben habe – es kam immer nur Müll dabei raus. Ich habe auch vergeblich alle Vorzeichen gewechselt, komplexe durch reale Multiplikationen ersetzt usw. Wenn man die Beispiele aus dem Paper nur stark genug vergrößert, sieht man die Artefakte übrigens in abgeschwächter Form auch dort:
ppr.png
Durch viel Entropie in der Iristextur konnte ich künstlich Strahlenbildung hervorrufen, die stark genug war, um die Ringe und Balken einigermaßen zu überdecken – die hatten aber weder Bezug zur realen Iris noch waren sie irgendwie berechenbar. Ich konnte einfach nur auf gut Glück drin rumkrickeln und gucken, ob das Ergebnis besser oder schlechter wurde – mit Simulation hatte das nichts mehr zu tun. Ihr konntet mir auch nicht weiterhelfen und alle meine Versuche waren zwar besser, aber immernoch suboptimal, also habe ich es sein gelassen.

Weiterhin verbraucht die Berechnung der PSF samt SSC etwa so viel Rechenzeit wie der ganze restliche Algorithmus (lies: statischer Glare ist doppelt so schnell). Das ist es mir einfach nicht wert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Glare-Algorithmus

Beitrag von Alexander Kornrumpf »

Jetzt nochmal für langsam dumme:

Was du für den Fresnel Term haben willst ist im Grunde ein Muster wie Figure 6, kleines Bild, aka konzentrische Kreise, was du tatsächlich bekommst ist das unregelömäßige muster, dass unter "immer nur Müll" verlinkt ist?!

Kannst du das vielleicht einmal für Realteil und Imaginärteil getrennt plotten? Oder ist das der Realteil? Der Betrag? Streich das, der scheint konstant zu sein.

Die Formel funktioniert anscheinend ganz gut, für reelle x, y und lambda*d=1 (da ich nicht wusste was hier brauchbare Werte sind) spuckt jedenfalls Wolfram Alpha dieses aus:

http://www.wolframalpha.com/input/?i=co ... By^2%29%29

unter Contour Plot schauen. Leider kann ich das Ding nicht überreden über einen größeren Wertebereich zu plotten, hat vielleicht jemand eine Mathematica Vollversion?

Was das mit dem Seitenverhältnis zu tun haben soll entzieht sich vollkommen meiner Vorstellungskraft.

EDIT: Lustig, zirkumflex killt url parsing

EDIT2: Vielleicht blamiere ich mich jetzt aber eigentlich kann dein Bild gar nicht richtig sein. Für gleiche werte von x^2+y^2 aka Kreislinien muss die Funktion ja denselben output liefern. Schlangenlinien wie in deinem Bild hinter immer gehen doch gar nicht. Mich würde auch interessieren wie dein Bild im Fourierraum aussieht. Ich nehme intuitiv an, dass die Fouriertransformierte von der eigentlichen Funktion wieder ein regelmößiges Muster sein muss.
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Glare-Algorithmus

Beitrag von eXile »

Falls es was hilft.. Ich stehe dazu, dass ich noch was zum Fresnel-Term sagen muss, bin aber zu eingespannt, dass ich hier meine drei Seiten zu Ende ausführen und abtexen kann. ETA 1,5 Wochen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Alexander Kornrumpf hat geschrieben:Kannst du das vielleicht einmal für Realteil und Imaginärteil getrennt plotten?
Der Code ist schon seit Wochen rausgeschmissen, drum muss ich hier alles aus dem Gedächtnis machen ;)

Die Balkenartefakte und das Ringing haben zwei unterschiedliche Ursachen; ich fange mit dem Ringing an, weil das in der Fresnel Term fußt:
Alexander Kornrumpf hat geschrieben:Jetzt nochmal für langsam dumme:
Sagen wir, für Leute, die sich nicht 20 Nächte damit auseinandergesetzt haben ;) Um es mal deutlicher auszudrücken:

Was die Funktion ausgibt, ist (betragsmäßig 1 und im Real- und Imaginärteil je einander abwechselnd) das Muster einer Fresnel-Zonenplatte.

Diese Zonenplatte hat die Eigenschaft, ein fokussiertes Beugungsmuster zu erzeugen. Sie ist also eine Linse, die nicht durch Brechung bündelt, sondern durch Beugung (positive Interferenz). Sie soll die menschliche Linse simulieren – diese fokussiert das Bild und verhindert dadurch Beugungsringe im Auge. Das erreicht man, indem man die Fresnel Term berechnet und mit der Innenansicht der Pupille komplex multipliziert. Die Beugung an sich wird danach, wie gewohnt, durch die FFT berechnet. Da dann die Fresnel Term mit einfließt sollte das Resultat frei von Ringen sein.
Alexander Kornrumpf hat geschrieben:Was du für den Fresnel Term haben willst ist im Grunde ein Muster wie Figure 6, kleines Bild, aka konzentrische Kreise
Genau. Das hatte ich auch alles problemlos berechnen können.
Alexander Kornrumpf hat geschrieben:was du tatsächlich bekommst ist das unregelömäßige muster, dass unter "immer nur Müll" verlinkt ist?!
Nicht ganz. Die Fresnel Term erwartet einen Parameter (wenn ich mich recht erinnere: das Verhältnis von Brennweite und Wellenlänge). Wenn ich den einsetze und wie gewohnt verfahre, erhalte ich die verlinkten Muster als resultierende Punktspreizfunktionen – ist der Parameter klein, ist noch alles regelmäßig geringt. So ab einem Betrag von 6 erhalte ich einen fetten Fleck. Und ab 100 ist dann alles voller Quadrate. Ich …
  • … bin alle Parameter von 1e-5 bis 10e10 in 0,01-%-Steigerungen durchgegangen
  • … dasselbe für negative Parameter
  • … habe Sinus und Kosinus vertauscht
  • … habe x²+y² durch x+y, (x+y)², x³+y³ etc ausgetauscht
  • … habe in der Innenansicht 1 und 0 vertauscht
  • … habe nicht komplex multipliziert, sondern reell, und auch einfach den Imaginärteil in den der Pupillenverdeckung eingesetzt
und so weiter und so fort. Ich habe nie ein fokussiertes Bild erhalten sondern immer nur die verlinkten Anomalien.

————————

Soo. Das war das eine. Nun zu den Balkenartefakten:

Die FFT einer Kreisfläche erzeugt immer ein Balkenmuster (begründet durch die Diskrete Abtastung). Bild:
balken.png
(Applet) Antialiasing dämpft es minimal, Unschärfe sogar noch mehr, aber so lange die Kreisfläche nicht mit einem riesigen Gauss geglättet ist gibt es immer Balken. Sie werden erst erträglich schwach, wenn die Kreisfläche schön klein ist (im Durchmesser kleiner als die Hälfte des FFT-Durchmessers) – aber dann wird eben das Ringing immer stärker und der Punkt immer unschärfer.

————————
eXile hat geschrieben:Falls es was hilft.. Ich stehe dazu, dass ich noch was zum Fresnel-Term sagen muss, bin aber zu eingespannt, dass ich hier meine drei Seiten zu Ende ausführen und abtexen kann. ETA 1,5 Wochen.
Leider nicht; aber lass dir ruhig Zeit – die dynamisch generierte PSF habe ich vorerst ja sowieso abgeschrieben.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Glare-Algorithmus

Beitrag von Alexander Kornrumpf »

Die Fresnel Term erwartet einen Parameter (wenn ich mich recht erinnere: das Verhältnis von Brennweite und Wellenlänge). Wenn ich den einsetze und wie gewohnt verfahre, erhalte ich die verlinkten Muster als resultierende Punktspreizfunktionen
im Paper ist das 1/d*lambda wobei d der Abstand zwischen Pupille und Retina ist. Offensichtlich habe ich mehr von Biologie und Physik vergessen (in dem Sinne dass ich zwar weiß dass ich mal wusste wie das funktioniert, das eigentliche Wissen aber weg ist) als behalten, aber rein von der Intuition her sollte sich d beim Fokussieren ja ändern. Korrekt?

Auch wenn das jetzt vermutlich überhaupt nichts zur Lösung des Problems beiträgt würde ich trotzdem aus Interesse gerne Plots von den Zwischenschritten sehen, d.h. Fresnel Term und Aperture aus deren Figure 8 mit realistischen Werten, aber vor der Multiplikation. Und while we are at it, wie multipliziert man zwei bilder? Faltung kann ja nicht gemeint sein. Pixelweise?
(begründet durch die Diskrete Abtastung)
Ach scheiße warum vergesse ich Diskretisierungsfehler immer?
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Alexander Kornrumpf hat geschrieben:
Die Fresnel Term erwartet einen Parameter (wenn ich mich recht erinnere: das Verhältnis von Brennweite und Wellenlänge). Wenn ich den einsetze und wie gewohnt verfahre, erhalte ich die verlinkten Muster als resultierende Punktspreizfunktionen
im Paper ist das 1/d*lambda wobei d der Abstand zwischen Pupille und Retina ist. Offensichtlich habe ich mehr von Biologie und Physik vergessen (in dem Sinne dass ich zwar weiß dass ich mal wusste wie das funktioniert, das eigentliche Wissen aber weg ist) als behalten, aber rein von der Intuition her sollte sich d beim Fokussieren ja ändern. Korrekt?
Gute Frage – afaik funktioniert die Fokussierung ja über eine Veränderung der Linsenform und nicht durch ein Wegschieben der Linse von der Retina. Sicher bin ich mir aber nicht.

Wenn doch, ändert sich der Faktor aber auch nur um ein paar Prozent. Die Artefakte bestanden aber über Dekaden … :/
(Bei sehr kleinen Werten waren btw dieselben Artefakte wie bei sehr großen, ist mir gerade wieder eingefallen.)
Alexander Kornrumpf hat geschrieben:Auch wenn das jetzt vermutlich überhaupt nichts zur Lösung des Problems beiträgt würde ich trotzdem aus Interesse gerne Plots von den Zwischenschritten sehen, d.h. Fresnel Term und Aperture aus deren Figure 8 mit realistischen Werten, aber vor der Multiplikation.
Die Pupille in Realwerten ist hier. Von der Fresnel Term habe ich keine Screenshots, sie sah aber exakt so aus wie die Zonenplatte und wie in den Graphen, die ihr mir geschickt habt. (Ich verweise auch nochmal auf meine geflushte Pipeline hier, da kann man erkennen wie aus der FFT der Pupille die Balken in der PSF entstehen.)

Beide multipliziert ist schwierig. Also, „realistische Werte“ ist ganz schlecht. 1÷d×lambda ergibt astronomische Werte (d im Zentimenterbereich, lambda im Nanometerbereich); da ist die Fresnel Term so komprimiert dass alles in Aliasing untergeht und man am Ende das hier rauskriegt. Wenn man aber von 1 ausgeht, habe ich genau einen Schnappschuss von Pupille × Fresnel: hier, wo ich mich über Race Conditions aufgeregt habe. Das ist der Betrag; die vertikalen Artefakte musst du dir wegdenken; die Pupille ist superweit geöffnet und der dunkle Fleck in der Mitte sowie der dunkle Kreis, der den Rand berührt, sind eine Folge der Fresnel Term.
Alexander Kornrumpf hat geschrieben:Und while we are at it, wie multipliziert man zwei bilder? Faltung kann ja nicht gemeint sein. Pixelweise?
Genau; man multipliziert die komplexen Bilder (Pupille, 0) und (Fresnel r, Fresnel i) pixelweise.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Glare-Algorithmus

Beitrag von Alexander Kornrumpf »

Also, „realistische Werte“ ist ganz schlecht. 1÷d×lambda ergibt astronomische Werte (d im Zentimenterbereich, lambda im Nanometerbereich);
Das muss ja irgendwie Einheitenfrei sein oder wie man das nennt. Also ob du irgendwas in der Größenordnung von 1/(10^-13 m^2) hast wobei 10^-13 = centi*nano oder 1/(10^-1 µm^2) muss egal sein (und ist es sehr wahrscheinlich auch bis auf halt Diskretisierungsfehler) Da eine Einheit zu finden, die dir in den Kram passt sollte das kleinere Problem sein. Ich vermute dass es für die Genauigkeit (viel) weniger schlimm ist die Pixelhelligkeit in cd/(µm^2) anzugeben als irre hohe Frequenzen zu bekommen (einfach weil float intelligenter diskretisiert als Pixel) Ich nehme auch an, dass der Normalisierungsterm (K) genau dafür da ist, da die überflüssigen Einheiten wieder loszuwerden, auch wenn ich zugebe dass nicht im Detail durchdacht zu haben. Am Ende (mein 12/13427stel Wissen sagt vor oder beim Tone-Mapping), kannst du das Problem der seltsamen Einheit der Helligkeit dann ja auch wieder korrigieren.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Neinein – das hat nichts mit Helligkeiten zu tun die man hinterher wieder wegskalieren kann. Wenn ich mich nicht fundamental irre, bestimmt dieser Term nämlich (direkt oder indirekt) die Brennweite der Fresnel-Linse. Und wenn da steht d÷lambda, und für nichts von beidem ist eine explizite Einheit gegeben, dann wird in den SI-Basiseinheiten gerechnet. Und bei 1 ÷ (0,03 m × 0,000…00044 m) geht das schlicht und einfach nicht gut.

Ganz davon ab habe ich ja wirklich alle Parameter, die irgendwie noch als Gleitkommazahl sinnvoll darstellbar sind, getestet. Und es kam nie eine ordentliche Fokussierung dabei raus.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Glare-Algorithmus

Beitrag von Alexander Kornrumpf »

Nach allem was ich weiß kommt es einzig und allein darauf an überall die gleichen Einheiten zu verwenden. (http://en.wikipedia.org/wiki/Dimensional_analysis).

Natürlich ist es immer einfacher in SI Einheiten zu rechnen, aber es ist nicht zwingend. Wie es in der ODE Doku z.B. heißt, du kannst Geschwindigkeiten auch in furlongs per fortnight angeben oder wie bei xkcd angstroem pro jahr :twisted: Du musst dann nur überall die Einheit ändern. Jetzt kommen Meter ja in deinen Berechnungen nicht sooo unglaublich oft vor, aber weiter oben in dem Paper habe ich halt gelesen, dass die Helligkeit als cd/m^2 interpretiert wird (und ich erinnere mich dunkel, dass ihr das beim Sternenartikel auch diskutiert habt), nur darauf bezog sich meine Ausführung. Wenn sich sonst noch irgendwo ein m in der Formel versteckt dass ich übersehen haben sollte, musst du das natürlich auch noch umrechnen.

Mir fehlt leider ein wenig die Intuition, was die Fourier-Transformation aus den Einheiten macht aber diese Fundamentale Regel dürfte sie eigentlich nicht aushebeln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Jaa, durch K werden die Einheiten auch zu dem wiederhergestellt, was sie vor der Multiplikation mit der Fresnel Term waren. Aber es bleibt dabei, dass dabei längst nicht dieselben Ergebnisse rauskommen. Wenn du für eine Linse die tausendfache Brennweite wählst, ist das Bild dahinter ein anderes als wenn du eine Linse mit einfacher Brennweite wählst und die Helligkeit ihres Bildes durch tausend teilst. Aber genau das tust du, wenn du anfängst, in der Formel beliebige Einheiten einzusetzen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Glare-Algorithmus

Beitrag von Alexander Kornrumpf »

Du ahnst nicht wie es mich nervt über alle diese Dinge nur Halbwissen zu haben und nicht die Muße zumindest ein paar grundlegende Experimente zu machen.

Es scheint ja ganz abseits der Diskussion hier auch eine Faustformel für Zoneplates zu geben: http://pinhole.stanford.edu/zoneplatemath.htm jetzt stellt sich mir natürlich die Frage wie man das Digital hinbekommen würde, da kämen ja dann dpi ins Spiel. Ich habe (durch Einsetzen von Parametern bei Wolfram Alpha) den Eindruck gewonnen, dass die Zoneplate sowieso immer genau gleich aussieht und nur die Auflösung sich ändert. Was auch immer das bedeuten mag.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Alexander Kornrumpf hat geschrieben:Du ahnst nicht wie es mich nervt über alle diese Dinge nur Halbwissen zu haben und nicht die Muße zumindest ein paar grundlegende Experimente zu machen.
Mein Wissen ist auch nur aus der Beobachtung der Implementierung abgeleitet und glaub mir, wenn die Experimente nicht tun, was sie sollen, ist das noch viel nerviger.
Alexander Kornrumpf hat geschrieben:Ich habe (durch Einsetzen von Parametern bei Wolfram Alpha) den Eindruck gewonnen, dass die Zoneplate sowieso immer genau gleich aussieht und nur die Auflösung sich ändert. Was auch immer das bedeuten mag.
Ja, darum kann man das z.B. in einer 1D-Textur vorberechnen. Mit der „Auflösung“ ändert sich das Beugungsmuster und dadurch die Brennweite.
Alexander Kornrumpf hat geschrieben:Es scheint ja ganz abseits der Diskussion hier auch eine Faustformel für Zoneplates zu geben: http://pinhole.stanford.edu/zoneplatemath.htm jetzt stellt sich mir natürlich die Frage wie man das Digital hinbekommen würde, da kämen ja dann dpi ins Spiel.
Ja, das sieht solide aus. Die DPI brauchst du nicht einmal – du renderst ja die Innenansicht der Pupille; deren Größe ist ja ungefähr bekannt und die setzt du dann einfach in Relation zu der Zonenplatte. Hmm. Jetzt hätte ich glatt Lust, das nochmal auszuprobieren, wenn es nicht wieder tagelanges Umschweffeln von Puffern und Shadern bedeuten würde …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Glare-Algorithmus

Beitrag von Alexander Kornrumpf »

hier fehlt doch ein Beitrag....
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

Baut hier einen Promille-Check ein und ich muss nichts mehr nachträglich löschen. Vor allem war meine Gleichsetzung des ATI-Teams mit geistig behinderten Mitbürgern wirklich mies – schließlich heißen die mittlerweile AMD.

Ich wiederhole das irgendwann noch einmal genau, aber es lief darauf hinaus, dass man die Texturen exakt so zurecht schneidet, dass statt Padding out-of-bounds gelesen wird und man sich dadurch das Füllen mit Nullen spart. In Full-HD spart das fast den halben Bandbreitenbedarf; bei Nvidia ist der Effekt stärker zu spüren als bei AMD.

Nachtrag: Ich habe mal eine kleine, auf 85 % genaue Leistungsmessung vorgenommen. (Da mir AMDs Stream/APP Profiler in D3D11CreateDevice() abstürzt, geht es einfach nicht präziser.) Demnach macht Glare momentan 68 % meiner Render-Zeit aus:
  • 5,5 % zum Auflösen des Multisamplings
  • 2,8 % für die horizontale FFT
  • 28,5 % für die vertikale FFT inklusive Multiplikation mit der PSF
  • 27,1 % für die inverse vertikale FFT
  • 4,1 % für die inverse horizontale FFT.
Die vertikalen FFTs schreiben gleich viel (acht Mal so viel wie die horizontalen FFTs). Die inverse vertikale FFT liest hingegen 30 % weniger als die vorherige vertikale FFT, ist aber trotzdem nur 5 % schneller – ein Hoch auf AMDs Schreiboperationen. Mal gucken, was ich da noch rausholen kann …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Glare-Algorithmus

Beitrag von Krishty »

In einem heroischen Schlag gegen die Horden ungläubiger Register, die der satanische AMD-Compiler gegen meine heiligen Shader aussandte, habe ich einen überragenden Sieg errungen:

Einer glorreichen Erleuchtung folgend hatte ich mich auf gemacht, die drei Schritte – vertikale FFT, Multiplikation mit PSF, inverse vertikale FFT – nach revisionhundertelanger Feindschaft ehrvoll zu verbrüdern und damit all ihre Schreiboperationen zu einem eisernen Fluss strahlender Information zu bündeln und damit meine mächtige FFT in entfernteste Speicher zu tragen.

Torpediert wurde ich – erneut – von dem AMD-Compiler, der – den Befehlen Satans folgend – dutzende Register und Hundertschaften von Scratch-Registern allokierte und gegen mich entsandte, um die heilige Erleuchtung seiner Hardware durch meinen Shader zu verhindern. Doch mit großer List, eiserner Faust, wegweisender Kampfkunst und dem Willen Gottes gelang es mir – erneut – spielend, seine tablettierten Ratten zurückzuschlagen. Einen Bruchteil der ursprünglichen Register habe ich als Zeichen meiner endlosen Güte begnadigt.

Zutiefst beschämt und bloßgestellt von der Schande seines ehrlosen Vergehens, und durch Wissen um die Ehrlosigkeit seines Handelns offenbar dem Wahnsinn verfallen, hat sich der Compiler in sinnlose ALU-Operationen zurückgezogen. Doch auch dieser Hort gottlosen Treibens wird bald von der ewigen Sonne meiner FFT erleuchtet, die mit meinem makellosen Glare tausend Mal heller strahlt und tausend Mal heißer brennt als die Hölle, in der sich die degenerierten Ungläubigen des AMD-Compiler-Teams bald wiederfinden werden!

(siehe auch Tabelle einen Post weiter oben)
  • Vertikale FFT mit PSF-Multiplikation: 11 General-Purpose-Register, 0 Scratch-Register, 180 ALU-Anweisungen
  • Inverse vertikale FFT: 10 GPR, 0 Scratch, 160 ALU
  • Beide kombiniert: 30 GPR, 54 Scratch, >450 ALU
  • Durch mein Genie optimiert: 18 GPR, 0 Scratch, 339 ALU
  • Der inverse-vertikale-FFT-Schritt, der weggefallen ist, hatte 27,1 % der Ausführungszeit ausgemacht
  • Obwohl die ALU-Laufzeit des zusammengefassten Shaders 50 % schlechter ist als die der einzelnen Shader addiert, hat sich die Gesamtleistung um 13 % verbessert
  • Der weggefallene Shader hat also mindestens 50 % seiner Ausführungszeit mit AMDs bekackten Schreiboperationen verbracht
  • Alle meine Pipeline-Stufen, inklusive Post-Processing und Tone-Mapping, benutzen AMDs bekackte Schreiboperationen
  • Wenn AMD das endlich fixen würde, würde meine Engine doppelt so schnell laufen
So ein Geraffel für 13 % … ich hasse mein Leben. Aber mehr noch AMD.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten