PostMortem - HDR-Implementation in der Splitterwelten-Engine

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Schrompf »

Hallo Leute,

dieser Beitrag wird keine wirkliche Frage. Ich möchte vielmehr eine Geschichte erzählen, wie ich der Splitterwelten-Engine HDR beigebracht habe und was ich dabei alles gelernt habe. Vielleicht nützen die Erkenntnisse auch anderen Leuten. Denn HDR beeinflusst so ziemlich *alles*, was man in einer Engine bisher programmiert hat. Die Engine ist ausschließlich DirectX9-Niveau - etwas anderes kommt vorerst nicht in die Tüte.

Zuerst mal ein paar Bilder, wie das Endergebnis aussieht. Recht oben in der Ecke steht jeweils die für das Bild ermittelte Durchschnittshelligkeit und daneben die aktuelle Aussteuerung, die sich der ersten Zahl fortlaufend anpasst.
bild0107.png
bild0108.png
bild0106.png
bild0110.png
Renderformat
Wer HDR sehen will, muss ein Rendertarget jenseits der A8R8G8B8 benutzen. Dafür gibt es verschiedene Optionen:

A16B16G16R16F - 16Bit-Fließkomma-Format. Der Klassiker. Wertebereich grob von 65000 bis 1e-4, entspricht 8 Dekaden.
A16B16G16R16 - 16Bit-Festkomma-Format. Also praktisch ushort - Wertebereich von 65000 bis 1, entspricht 4-5 Dekaden.
RGBE - 8Bit-Format, bei dem der Alphakanal zu einem gemeinsamen Exponenten umdefiniert wurde. Wertebereich von 1e36 bis 1e-36, aber kein Alphakanal.
A32B32G32R32F - 32Bit-Fließkomma-Format. Die volle Keule. Wertebereich von 1e36 bis 1e-36.

Das RGBE-Format ist das schnellste, sollte man meinen. Allerdings fällt prinzipiell jedes AlphaBlending aus, selbst ein simples ADD - das muss man selber implementieren. Da wir uns an einigen Ecken auf AlphaBlending verlassen, war das für uns damit gestorben. 32Bit-Floats sind genauso untauglich - es mag der bequemste Weg sein, aber jegliche Grafikkarte kleiner als die Geforce8000-Serie oder Radeon3000-Serie kann darauf auch kein AlphaBlending oder Texturfilter. Ganz abgesehen von dem enormen Speicher- und Bandbreitenverbrauch. Bleiben die beiden 16Bit-Formate - Festkomma oder Fließkomma. Ich wollte hier ursprünglich das Integer-Format nehmen - auch die zweieinhalb zusätzlichen Dekaden Dynamikbereich hätten mir erstmal gereicht. Allerdings reicht der Dynamikbereich eben doch nicht. Allein die Gammakorrektur wirkt wie eine Kompression von 1e4 auf 1e2, da braucht man bereits ein Format mit 4 Dekaden Genauigkeit und hat noch kein bisschen Helligkeit ausgesteuert. Außerdem stellte sich heraus, das NVidia-Karten selbst der neuesten Generation keine 16Bit-Integer-Formate filtern oder blenden können. Bleibt damit der Klassiker: das 16Bit-Fließkomma-Format A16B16G16R16F. Und das ist es dann auch geworden.

Nebenbei: NVidia unterstützt keine Rendertarget-Formate mit weniger als 32Bit pro Pixel. Wir haben z.B. Neben-Rendertargets mit R16F benutzen wollen. Geht prima auf ATI-Karten, auf NVidia scheitert die Texturerzeugung. Wir mussten auf G16R16F aufstocken, dann ist ein Pixel wieder 32Bit groß und NVidia hat wieder mitgespielt.

Bestimmung der Bildhelligkeit
Hier kann man einiges falsch machen. Zunächst die Runterskalierung: wir benutzen 3 Stufen von je 4x4 zu 1, wobei die erste Stufe noch Zusatz-Rechnungen für Bloom macht. Ich habe da früher oft empfohlen, den bilinearen Filter auszunutzen, indem man genau in der Mitte von 2x2 Texeln sampelt und so 2x2 Pixel von der Grafikkarte frei Haus aufsummiert bekommt. In der Praxis habe ich das aber trotz einiger Stunden Jagd mit PIX nicht hinbekommen - die Textur-Zugriffskoordinaten stimmen, aber trotzdem bekomme ich nur einen der 2x2 Texel. Dadurch wurde der Bloom extrem unruhig mit jeder Bildbewegung. Ich habe das DownScaling dann auf 4x4 explizite Texturzugriffe umgebaut. Hier übrigens Vorsicht mit der Mathematik unter SM2.0-Hardware: eine harmlose Zeile wie "tex2D( sampler, texkoord + offset.xy * skal.zw)" wurde zu linearen Mathe-Ops, weswegen der Shader die 64-MatheOps-Grenze von SM2-Hardware gesprengt hatte. Mit "skal.xy" geht es, die Multiplikation lässt sich dann vektorisieren.

Als Helligkeit habe ich die Wurzel des Grauwertes jedes Pixels genommen:

Code: Alles auswählen

        // 4x4 Pixel zusammenrechnen
        float4 f = 0.0f;
        for( float a = 0; a < 16; ++a)
          f += tex2D( TexBild, rein.mTexKoords + gOffset[a] * rein.mOffsetSkal.xy);
        f *= 0.0625f;
            
        // Helligkeit im Alphakanal durchschleifen. 
        static const float3 grau = float3( 0.3f, 0.59f, 0.11f);
        f.a = sqrt( max( dot( f.rgb, grau), 1e-6));                
Die Wurzel war eine Geschmacksfrage, weil mir die Bildhelligkeit sonst zusehr überschwang. Dunkle Stellen wurden damit tatsächlich sogar überkorrigiert, das sah einfach seltsam aus. Auch das "max" sei dringend empfohlen. Nicht nur verhindert es, dass das HDR in wirklich dunklen Ecken aus dem Wertebereich rausläuft, sondern es bekämpft auch beim Rendern entstehende NANs. Auf SM4.0-Hardware (GF8000, Radeon3000) werden Float-Ausnahmen in jeder MatheOp korrekt weitergeführt. Das bedeutet, dass auch nur eine Fläche mit invaliden Texturkoordinaten ausreicht, um da die Tangentenberechnung zu killen, wodurch im Shader die Beleuchtungsberechnung ein NAN ergibt. Wenn man da kein "max" benutzt, pflanzt sich das NAN noch im Bloom fort und führt so großen pechschwarzen Blöcken auf dem Bildschirm. Unbedingt aufhalten. Und ich habe die Erfahrung gemacht, dass es praktisch unmöglich ist, die Grafiker dazu zu erziehen oder/und die fehlerhaften Stellen selbst ausbessern zu wollen. Das nimmt kein Ende. Ganz nebenbei erwähnt: wir bekamen auf NVidia-GPUs in sehr dunklen Ecken ein absurdes graues Bildrauschen rein, dass vom HDR dann stark aufgehellt wurde. Das max() aus obigem Code hat auch dieses seltsame Phänomen entfernt.

Nach der dritten Skalierungsstufe hatte ich damit ein 64stel-Renderziel mit der Helligkeitsverteilung des Bildes. Diese Stufe ging jedes Frame reihum in mehrere Renderziele, wobei ich jeweils in eins gerendert und ein anderes mit der CPU gelockt und ausgelesen habe. Das sollte ursprünglich den CPU-GPU-Sync verhindern, den man sonst mit solchen Aktionen provoziert. Leider prüft sowohl der ATI-Treiber noch der NVidia-Treiber überhaupt nicht, ob das Renderziel noch benutzt wird - ein Lock synct *immer*, selbst wenn vor 20 Frames das letzte Mal da reingerendert wurde. Daher sind die Frameraten auf den Bildern auch ca. 20 bis 50% niedriger als normal. Die Lösung dafür wäre, das Rendertarget mit IDirect3DDevice9::CreateRenderTarget() zu erzeugen, um dann beim Locken D3DLOCK_DONOTWAIT anzugeben. Habe ich aber noch nicht getan, unsere Rendertargets sind momentan nur normale D3D-Texturen, bei denen man diesen Flag nicht benutzen kann.

Licht und Schatten
HDR ist grausam - es bringt jeden kleinen Renderfehler in gleißender Helligkeit hervor. Die oben beschriebene NAN-Fortpflanzung ist nur ein Aspekt dieses Ärgernisses. Wenn die ShadowMapping-Implementation nicht in jeder Lebenslange absolut wasserdicht ist, bekommt man verirrtes Sonnenlicht in dunklen Höhlen, was wegen des HDRs dann klatschhell wird. Wenn die Spiegelebene vereinzelt Fehlpixel von jenseits der Landschaft liest, werden die weithin leuchten. Wir haben dabei auch festgestellt, dass unser Terrain nicht dicht ist. Durch die verschiedenen Transformationsmatrizen für verschiedene Terrainsegmente passen die Eckpunkte der Segmente nicht perfekt aufeinander. Fiel vorher nie jemandem auf, aber jetzt sieht man in dunklen Höhlen Linien aus strahlend weißen Fehlpixeln durch die Wände ziehen. Eine subtile Vergrößerung der Terrain-Meshes an den Kanten brachte Abhilfe.

Nebel
Nebel ist eigentlich eine schlichte, nette Sache: in Abhängigkeit von der Entfernung mischt man in jeden Bildschirmpixel zunehmend die Nebelfarbe rein. Aber was für Außenareale prima funktioniert, wird in Innenräumen mit meist hoher Helligkeitsaussteuerung zu einer weißen Wand, die man vor sich her schiebt. Ich habe dafür momentan noch keine Lösung gefunden. Aktuell haben wir den Nebel so eingestellt, dass er erst ~50m vor dem Spieler überhaupt beginnt. Dadurch wurde die weise Wand so weit rausgeschoben, dass die meisten Höhlen nebelfrei sind. Das ist aber keine Lösung, sondern nur ein Verstecken der Symptome, bis mir was besseres einfällt.

Spiegelungen
Auch Spiegel-Ebenen oder -CubeMaps sollte man jetzt als HDR-Texturen anlegen. Das letzte Bild oben zeigt, wie die Mischung dann aussieht: helle Stellen der Spiegelung überstrahlen korrekt dunkle Untergründe, die Sonne strahlt auch im Wasser noch hell zwischen den Wolken hervor. Vorher hatte man tagsüber draußen nur matte Spiegelungen. Und vor allem in Höhlen hilft die zusätzliche Genauigkeit, die Spiegelungen auch in der dunkelsten Ecke noch ordentlich aussehen zu lassen. Eine 8Bit-Reflection Map brauchte bereits bei HDR x100 ein kunterbuntes Pixelwirrwarr zu Tage.

Gamma-Korrektur
Schon vorher empfehlenswert, aber mit HDR erst wirklich hübsch. Wie ihr sicher wisst, hat jede Grafikkarte eine Helligkeitskorrektur im DA-Wandler. Das Auge nimmt Helligkeiten nur logarithmisch wahr - doppelte Lichtenergie wird weniger als doppelt so hell wahrgenommen. Damit der Standard-Wertebereich von Rot-Grün-Blau trotzdem von 0 bis 1 als linearer Helligkeitsverlauf erscheint, verstärkt die Grafikkarte die hellen Farbwerte. Die genaue Formel ist einstellbar, liegt aber meist im Bereich "pow( farbwert, 2.2f)" - also etwas mehr als eine Quadrierung. Wenn man eine Engine schreibt, will man aber meist, dass der Helligkeitsverlauf als natürlich empfunden wird. Man muss daher die Gammakorrektur der Grafikkarte entweder abschalten oder vorab rückgängig machen, indem man den Ergebnis-Farbwert vor der Ausgabe mit "pow( farbwert, 0.45f)" vorkorrigiert. Wir benutzen stattdessen nur ein "sqrt( farbwert)", das ist minimal schneller. Mit dieser Vorkorrektur überlagern sich dann Farbwerte, wie es das menschliche Auge erwartet. Helle Elemente überstrahlen dunkle, der Helligkeitsverlauf entlang einer zur Sonne geneigten Oberfläche wird glaubwürdig, und vor allem das AlphaBlending sieht besser aus. Das letzte Bild in obiger Liste zeigt das Seewasser, das jetzt nur noch aus einer Spiegeltextur besteht, die mit Alphablending gezeichnet wird. Man sieht dann, dass z.B. die helle Sonnenspiegelung alle Pixel hinter sich überstrahlt, während an dunklen Spiegelungen der Untergrund durchscheint. Das ist nur noch die Folge von AlphaBlending auf HDR-Formaten - es war keine weitere Shaderlogik nötig, um solche natürlichen Effekte zu erreichen.

Das Bild wirkt statisch etwas seltsam, sieht in Bewegung aber viel glaubwürdiger aus als vorher. Übrigens: die Farbtexturen, die man üblicherweise benutzt, sind natürlich auch für die GPU-Gammakorrektur ausgelegt. Wenn man die einfach so weiterverwendet, wird bei denen die oben beschriebene Gamma-Vorkorrektur doppelt angewendet, was das farbliche Erscheinungsbild ruiniert. Ich empfehle dazu, die Farbtexturen im Shader nach dem Samplen zu konterkorrigieren. Theoretisch wäre das wieder ein "pow( diffuse, 2.2f)", aber das ist sehr teuer. Nahezu identische Ergebnisse zeigt ein schlichtes Quadrieren.

So. Theoretisch könnte man noch viel mehr dazu erzählen, aber der Text ist sowieso schon ewig lang. Ich hoffe, es waren ein paar Infos erhalten, die Euch interessieren.

Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Krishty »

Super, einfach super. Vor allem Respekt dafür, das auf SM 2.0 umzusetzen, ohne sRGB-Reads und mit Instruction-Limit.

Zum Thema „Licht und Schatten“ sollte man noch erwähnen, wie gut indirekte Beleuchtung erst mit Linear-Space und HDR aussieht – das sieht man gut im ersten Bild. Kein Vergleich zur gewöhnlichen, gammaüberkorrigierten Beleuchtung.

Was den Nebel angeht, dürfte das Problem nur über recht relativ komplexe Shader lösbar sein … habt ihr eine Heightmap, vergleicht die Höhe jedes Pixels (oder ab SM 3.0 jedes Vertexes) damit und macht die Nebelfarbe schwarz, wenn sie unter der Heightmap liegt (also unterirdisch ist). Am besten mit Bias, damit die Höhleneingänge nicht auch in der Entfernung schwarz wirken.

Dass der Himmel jetzt so schön strahlt freut mich natürlich besonders :)

Wie groß sind nun die Helligkeitsunterschiede bei eurem Content? Bekommt ihr alle Dekaden des Render-Targets voll?

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von eXile »

Von mir aus auch ein herzliches Dankeschön! Ein schöner Erfahrungsbericht ohne SM 4.0 Schnickschnack ;)
Benutzeravatar
Richard Schubert
Moderator
Beiträge: 106
Registriert: 27.02.2009, 08:44
Wohnort: Hohen Neuendorf (b. Berlin)
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Richard Schubert »

Ein toller Beitrag.

sRGB: Vielleicht habe ich falsch verstanden, was genau du anders machst, aber eigentlich kannst du doch auf dem Sampler einstellen (D3DSAMP_SRGBTEXTURE), dass die Farben sRGB konvertiert werden, sodass die manuelle Korrektur in den linearen Raum schon in Hardware ausgeführt wird.

D3DLOCK_DONOTWAIT: Wird eventuell auch nicht helfen, da auch hier die Treiber oft sehr schäbig implementiert sind. Im Normalfall kannst du aber eigentlich darauf verzichten die Daten des heruntergesampleten Rendertargets in den Arbeitsspeicher der CPU zu laden. Die Auswertung/Anpassung der Helligkeit lässt sich komplett auf der GPU erledigen. Mittlerweile hat dazu auch schon jemand ein Paper bzw. Artikel für ein aktuelles Shader Gems Buch geschrieben.
Produktivität über Performance - XNA Creators Club
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Schrompf »

Danke für die netten Kommentare. Da hat sich das Tippen doch gelohnt :-) Zu den einzelnen Fragen:

@Krishty: Ja, die indirekte Beleuchtung bzw. die Überlagerung von indirekter und direkter Beleuchtung hat mit Gammakorrektur enorm dazugewonnen. Das sieht einfach geil aus... :-) Allerdings war da dann auch HDR nötig. Wir berechnen bei uns für die ganze Welt pro Instanz / Objekt / Vertex das indirekte Licht, indem wir uns auf den entsprechenden Punkt setzen und eine 180°-Halbkugel ausrendern, die wir dann als Durchschnittsfarbe oder SH für die indirekte Beleuchtung benutzen. Das dann mehrfach iterativ unter Verwendung der vorherigen indirekten Beleuchtung - so bekommen wir auch mehrfache Reflektionen, und das Ergebnis ist immer physikalisch korrekt. Das ist aber nicht zwangsweise erstrebenswert: unsere Gebäude sind im Innern momentan arschdunkel, einfach weil die Häuser passend zum Szenario nur kleine und wenige Fenster haben. Dort hat HDR eine Menge bewirkt. In der Taverne sieht es z.B. so aus:
bild0109.png
Hinter der Kamera ist noch ein Fenster, deswegen wird es von dort heller. Die Zahlenwerte dort sind selbst nach drei Iterationen noch im Bereich 10^-2 bis 10^-3 - bei einer Sonnenhelligkeit von ~3. Dass man dort überhaupt was sieht, ist zum Einen der Gammakorrektur und zum Anderen der HDR-Augenanpassung geschuldet. Der Wertebereich geht bei uns von 0 (Höhle hinter der zweiten Biegung) über 1e-5 (dunkelste sichtbare Ecken durch den letzten Bounce) bis zu 100 (Sonnenscheibe). Man könnte nach oben noch weiter aussteuern, aber nach unten sind wir an der Grenze des fp16-Formats. Was ich schade finde, weil ich trotz des astronomischen Rechenaufwands gern noch ein paar mehr Bounces haben wöllte, um in Höhlen das Licht noch etwas weiter reichen zu lassen. Wird wohl aber darauf hinauslaufen, dass wir dort dann Helferlichter verteilen.

Zum Thema "Nebel" müsste man theoretisch, wenn man physikalisch korrekt sein will, ein Streckenintegral über die beleuchtete Nebelfarbe bis zur Oberfläche machen. Meine Überlegungen gehen aber eher dahin, konvexe Volumen in den Höhlen zu verteilen, anhand derer ich die sichtbare Tiefe im Volumen berechnen kann. Diese Tiefe ziehe ich dann von der wirksamen Nebelentfernung ab und bekomme so nebelfreie Höhlen und korrekten Nebel außerhalb. Das würde nur einen zusätzlichen Kanal im Rendertarget erfordern. Das Integral über die indirekten Beleuchtungsmesspunkte dagegen... oh Himmel.

@Richard:

sRGB - wäre natürlich fein, wenn ich die Multiplikation von der Graka automatisch machen lassen könnte. Aber ich weiß nicht, wie verbreitet diese Option ist. Hab auf die Schnelle nichts dazu in der Doku oder in den Caps gefunden. Muss ich mir später nochmal anschauen. Und Danke für die Tipps zu DONOTWAIT - da kann ich mir ersparen, das auszuprobieren. Auf der GPU wollte ich das eigentlich nicht haben, weil ich da für meinen Geschmack zu wenig Kontrolle habe. Und es einen zusätzlichen Texturzugriff im PostProcessing erfordern würde - der braucht einige Takte, auch wenn er aus dem Cache kommt. Wie die Genauigkeit ist, weiß ich da auch nicht - auf der CPU benutze ich einen normalen Float, der bislang auch hinreichend langsame Anpassungen gut hinbekommt.

Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Richard Schubert
Moderator
Beiträge: 106
Registriert: 27.02.2009, 08:44
Wohnort: Hohen Neuendorf (b. Berlin)
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Richard Schubert »

sRGB Read sollte ab RADEON 9800 also der ersten DX9 Generation für die gängigsten Texturformate unterstützt werden. Kann man auch über das D3DUSAGE_QUERY_SRGBREAD flag abfragen.
Aber sowohl in der CardCaps.xls aus dem DX SDK als auch auf http://www.netsphere.jp/dxinfo/ kann man die Daten leider nicht verifizieren, hast du recht. Sehr schade eigentlich.

Auf der GPU hast du eigentlich genau die gleiche Kontrolle wie auf der CPU. Dafür muss man sich natürlich hier und da was einfallen lassen und evtl ist dazu auch Shader Modell 3.0 nötig, aber man kann das eigentlich schon machen, ohne dass man selbst darüber Bescheid weiß, was die Graka da macht. :D
Die Genauigkeit mit dem Float bekommt man mit einem 1x1 R32F Rendertarget auch hin. So mache ich das jedenfalls bisher.
Produktivität über Performance - XNA Creators Club
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Gelöschter Benutzer »

Argh :) Jetzt habt ihr mich auf HDR gelenkt und jetzt interessiert es mich auch noch.

So einiges konnte ich mir jetzt in den Posts an Überblick verschaffen, jedoch habe ich einige Fragen, die mir offen geblieben sind. Das liegt wohl daran, dass ich die ganze Zeit im RGB-Raum war.

Testweise habe ich jetzt mal in DirectX 10 das Back Buffer Format von R8G8B8A8_UNORM auf R16G16B16A16_FLOAT gesetzt. Habe ich es richtig verstanden, dass man den Render Target des Swap Chains auf dieses Format setzt? Das habe ich jetzt mal gemacht und mal beim Swapchain Clear() aufgerufen mit verschiedenen Farbkonstanten. Vielleicht liegt es an voriger falscher Idee, aber was sind den bei HDR Wertebereiche die auf den Pixel kommen? Ich wollte mir erstmal mit clear() einen Überblick auf das Verhalten von Farbwerten bilden.

Eine andere weise ist, wie ich jetzt die Posts verstehen kann, als Endmuster ein R8G8B8A8_UNORM Render Target zu verwenden. Allerdings müssen die berechneten Werte vom zweiten Render Target vom HDR Format R16G16B16A16_FLOAT in das RGB-Format umberechnet werden. Ist das eher so zu verstehen? Bzw. wenn ja, wie berechnet man sowas um?

Wenn ich mir die DX SDK Samples ansehe oder von nVidia, dann kommt mir dort viel Schnick Schnack nebenbei vor und ich kann mich auf das eigentliche Problem nicht konzentrieren. Gibt es da ein Beispiel das mal relativ nackt ist damit man sich in das Thema einarbeiten kann?
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Krishty »

Patrick,
Deine zweite Vermutung ist richtig. Back-Buffer-Formate sind in D3D10 immer _UNORM, denn _FLOAT können die Bildschirme garnicht verarbeiten. Du musst interne Puffer für HDR-Bilder erzeugen, sie am Ende mit einem Tonemapping-Operator (googlen) runterrechnen und in den Back-Buffer schreiben. Übrigens arbeitet man auch beim Einsatz von HDR-Rendering meist mit RGB ;)


Schrompf,
Habt ihr einen „normalen“ Tonemapping-Operator genutzt oder so einen „edlen“, der helligkeitsbedingte Farbverschiebungen und das Kontrastempfinden berücksichtigt?
Wie lange dauert die Berechnungszeit für die Indirekte Beleuchtung? Und vor allem, wie geht ihr dabei mit dem Tag-Nacht-Rhythmus um?
Der Wertebereich von Halfs geht afaIk bis rund 65000, könntet ihr nicht die Helligkeit der Sonnenscheibe darauf normalisieren (also alles Licht 500× heller machen)? Dann müssten euch nach unten noch mehr Werte zur Verfügung stehen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Zudomon »

Eigentlich ist HDR nichts besonderes. Solange man im PS was berechnet, ist das HDR. Erst sobald man es in das Rendertarget schreibt, geht der hohe Kontrast verloren. Die Rendertargets jenseits der 8 Bit braucht man nur, wenn man die Ergebnisse zwischenspeichern möchte. Aber auch das ist eigentlich unnötig.

Vor 3 Jahren hatte ich mal logarithmisches Tonemapping auf mehrere Lichtquellen angewendet. Allerdings habe ich da keine besonderen Formate benutzt. Also alles war nur 8 Bit! Die einzelnen Lichtquellen wurden nach und nach auf das Bild addiert. Es war also nicht einfach "alles im Shader berechnen und Tonemapping drüber". Das ganze lief sehr schnell, da ja kein Overhead durch die Speicherlastigen Rendertargets dazu kam. Und es lief auf jeder PS2.0 Hardware.
8 Bit HDR/Tonemapping/Bloom
8 Bit HDR/Tonemapping/Bloom
@Schrompf
Euer indirektes Licht ist super! :D So hatte ich das bei mir auch gemacht. Allerdings mit Lightmaps.

zfx_14.jpg
Das funktioniert auch gut mit direktem Licht. Auf den folgenden beiden Bildern gibt es keine Lichtquellen mehr... das komplette Licht kommt von den Texturen.
zfx_15.jpg
zfx_16.jpg

Hab die alte 8-Bit HDR Demo noch drauf. Leider ohne den Bloom Effekt, dafür mit soften StencilShadows. Wobei die Schatten stark auf die Performance gehen, aber vielleicht ist ja trotzdem mal interessant zu sehen:
zfx_hdr.zip
(335.4 KiB) 216-mal heruntergeladen
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 577
Registriert: 05.07.2003, 11:17

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Lord Delvin »

Zudomon hat geschrieben:Auf den folgenden beiden Bildern gibt es keine Lichtquellen mehr... das komplette Licht kommt von den Texturen.
Wie macht man denn sowas mit nem Rasterizer?
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Gelöschter Benutzer »

Also verläuft das so, wenn ich Zudomons und Krishtys Beiträge verstehe:
  1. Render Target mit R16G16B16A16_FLOAT erzeugen.
  2. Ganz normal in das Gleitkommamodellformat rendern
  3. Post Processing: Einen Tonemapping-Filter über den Shader laufen lassen (, eventuell einen Bloom-Shader zur Lichtstreuung dazu)
  4. Farbwerte vom Gleitkommamodell in das R8G8B8A8_UNORM-Format übertragen
  5. Bild anzeigen
Was ich jetzt dabei vermute:
Der Tonemappingfilter ist eine einfache Funktion, die die Helligkeit des Pixels erhöht bzw. verringert. Sowas könnte auch rein theoretisch ein beliebiger Filter sein, um Farben hervorzuhenen: f(x, p) = ln(x^p + 1). x und p haben jeweils Elemente [r g b a] im reellen Bereich. Es gibt dabei (logischerweise) viele Funktionstypen, da hier nur eine Skalierung der Farbwerte vorgenommen wird.

Diese resultierenden Farben werden dann auf den Back Buffer geformt. Darf ich g(x) = unsigned char(x * 255.0f) vermuten?

Wenn das so wäre, wäre es ja tatsächlich kein großer heißer Brei. Wenn die vom Pixel Shader berechneten Farbwerte nicht herunterskaliert werden, ist natürlich eine höhere Genauigkeit in den Texturen gespeichert. Das genau Effekte wie Blooming und ich sage mal Farbskalierung ein großen Vorteil wegen der relativen Beseitigung der Ungenauigkeit haben wäre ein logischer Schritt.

Der Rasterizer dürfte in D3D10 relativ unbeeindruckt weiterrödeln (meiner Meinung nach)...
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Schrompf »

Krishty hat geschrieben: Habt ihr einen „normalen“ Tonemapping-Operator genutzt oder so einen „edlen“, der helligkeitsbedingte Farbverschiebungen und das Kontrastempfinden berücksichtigt?
Einen normalen. Bzw. "banalen", nämlich eine schlichte Multiplikation. Ein bisschen ToneMapping, um den Verlust des Farbsehens bei Nacht zu simulieren, will ich noch einbauen - ich hoffe, dadurch sehen Nachtszenen glaubwürdiger aus. "Nachts sind alle Katzen grau", hat damals der Volksmund schon treffend ToneMapping charakterisiert :-)
Wie lange dauert die Berechnungszeit für die Indirekte Beleuchtung? Und vor allem, wie geht ihr dabei mit dem Tag-Nacht-Rhythmus um?
Der Wertebereich von Halfs geht afaIk bis rund 65000, könntet ihr nicht die Helligkeit der Sonnenscheibe darauf normalisieren (also alles Licht 500× heller machen)? Dann müssten euch nach unten noch mehr Werte zur Verfügung stehen.
Den Zahlenbereich noch zwei Dekaden nach oben zu schieben wäre ne Idee. Dann müsste ich nur noch zwei drei weitere Iterationen des indirekten Lichts berechnen. Leider ist mir bislang keine gute Methode eingefallen, wie man herauskriegen könnte, wo noch weitere Iterationen nötig sind. Eine Iteration für den gesamten Startsplitter (etwa 1km^2) braucht auf meinem Intel Core2 Quad etwa zwei Stunden. Graka ist dabei egal, die primäre Rechenzeit geht dafür drauf, die DrawCalls zu machen, um die Umgebung eines Punktes in eine CubeMap zu rendern. Bzw. in eine halbe CubeMap, wenn ich nur die 180°-Halbkugel brauche. Zu berechnen sind 356k Vertex-Samples (also halbe CubeMaps) und 60k SH-Samples (also ganze CubeMaps). Plus am Ende nochmal 40k SH-Samples für das Messpunkt-Raster, anhand dessen bewegliche Objekte ihre Ambient-SH beziehen.

Das ist der Nachteil, wenn man die Grafikkarte dazu nimmt: man kann es kaum sinnvoll parallelisieren. Wenn ich dafür Raytracing nehmen würde, wäre die Aufteilung auf die 4 Cores trivial. Allerdings müsste ich dazu halt die ganze Welt in eine Beschleunigungsstruktur packen - die bisherigen Strukturen sind dafür nicht ausgelegt. Das ist bei der Vielfalt von Klassen, die bei uns inzwischen die sichtbare Welt ausmachen, ein ziemlicher Packen Arbeit. Wenn ich irgendwann mal viel freie Zeit habe, versuche ich mal, das Rendern auf einen zweiten Core auszulagern.
Zudomon hat geschrieben:Die Rendertargets jenseits der 8 Bit braucht man nur, wenn man die Ergebnisse zwischenspeichern möchte. Aber auch das ist eigentlich unnötig.
Das ist nur unnötig, wenn Du wirklich mit einem einzigen Pass überall auskommst. Sobald sich irgendwo Materialien überlagern, Partikel dazukommen oder Du mehr als einen Pass für viele Lichtquellen brauchst, ist es vorbei. Denn auch die Gamma-Korrektur braucht eine gewisse Genauigkeit, und die sollte man tunlichst erst auf das finale Bild anwenden. 8Bit pro Kanal führen da zu hässlichen Banding-Artefakten.

Die Bestimmung der Aussteuerung dagegen könnte man auch mit 8Bit-Rendertargets machen: einfach heller drehen, wenn das Bild sehr dunkel ist, oder dunkler, wenn viel weiß vorkommt.

Zum Thema Partikel übrigens: auch die müssen jetzt auf irgendeine Art beleuchtet werden. Wir rendern z.B. einen Wasserfall über schlichte AlphaBlend-Partikel "Weiße Gischt" - aber das Weiß ist halt eine konstante, wie bei Partikeln halt üblich. Nachts bei 1000x dunklerer Szene leuchtet der Wasserfall wie ein atomarer Unfall. Zumindest irgendeine Art Skalierung mit dem indirekten Licht muss ich da auf jeden Fall noch einbauen.

Übrigens: Tolle indirekte Beleuchtung! Ich mach bei Gelegenheit auch nochmal ein Bild ohne direkte Beleuchtung, damit man mal sieht, wie sehr selbst so eine diffuse Waldszene von ordentlichem Ambient Light profitiert.

@Patrick:

HDR-Rendering ist im Grunde kein wirkliches Problem. Was ich mit meinem Start-Beitrag aber sagen wollte: das Drumherum wird Dich sehr viel länger beschäftigen. In ner TechDemo mit ein paar schlichten Objekten ist das schnell gemacht. Richtige Spielszenen dagegen sind sehr vielfältig, man ist noch lange damit beschäftigt, auch die letzten Grenzfälle vernünftig aussehen zu lassen.

Die Abbildung HDR auf LDR am Ende kannst Du tatsächlich frei wählen, wie Du magst. Wir machen da ein "sqrt( HDR-Wert * Aussteuerung)" - also eine simple Helligkeitsskalierung, und das sqrt() als Gamma-Vorkorrektur wie oben beschrieben. Bloom kommt dann nur noch oben drauf, um das Überstrahlen heller Stellen auf benachbarte Sichtbereiche zu simulieren, wie es im menschlichen Auge passiert. Die riesigen Lensflares dagegen sind Artefakte, wie sie bei Kameras auftreten. Wenn Du ein Spiel schreibst, das aus Sicht eines Menschen passiert, solltest Du auf sowas eher verzichten. Wenn Du dagegen ein Spiel schreibst, bei dem man die Welt aus einer Kamera sieht (z.B. Roboter oder Raumschlacht oder wasweißich), dann wäre so ein Sechsfach-Stern wie bei Zudomons Bild angebracht.

Der eigentliche Trick bei HDR ist aber nur die Dynamikbereich-Anpassung beim HDR->LDR - und da tut es im einfachsten Fall wirklich eine simple Multiplikation. Die optische Wirkung von HDR kommt meiner Meinung nach durch den Bloom, weil Bloom dem menschlichen Auge vorgaukelt, dass die umbloomten Stellen noch heller sind. Theoretisch geht es da nicht heller als "weiß", aber praktisch produziert das Sehzentrum des Spielers vor dem Bildschirm dann den Eindruck, als wäre es da noch heller. Und HDR imitiert über die Nachführung der Aussteuerung die menschliche Augenanpassung an verschiedene Helligkeiten. Darauf sind wir wie gesagt angewiesen, weil es bei uns in Gebäuden z.B. physikalisch korrekt saudunkel ist. Auch das kann man mit Helferlichtern und gutem Leveldesign machen, anstatt die HDR-Keule rauszuholen - ob Du das im Spiel haben willst, ist eine Geschmacksentscheidung. Die meisten Spiele heutzutage benutzen HDR nur als optisches Gimmick mit sehr kleinen Wertebereichen und machen an all den Stellen, wo die Helligkeit wirklich drastisch schwanken würde, lieber einen Map-Wechsel rein. Fallout3 wäre ein Beispiel dafür, oder auch Crysis. Kann man wie gesagt machen, wie man mag.

Bye, thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Zudomon »

@Lord Delvin
Eigentlich ganz einfach. Man nehme eine pechschwarze Szene... da setzt man eine helle Textur rein. Und nun läuft das ganze so, wie Schrompf es schon gesagt hat. Man betrachtet an jedem Punkt, den man beleuchten will, wie viel Licht aus der Umgebung hinein fällt. Macht man diesen Schritt nur ein einziges mal, dann hat man die "direkte Beleuchtung". Wenn man das ganze wiederholt, bekommt man die "indirekte Beleuchtung". Da das ganze für die Lightmaps erstellt wird, ist das dem Rasterizer egal, ob man echte Lichtquellen hat, oder die Lichtinformationen aus Texturen liest.

Auf dem folgenden Bild sind die Lightmaps nur zum Teil berechnet, und da ich das in der ersten Iteration abgebrochen habe, ist auch nur das direkte Licht drauf. Aber was ich zeigen wollte kann man, kann man erkennen. Und zwar hat man durch diese Technik die möglichkeit, auch bunte Texturen Licht werfen zu lassen. Man sieht, wie der ColaAutomat weißes und rotes Licht auf den Boden wirft. Wäre etwas ganz dicht vor dem Automat, so das die diffuse Streuung nicht so extrem ist, dann würde sich das Bild da abzeichnen. Auch der Schatten der Wand, der direkt an der Wand scharf ist und dann ins weiche verläuft kommt automatisch zu stande! Es werden keine Schattensampels oder ähnliches dafür berechnet. Noch natürlicher geht es nur mit Photonenmapping.
zfx_17.jpg
@Patrick
Wenn du alles in einem SinglePass renderst, geht es noch einfacher:
R8G8B8A8 als Rendertarget lassen. Berechnungen im Shader ganz normal vornehmen.
Und eine Tonemapfunktion am Ende des Shaders aufrufen...

Code: Alles auswählen

float4 tonemap(float4 c, float lum, float key)
{
  float ln  = 1-exp(-lum * key);
  c.rgb = c.rgb / lum * ln;
  return c;
} 
Diese Funktion berechnet das logarithmische Tonemapping.
Allerdings brauchst du die Luminance des Bildes. Das ist folgende erste Zeile. In der zweiten wird die Funktion dann angewendet. Der Key-Wert, hier 0.1 steht für die Belichtungszeit. So weit ich weiß sollte das etwa 0.02 - 0.5 sein. Je nachdem, wie hell die Szene sein soll. Da sollte man aber mal Fachliteratur hinzu ziehen, um "realistische Werte" für die Belichtungszeit zu bekommen, oder umgekehrt, im Shader mit "echter Helligkeit" arbeiten und dann die Belichtungszeit diesem anpassen.
Wenn man die gemittelte Luminance der Szene ermittelt, kann man langsam in den Key-Wert einfließen lassen. Dann hat man den Effekt, als ob sich das Auge anpasst.

Code: Alles auswählen

float lum = dot(col.rgb, float3(0.27, 0.67, 0.06));
col = tonemap(col, lum, 0.1);
Den Bloomfilter bekommste hin, indem du einfach einen den Teil des Bildes, der auslaufen soll in eine weitere Textur renderst.
Es lassen sich auch andere interessante Effekte damit bewerkstelligen.
Hatte mal, dass sich das übersteuerte Licht ins Auge einbrennt für etwa 1-2 Minuten. :D
Wenn man etwas zu lange auf zu helle Flächen schaut, dann kommen ja, je nach Farbe bestimmte Artefakte ins Bild. Im gelblichen Licht sind die ja so türkis/grün. Vielleicht erkennt man das auf dem Bild etwas.
zfx_18.jpg
@Schrompf
Schrompf hat geschrieben:
Zudomon hat geschrieben:Die Rendertargets jenseits der 8 Bit braucht man nur, wenn man die Ergebnisse zwischenspeichern möchte. Aber auch das ist eigentlich unnötig.
Das ist nur unnötig, wenn Du wirklich mit einem einzigen Pass überall auskommst. Sobald sich irgendwo Materialien überlagern, Partikel dazukommen oder Du mehr als einen Pass für viele Lichtquellen brauchst, ist es vorbei. Denn auch die Gamma-Korrektur braucht eine gewisse Genauigkeit, und die sollte man tunlichst erst auf das finale Bild anwenden. 8Bit pro Kanal führen da zu hässlichen Banding-Artefakten.
Wie ich schon in meinem Beitrag erwähnt habe, hatte ich da wirklich 8Bit benutzt und das mit mehreren Renderpasses:
* Ambientes Licht
* Für jedes Licht Diffuse Farbe
* Textur drüber
* Für jedes Licht Specular
Das ganze ohne ColorBandings oder sonstige Renderartefakte und mit logarithmischem Tonemapping! Und das ganze mit einem 8Bit Rendertarget. Also ich würde ja ganz stur behaupten das das geht, man muss halt nur wissen, wie. ;)
Und da in der Demo sogar jedes Licht seinen eigenen Stencilschatten bekommt, sollte ja klar sein, dass es sich hier um Multipass-Rendering handelt.
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Gelöschter Benutzer »

HDR betrachte ich zum Beispiel praktisch sehr gut sinnvoll wenn ich in meiner Zugsimulation aus dem Tunnel brause. Schaut man aus dem langen Tunnel heraus, sieht man bis zur Ausfahrt eher ein relativ gleißendes Weiß und hoffentlich gut gemauerte Tunnelanlagen. Nur wenig sieht man vom Rest. Dann wird alles erstmal weiß überstrahlt und wird dann wieder relativ normal.

Oder eine Durchfahrt durch eine etwas längere Brücke: Wird am Anfang ein wenig dunkel, dahinter heller. Nach der Vorbeifahrt wieder kurz deutlich heller und dann normal. Das wäre ein Einsatz fürs Tonemapping.

Andere Szene, die wohl alle kennen. Schöner Sommertag und freier Himmel. Kaum dreht man sich um, kommt eine dicke fette dunkle Gewitterfront an - sieht eher dunkelblau als grau am Regentag aus. Ist man in der Gewitterwolke, sieht das ganze wieder wie ein bedeckter Regentag aus. Aber das wäre ein Effekt wie du ihn mit den Lichtquellen beschreibst.

Allerdings sind solche Dinge mal über ein paar Lichtquellen so glaubhaft nicht zu illuminieren. Daher betrachte ich das als gute Lösungsmöglichkeit.

@Zudomon: Das ist mir auch schon begegnet beim Atmospheric Scattering in abgewandelter Form. Das ist auch Möglich. Aber für mich ist wichtig, dass ich weiß wie ich auf die Technik zurückgreife, damit ich das mal später auch direkt einbinden kann ohne viel in Kanten beißen zu müssen.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Zudomon »

@Patrick
Okay, wenn du für später gewappnet sein möchtest, dann musst du es so machen, wie du schon sagtest. Also alles in ein Rendertarget, was jenseits der 8Bit liegt.
Dann hast du das Bild als RAW-Daten zur Verfügung und kannst damit verschiedene Post-Processing Effekte realisieren.
Und wenn du dann die finale Komposition zusammenrenderst, lässt du das durch den Tonemappingfilter laufen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Krishty »

Schrompf hat geschrieben:Einen normalen. Bzw. "banalen", nämlich eine schlichte Multiplikation. Ein bisschen ToneMapping, um den Verlust des Farbsehens bei Nacht zu simulieren, will ich noch einbauen - ich hoffe, dadurch sehen Nachtszenen glaubwürdiger aus. "Nachts sind alle Katzen grau", hat damals der Volksmund schon treffend ToneMapping charakterisiert :-)
Echt, nur eine Multiplikation und danach Gamma-Korrektur? Keinen Logarithmischen Operator? Habt ihr einen logarithmischen schonmal ausprobiert, insbesondere in Indoor-Bereichen? Langsam dämmert mir, warum ihr mit so wenigen Dekaden auskommt, während mein Tag-Nacht-Rhythmus sich nicht unter zehn Dekaden komprimieren lässt :shock:
Eine Iteration für den gesamten Startsplitter (etwa 1km^2) braucht auf meinem Intel Core2 Quad etwa zwei Stunden. Graka ist dabei egal, die primäre Rechenzeit geht dafür drauf, die DrawCalls zu machen, um die Umgebung eines Punktes in eine CubeMap zu rendern.
Okay, du hattest ja früher schonmal gesagt, dass ihr CPU-limitiert seid.
Das ist der Nachteil, wenn man die Grafikkarte dazu nimmt: man kann es kaum sinnvoll parallelisieren.
Soll ich jetzt mit D3D10 anfangen – bis zu acht 180°-Projektionen in einem Pass? ;) Neee. Ich denke eher, das liegt daran, dass ihr euch mit dem 180°-Panorama die präziseste Form der Global Illumination ausgesucht habt, die man überhaupt durchführen kann. Bei anderen Annäherungen, wie einer Lichtquelle pro beleuchteter Fläche, sieht das anders aus, aber dafür ist die Qualität dann nicht ganz so gut.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Zudomon »

@Schrompf
Raytracen wäre meiner Meinung nach keine gute Idee. Schon allein deswegen, weil es langsamer wäre, als zu Rasterizieren. Dann kommt dazu, dass ihr dann auch die Texturen sampeln müsstet, damit dessen Farbe richtig einfließt. Wenn man dann noch bedenkt, das man, um das korrekte Ergebnis zu erhalten, auch die Schatten mit einbeziehen müsste, die durch maskierte Texturen fallen, wäre das schon einiges an Aufwand.
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 577
Registriert: 05.07.2003, 11:17

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Lord Delvin »

Schrompf hat geschrieben:Das ist der Nachteil, wenn man die Grafikkarte dazu nimmt: man kann es kaum sinnvoll parallelisieren. Wenn ich dafür Raytracing nehmen würde, wäre die Aufteilung auf die 4 Cores trivial. Allerdings müsste ich dazu halt die ganze Welt in eine Beschleunigungsstruktur packen - die bisherigen Strukturen sind dafür nicht ausgelegt. Das ist bei der Vielfalt von Klassen, die bei uns inzwischen die sichtbare Welt ausmachen, ein ziemlicher Packen Arbeit. Wenn ich irgendwann mal viel freie Zeit habe, versuche ich mal, das Rendern auf einen zweiten Core auszulagern.
Öhm also es ist vermutlich nicht *ganz* so einfach wie du dir das vorstellst. Ich hab echt lange nachdenken müssen, bis ich einen Weg gefunden hab, der lange linear skaliert. Falls du offline irgendwelchhe light/reflection/whatever-maps aktualisieren willst is das aber vielleicht ein thema...kommt halt sehr auf die auflösung dieser maps an und wie gut du rausfinden kannst, welche maps(am besten punkte) du jetzt sinnvoller weise aktualisieren willst.
Allerdings glaub ich nicht, dass es die mühe wert ist, weil es mir so scheint, dass rasterizer schatten/reflexion/etc. nur deswegen nicht so gut aussehen lassen, weil man halt irgendwelche texturen dafür missbraucht und die auflösung halt immer zu klein ist, wogegen raytracer das halt per pixel machen. Dafür am wir halt wahnsinnige probleme mit *weich* in jeder form.

Und das Problem mit deinen Strukturen sollte auch eher mäßig sein, weil du ja nem raytracer quasi alles geben kannst, da der ja softwaremäßig arbeitet. Wenn du nur wissen willst, obs theoretisch machbar ist, dann kannst dus ja auch in ner liste speichern und den profiler fragen, wie viel zeit der rest so braucht.

Wenn du willst kann ich dir irgendwann mal unseren Code geben, damit du mit rumspielen kannst, aber ich glaub nicht, dass es sich in naher Zukunft lohnt.

(Ist spannend zu sehen, was die beiden sachen können und was nicht, vor allem hätte ich nicht gedacht, dass es auf ner graka nen unterschied macht ob man 16bit oder 32bit floats nimmt, bei uns is das irgendwie nie zur diskussion gestanden, weil die hardware halt nur int oder 32bit floats kann und die floats viel schneller waren ( wegen normieren und so nem zeuch, das bei floats halt erstmal wegfällt))
Ich hab tonemaping bei uns mal versucht, aber der shader war irgendwie ungeschickt...sah nicht gut aus:-/

Wie viel code ist das bei euch eigetlich? Also das ganze lighting/reflaction Zeug?

Edit: @Zudomon: Naja ist nur langsamer, wenn die Ressourcen sonst was zu tun hätten. Wenn du 6 Cpus hast, die sowieso nur rumidlen, dann können die dir auch deine lightmaps reparieren:)

Gruß
LordD
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Zudomon »

@Lord Delvin
Lord Delvin hat geschrieben: Allerdings glaub ich nicht, dass es die mühe wert ist, weil es mir so scheint, dass rasterizer schatten/reflexion/etc. nur deswegen nicht so gut aussehen lassen, weil man halt irgendwelche texturen dafür missbraucht und die auflösung halt immer zu klein ist, wogegen raytracer das halt per pixel machen. Dafür am wir halt wahnsinnige probleme mit *weich* in jeder form.
Vor allem ist das Kuriose an der ganzen Sache, das in Raytracern Optimierungen wie Cubemaps und Shadowmaps angewendet werden. Weil sampeln ist nicht umsonst.
Lord Delvin hat geschrieben: Edit: @Zudomon: Naja ist nur langsamer, wenn die Ressourcen sonst was zu tun hätten. Wenn du 6 Cpus hast, die sowieso nur rumidlen, dann können die dir auch deine lightmaps reparieren:)
Die Frage ist immer, was man machen will und wie viel man sich einfallen lässt. Das zweite Bild in meinem ersten Post in diesem Thread (zfx_14.jpg), da hatte ich aufwendig die Schatten geraytraced. Ich glaube 128 Sampels waren das. Obwohl das mit Octrees usw. optimiert war, hat das seine Zeit gedauert. Und was wäre schneller, als 128 mal Schatten sampeln??? Genau, garnicht sampeln! Ich hab ja ein Bild mit dem Cola-Automaten gepostet, wo man die Schattenkante sieht. Da die Information aus direkt aus dem rasterizierten Bild stammt, brauchte ich für den WEICHEN Schatten nur ein einziges mal Sampeln. Naja, aber müsst ihr wissen, was ihr mit eurer freien CPU-Power so anstellt. Aber mir wären 6 CPUs zu schade um etwas zu berechnen, was man auf der anderen Seite gratis bekommt, auch wenn die sonst nichts zu tun hätten. ;)
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Schrompf »

Lord Delvin hat geschrieben: Öhm also es ist vermutlich nicht *ganz* so einfach wie du dir das vorstellst. Ich hab echt lange nachdenken müssen, bis ich einen Weg gefunden hab, der lange linear skaliert.
Ich würde dazu die Threading Building Blocks nehmen, die sauber skalieren bis sonstwohin. Raytracing ist in seiner Basisform ein rein lesender Prozess und damit perfekt parallelisierbar. Erst wenn man Caches einbaut oder die räumliche Kohärenz benachbarter Strahlen auszunutzen beginnt, könnte es kniffliger werden.

In meinem Fall ging es ja um einen reinen Offline-Prozess. Ich muss für 400k Messpunkte den Lichteinfall aus der Umgebung berechnen. Momentan werfe ich dafür einfach die Engine an wie für ein normales Bild auch. Jeweils in drei CubeMap-Seiten bzw. 6 CubeMap-Seiten, wenn ich eine SH haben will. Das hat den Vorteil, dass ich *exakt* den Lichteinfall bekomme, den man auch auf dem Bildschirm sieht. Und all die verschiedenen Objekte, die den Szenegraphen ausmachen, werden genauso angezeigt wie im Spiel auch. Ich könnte jetzt natürlich anfangen, die komplette Szene in einen riesigen kd-Tree einzusortieren, um dann auf den CPUs mit Raytracing den Lichteinfall zu bestimmen. Aber es wäre halt ein ordentliches Stück zusätzliche Arbeit für all die verschiedenen Spezialklassen, die die Szene ausmachen.
Wenn du willst kann ich dir irgendwann mal unseren Code geben, damit du mit rumspielen kannst, aber ich glaub nicht, dass es sich in naher Zukunft lohnt.
Lohnt sich nie. Denn wie gesagt: die Hauptarbeit wäre es, die ganzen für's Rasterizing bestimmten Klassen für's Raytracing umzusetzen. Manches (z.B. das Wasser) geht viel schneller, anderes (z.B. alles mit Bones) wäre schwerer.
(Ist spannend zu sehen, was die beiden sachen können und was nicht, vor allem hätte ich nicht gedacht, dass es auf ner graka nen unterschied macht ob man 16bit oder 32bit floats nimmt, bei uns is das irgendwie nie zur diskussion gestanden, weil die hardware halt nur int oder 32bit floats kann und die floats viel schneller waren ( wegen normieren und so nem zeuch, das bei floats halt erstmal wegfällt))
Die Ära der 16Bit-Floats war kurz, und nur auf NVidia beschränkt. Das ist inzwischen aber wieder vorbei. Aber auch CPUs sind inzwischen ziemlich fix in der Verarbeitung von floats... es gibt heutzutage keinen Grund mehr, Festkommamathematik der Fließkommamathematik vorzuziehen.
Wie viel code ist das bei euch eigetlich? Also das ganze lighting/reflaction Zeug?
Was ist denn das für eine Frage? Der Shadercode nur für Licht und Schatten sind ein paar hundert Zeilen HLSL, aufgrund der verschiedenen Lichtquellentypen und Qualitätsstufen, die zur Wahl stehen. Der Wassershader ist grob ein Dutzend Zeilen HLSL. Beantwortet das Deine Frage?

@Krishty:
Im ToneMapping steckt bei uns keine Magie oder sowas... ich glaube, Du bist da auf der falschen Fährte. Wir kommen nur deswegen mit sehr viel weniger Dynamikbereich aus, weil unsere Helligkeitswerte handgetrimmt sind. Die Nacht ist bei uns halt nur 100x dunkler als der Tag. Du gehst an die Sache ja ganz anders ran: physikalisch korrekt. Während wir nur an den Werten schieben, bis es gut aussieht :-)

Aber die Anspielung auf D3D10 bringt mich gerade auf eine Idee... wenn ich einfach ein neues Projektionsfragment erfinde, dass eine 180°-Halbkugel auf eine 2D-Textur projeziert, komme ich mit einem Renderdurchgang anstatt dreien aus. Die Formel für die Projektion müsste man halt clever wählen, so dass die Verteilung über die Textur halbwegs gleichmäßig ist, damit Licht aus gewissen Richtungen nicht überbewertet wird. Danach sind wir dann aber mal locker bei Faktor 3 Performance für die Terrain-Beleuchtung. Hmm... das schreib ich mir auf die Liste.

Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Jörg »

Schrompf hat geschrieben:... wenn ich einfach ein neues Projektionsfragment erfinde, dass eine 180°-Halbkugel auf eine 2D-Textur projeziert, komme ich mit einem Renderdurchgang anstatt dreien aus.
Jibbet schon, schaust Du mal unter 'paraboloid mapping' nach.

Und parallelisieren kannst Du es doch gut, falls Du noch Platz für weitere Grafikkarten im Rechner hast oder auf einen Cluster zugreifen kannst....ich kenne Euer Budget ja nicht.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Krishty »

Schrompf hat geschrieben:Du gehst an die Sache ja ganz anders ran: physikalisch korrekt. Während wir nur an den Werten schieben, bis es gut aussieht :-)
Okay, aber ich habe auch noch nicht mehr als ein halbfertiges HDR-Projekt und bin deshalb immer in panischer Angst, ich könnte was falsch gemacht haben, wenn anderer Leute Werte von meinen abweichen ^^
Schrompf hat geschrieben:Aber die Anspielung auf D3D10 bringt mich gerade auf eine Idee... wenn ich einfach ein neues Projektionsfragment erfinde, dass eine 180°-Halbkugel auf eine 2D-Textur projeziert, komme ich mit einem Renderdurchgang anstatt dreien aus. Die Formel für die Projektion müsste man halt clever wählen, so dass die Verteilung über die Textur halbwegs gleichmäßig ist, damit Licht aus gewissen Richtungen nicht überbewertet wird. Danach sind wir dann aber mal locker bei Faktor 3 Performance für die Terrain-Beleuchtung. Hmm... das schreib ich mir auf die Liste.
Das musst du nicht erfinden, das gibt es schon als Paraboloid Rendering (hier und hier, xcvb hatte im alten ZFX-Forum auch mal eine Diskussion drüber gestartet). Die Verteilung ist zwar nicht 100% gleichmäßig, aber auch nicht viel schlechter als bei Cubemaps – afaik hat Nvidia sowas auch früher schon bei Demos für indirekte Echtzeit-Beleuchtung eingesetzt. Selbst habe ich das aber noch nicht implementiert, also nicht zu sehr auf mein Halbwissen stützen :)

Edit: Okay, Jörg war ein bisschen schneller. Dafür habe ich aber Links :D
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
glassbear
Establishment
Beiträge: 324
Registriert: 08.04.2003, 18:09
Alter Benutzername: Enrico_
Echter Name: Enrico
Wohnort: San Diego
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von glassbear »

@Schrompf: Danke, Postmortems sind toll =)

@Zudomon: Die HDR-Implementierung ist die von Half-Life2/Source-Engine, oder?
Ein Hoch auf uns Männer... Auf die Frau, die uns HAT ( oder hat, und nicht weiß, dass sie uns hat ) ...auf die Idiotinnen ... besser gesagt VOLLPFOSTINNEN ... die uns hatten und uns verloren haben ... und auf die GLÜCKLICHEN, die das Vergnügen & Glück haben werden uns kennenzulernen!
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Zudomon »

@Enrico_
Kann ich dir leider nicht sagen, weil ich deren Implementierung nicht kenne. Aber die hatten das soweit ich weiß auch ohne Spezial-Formate geschafft.
Ist auch eigentlich kein großer Trick dahinter. Die Schwierigkeit war dieser Logharitmus. Ich kenne mich leider nicht gut in Mathe aus. Vor allem der log macht mir Schwierigkeiten.

Aber ich werde euch verraten, wie man das ganze hinbekommen kann, leider nur grob, da das jetzt schon lange her ist. Normalerweise wird z.B. im Multipass jede Lichtquelle übereinander addiert und dann das Ergebnis logharithmiert, zumindest mit dem einen Tonemapping da.
Man könnte aber auch jede Lichtquelle einzeln logharithmieren. Dann werden die Lichtquellen allerdings nicht addiert, sonder multipliziert. Am Ende muss das Bild noch invertiert werden. So bekommt man das gleiche Ergebnis, wie bei der ersten Variante. Das es tatsächlich funktioniert, seht ihr meiner Demo. Es werden nie die 8Bit überschritten, stattdessen die einzelnen Komponenten direkt mit dem endgültigen Betrag eingerechnet.

Edit: Ich sehe gerade, in meinem Codefragment hatte ich ja geschrieben: 1-exp(-lum * key); Also ich meinte die exp-Funktion.
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Gelöschter Benutzer »

Die Schwierigkeit war dieser Logharitmus. Ich kenne mich leider nicht gut in Mathe aus.
Na na na, log(x, n), ln(x) und lg(x) machen dir Probleme :) - und das bei der Shaderprogrammierung ?

ln(x) Logarithmus Naturalis ist die Umkehrfunktion zur Eulerschen Fuktion exp(x, y) oder e^x und entsprechend zur Basis e, also 2,7181 bzw. Die 1 + Summe(1/n!) bis unendlich. Glaubste nicht? Dann tipp mal ln(e^1) in deinen Taschenrechner ein und sehe es komme 1 heraus.
lg(x) ist die "Umkehrfunktion" zur Dezimalbasis. lg(1) = 0, lg(10) = 1, lg(100) = 2, ... . Die Umkehrfunktion ist 10^x.
log(x, y) ist jedoch zu einer beliebigen Zahl und zur beliebigen Basis, also 2, 3, 4 wie auch immer. Hier ist die Umkehrfunktion y^x.
Betrachte ln(x) = log(x, e^1) und lg(x) = log(x, 10) jeweils x e R ^ x > 0.

Ist das nicht bei euch Tagesordnung in der 12. Klasse oder wo ist das jetzt ein Problem?
(By the way kann ich für Einsteiger folgendes Buch empfehlen: "Mathematik Allgemeine Hochschulreife Richtung Technik" vom Cornelsen Verlag.)
Man könnte aber auch jede Lichtquelle einzeln logharithmieren. Dann werden die Lichtquellen allerdings nicht addiert, sonder multipliziert.
? Damit änderst du die Kompenentfaktoren höchstens aber multiplizierst diese Lichtquellen untereinander definitiv nicht. lg(x) ^ x < 1 ^ x e R ergibt allerdings bei Eingabewerten kleiner 1 negative Werte heraus. lg(1) = 0. Musst der Farbe zum vermeiden von Fehlern lg(max(L, 0) + float4(1,1,1,1)) wie geschrieben eine 1 addieren. Ich gehe eher davon aus, dass du die Farbvektoren jeweils addiert hast und dann durch die Anzahl geteilt hast? Übrigens kannst du hier die Farbe nochmals schön verändern, wenn du den Farbvektor mit einer beliebigen Funktion modifizierst (zum Beispiel Parabel, ln, Kubische Funktion, Exponent, etc.).
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Zudomon »

@Patrick
Ich weiß ja nicht was du mir hier erzählst, aber ich weiß, was ich programmiert habe. Und das ganze hatte was mit log(a) * log(b) = log(a + b) zu tun, und wenn da was falsch ist bitte ich dich, mich nicht zu belehren, da die meisten, die in Mathe mehr drauf haben, als ich, sich garantiert denken können, was ich meinte, und für die anderen, kann man es ja erklären. Es ging mir darum, zu erklären, wie man, ohne die 8Bit Grenze zu überschreiten das HDR simulieren kann, ohne hässliche ColorBandings zu bekommen. Aber dann so direkt angemacht zu werden! Wenn man sowas liest und mehr oder weniger als zu dumm für Shaderprogrammierung hingestellt wird, da könnt ich echt zu viel bekommen. Ich mache seit über 9 Jahren intensiv fast nichts anderes als 3D-Programmierung (OpenGL/DX/Software/Raytracing) und die meisten Dinge, die ich implementiert habe, habe ich mir selbst überlegt, vom Deferred Shading ( wo mir ein Freund hinterher sagte, wie man die technik nennt ) bis hin zu ParallaxOcclusionMapping, wobei letzteres bei mir zum ersten mal 2001 ohne Shader implementiert wurde, und dann kommt sowas. Dachte eigentlich, dass es ne interessante Sache ist, und dem einen oder anderen vielleicht eine neue Sicht auf die Dinge gibt. Naja, beim nächsten mal werde ich mir zweimal überlegen, ob ich nochmal irgendeinen "Trick" posten werde.

Licht muss man bei logarithmischem Tonemapping nicht mehr korrigieren, weil es auch physikalisch korrekt ganz natürlich wirkt, wie Krishty und Schrompf weiter vorne schon angemerkt haben!

Edit: Übrigens ich weiß auch nicht, wie man Sinus und Cosinus berechnet, aber ich weiß, welche Kurve entsteht und kann es somit auch anwenden. Das geht bei log/exp usw. genauso! Vielleicht sollte ich nochmal in die Unterstufe...
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Krishty »

@Patrick: Ich denke auch, wenn Zudomon hier meint er verstehe nicht viel von Mathe, dann meint er damit, dass es ihm nicht so einfach von der Hand geht wie anderen Leuten, nicht dass er nicht weiß was ein Logarithmus ist – er hat ja mit der Demo und den Screenshots bewiesen, dass er das sehr wohl auf die Reihe kriegt.
Ist bei mir ja genauso, ich verstehe z.B. von deinem Mathematischen Geschreibsel nur Bahnhof. Beim Atmospheric Scattering jongliere ich trotzdem mit Logarithmen und Exponenten und auch wenn ich da manchmal ganz schön dran zu knabbern habe, kriege ich es irgendwie doch immer hin :)
Zudomon hat geschrieben:Deferred Shading ( wo mir ein Freund hinterher sagte, wie man die technik nennt )
Haha, kenne ich zu gut … als ich das damals zum ersten Mal implementiert habe, war ich auch stolzerfüllter Brust wegen dieser neuen Render-Technik, bis ich hier irgendwann gelesen habe dass es sie längst gibt und man sie Deferred Shading nennt :lol:
Zudomon hat geschrieben:Licht muss man bei logarithmischem Tonemapping nicht mehr korrigieren, weil es auch physikalisch korrekt ganz natürlich wirkt, wie Krishty und Schrompf weiter vorne schon angemerkt haben!
Ganz genau. Diese ganze Idee von nicht-quadratischem Lichtanstieg ist in den Köpfen von Männern entstanden, die a) Leistung sparen wollten (indem sie den Lichtradius eingrenzen) oder b) die Gamma-Korrektur einbeziehen und irgendwie die logarithmische Empflindlichkeit des Auges für Licht annähern wollten (damit es halbwegs natürlich aussieht). Beim HDR-Rendering mit Tonemapping ist das überflüssig.
Zuletzt geändert von Krishty am 20.04.2009, 22:05, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Aramis »

Lichtanstieg ist in den Köpfen von Männern entstanden
Hey, Männer und Männerinnen bitteschön. Wir wollen doch politisch korrekt bleiben :-)
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Krishty »

Aramis hat geschrieben:
Lichtanstieg ist in den Köpfen von Männern entstanden
Hey, Männer und Männerinnen bitteschön. Wir wollen doch politisch korrekt bleiben :-)
Wenn du mir nur eine einzige nennen kannst, ändere ich das sofort in „Personen“ ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: PostMortem - HDR-Implementation in der Splitterwelten-Engine

Beitrag von Gelöschter Benutzer »

Du brauchst dich doch nicht so angemacht fühlen :). Mich hat nur die Aussage gestört: "Man könnte aber auch jede Lichtquelle einzeln logharithmieren. Dann werden die Lichtquellen allerdings nicht addiert, sonder multipliziert." und in Verbindung mit "Die Schwierigkeit war dieser Logharitmus. Ich kenne mich leider nicht gut in Mathe aus." hat mich besorgt. Daher habe ich nochmal kurz die Sache mit dem log erwähnt. Mich hat vor allem gestört, dass du eine Logarithmierung eines Wertes mit einer Multiplikation der einzelnen Komponenten unterschiedlicher Elemente gleichgestellt hast, was ja so nicht ist. Das du schon seit 9 Jahren mit Multimediaprogrammierung zu tun hast wusste ich noch nicht, aber die Ergebnisse die man sieht sprechen doch dafür - diese würde ich auch nicht im weitesten Sinne anzweifeln. Die Hinweise mit dem Logarithmus dienten eher zur mathematischen Betrachtung, da es sehr :!: sinnvoll ist zu wissen wie ein Porsche funktioniert und nicht nur wie der Porsche mal ungefähr aussehen wird. So geht es mir mit dem Atmospheric Scattering - Ich implementiere nicht sondern untersuche die Funktionen so lange bis ich das habe was ich brauche bzw. so wie ich es eigentlich will und dann :D implementiere ich. Haut es dann nicht hin wie ich es will bin ich sauer :x und Untersuche die Abschnitte jeweils nochmal auf die Fehler :|.

Das du dich jetzt so degradierst kann ich auch nicht verstehen. Schließlich waren dies für mich nur Aufforderungen Informationen zu liefern die ich liefern kann. Das ich dich jetzt mit jemandem verwechselt habe mit der 12. Klasse ist reiner Irrtum gewesen :oops:. Aber wenn hätte es mich wegen der Rahmenlehrplans gewundert, da dies dort relativ früh auftritt (ggf. eher) :) .

:| Falls du dich überhaupt weiter degradieren möchtest: Würde ich sowas zu meinem Physiklehrer zu Beleuchtungsmodellen in der Computergrafik sagen wie "physikalisch korrekt ganz natürlich wirkt", nimmt er mich außeinander mit der Formel. Entweder es wäre physikalisch korrekt oder es wirkt natürlich, also angenähert. Der sagt allerdings zum Logarithmus Naturalis "Linearisierung" :lol:. Hey, aber so ein Klugscheißer bin ich nicht, auch wenn ich Mathematik als Leistungskurs habe ;).
Antworten