Kurzartikel: Hochwertiges Rendern von Sternen 2.0

Hier können Artikel, Tutorials, Bücherrezensionen, Dokumente aller Art, Texturen, Sprites, Sounds, Musik und Modelle zur Verfügung gestellt bzw. verlinkt werden.
Forumsregeln
Möglichst sinnvolle Präfixe oder die Themensymbole nutzen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Kurzartikel: Hochwertiges Rendern von Sternen 2.0

Beitrag von Krishty »

Hochwertiges Rendern von Sternen  2.0

Bild
Mir persönlich zu dick aufgetragen, aber ich brauchte einen hübschen Aufmacher für diesen Artikel ;-)

Hier möchte ich Ansätze zum Rendern des Sternenhimmels diskutieren und die Erfahrungen weitergeben, die ich beim Entwickeln meines eigenen Renderers gemacht habe. Sterne darzustellen hört sich einfach an – bis zu einem natürlichen, realistischen und optisch ansprechenden Ergebnis ist es jedoch ein langer Weg (zumal sich diese Attribute zuweilen widersprechen). Wenn man sich dann nicht nur normales Rendering, sondern High-Quality-Rendering – rendern mit hohem Multisampling und der maximalen Bildqualität im Visier – vornimmt, ist der Weg nicht nur lang, sondern auch steinig.

Es handelt sich bei diesem Artikel um einen theoretischen Überriss. Ein Grund dafür ist, dass der Artikel mit allen Details, Erläuterungen und Quellcodes viel zu lang geworden wäre. Ein anderer Grund ist, dass solche Artikel umso schneller veralten und unbrauchbar werden, je konkreter sie sich auf bestimmte APIs und Codeteile beziehen.



tl;dr – wer nicht wissen will, warum er was tut oder nicht tut, springt zur Schritt-für-Schritt-Anleitung in Kapitel 4.

Demos gibt es hier.



Inhaltsverzeichnis

Der erste Teil befasst sich mit trivialen Ansätzen und mit der Suche nach geeignetem Material. Am Ende werde ich erklären, warum die bisherigen Ansätze nicht zu meiner Zufriedenheit funktionieren – wer schnelle Ergebnisse will, kann das also überspringen.
  • 1.1 Was machen wir hier überhaupt?
  • 1.2 Texel, Pixel, Sprites?
  • 1.3 Sterne sammeln
  • 1.4 Sterne sind nicht genug
  • 1.5 Alles umsonst?
Der zweite Teil stellt einen verbesserten, zeitgemäßen Ansatz vor …
  • 2.1 Das Abtasttheorem
  • 2.2 Antialiasing für Punkte und Linien
… und der Dritte perfektioniert ihn.
  • 3.1 Dithering gegen Banding
  • 3.2 Glare
  • 3.3 Tonemapping
Der vierte Teil ist eine Zusammenfassung, Ressourcensammlung und eine Präsentation der Ergebnisse.
  • 4.1 Ergebnisse
  • 4.2 Schritt-für-Schritt-Anleitung
  • 4.3 Sternenliste
  • 4.4 Hintergrundbild





1.1 Was machen wir hier überhaupt?

Wenn ich davon spreche, den Sternenhimmel zu rendern, beziehe ich mich ausschließlich auf die Sterne ohne Effekte wie Morgengrauen oder Sonnen- und Mondbahn (diese werden nur kurz am Ende angerissen). Dieser Artikel erklärt das Rendern des Sternenhimmels in seiner puren Form – wie er von einem hohen Berg aus oder im Weltraum sichtbar ist. Das macht ihn für Weltraum-Shooter genauso nützlich wie für Flugsimulatoren oder First-Person-Spiele.

Sterne sind nicht nur für Weltraumspiele oder Spiele, die bei Nacht spielen, wichtig. In großen Höhen können sie am helllichten Tag sichtbar sein und die ersten Sterne schimmern schon während der Dämmerung. Gerade dann können sie eine Bereicherung sein – wenn die Sonne gerade untergeht und ein paar einzelne Sterne schwach am Abendhimmel leuchten wirkt die Szene sofort glaubwürdiger und stimmungsvoller.

Schlecht gerenderte Sterne können genau das Gegenteil bewirken: fehlen die Sterne, sieht der Himmel zu leer und unnatürlich aus. Sind die Sterne zu groß, zu klobig oder zu viele, wirkt der Himmel erdrückend und einengend. Sind sie noch dazu so hell wie Laternen und die Farben zu aufdringlich, wirkt das Ganze geradezu lächerlich dilettantisch.

Darum versuche ich hier möglichst nah an der Realität zu bleiben. Sterne können leicht farbig sein, aber auf keinen Fall zu stark (was, wie wir noch sehen werden, eine Frage des Tonemappings ist). Sie dürfen nicht größer als ein paar Pixel sein (weil sie in Wirklichkeit geradezu verschwindend winzig sind). Es muss viele schwach leuchtende und wenige stark strahlende Sterne geben, wie am tatsächlichen Himmel.

Alle vorgestellten Techniken haben gemein, dass sie auf normalisiertem Raum arbeiten. Das bedeutet: sie funktionieren nur richtig, wenn sich der Betrachter am Nullpunkt befindet und sich nicht bewegt (genau wie eine Skybox). Das kann man erreichen, indem man aus der Transformationsmatrix die Einträge löscht, die für die Verschiebung zuständig sind und den Himmels als erstes Objekt und ohne Tiefeninformation rendert. Für den Betrachter sieht es dann aus, als sei der Himmel unendlich weit entfernt (obwohl er ihm eigentlich bloß überall hinfolgt).

Bild
Abbildung 1: Ausschnitt des Nachthimmels in Valves Hit-Shooter Half-Life aus dem Jahr 1998. Man kann erkennen, dass man in die Ecke eines Texture-Cubes blickt, auf welche die Sterne zu zu laufen scheinen. Außerdem wirken die Sterne für diese Auflösung zu groß und wenn man genau hinschaut, kann man die Handbewegung des Künstlers nachvollziehen.


1.2 Texel, Pixel, Sprites?

Fast jedes Spiel hat seine eigene Art, Sterne darzustellen. Vor einem Jahrzehnt waren Texture-Cubes sehr populär (siehe Abb. 1) – das rührte daher, dass zu dieser Zeit meist die ganze Umgebung eines Levels (inklusive Bergen, Wolken, der Sonne und dem Mond) durch Texture-Cubes gerendert wurde und sich Sterne schnell als einzelne Texel darauf auftragen ließen. Diese Methode hat einige Nachteile:

Zum einen reichen einzelne Pixel nicht aus um die Sterne zu rendern, weil die Pixel der Map in Richtung ihrer Ecken verzerrt werden. Um das auszugleichen, muss der Texture-Cube viel höher aufgelöst sein als die Anzeige, was einen recht hohen Speicherverbrauch bedeutet, der mit hohem Dynamikumfang noch steigt.

Weiterhin wirken die Sterne umso klobiger, je weiter man die Bildschirmauflösung steigert – denn während alle anderen Kanten immer schärfer werden, bleiben die Sterne so unscharf wie sie der Texture-Cube hergibt. In auf der Quake-Engine basierenden Spielen, die vor einem Jahrzehnt für weitaus niedrigere Auflösungen als sie heute üblich sind ausgelegt wurden, kann man das deutlich erkennen.

Zuletzt können die Sterne vom Künstler nur schwer frei Hand gesetzt werden weil er daran denken muss, in den Ecken weniger (aber dafür größere) Sterne zu platzieren, damit dort durch die perspektivische Verzerrung keine Ballungen entstehen. Außerdem muss der Cube unbedingt gefiltert werden, damit nichts verpixelt oder verwischt.

Das waren Gründe, mit fortschreitender Auflösung von Texture-Cubes abzurücken. Sterne als einzelne Bildschirmpixel wurden populär – man speicherte die Position und Helligkeit der Sterne in einem Vertex-Buffer und renderte ihn als einen Haufen Pixel fester, von der Perspektive unabhängiger Größe am Himmel (siehe Abb. 2). Diese Methode hat sich im Großen und Ganzen bis heute gehalten, weil sie sehr schnell und speicherschonend ist, die Sterne unabhängig von der Auflösung immer recht scharf sind und sie zudem kaum künstlerische Anforderungen stellt, sondern eine Sternliste schnell selbst generiert oder heruntergeladen werden kann. Der Grund, warum diese Entwicklung an die Auflösung gebunden war: Da die Sterne immer einen Pixel groß waren (bzw. vier viertelhelle Pixel beim Einsatz vom Multisampling) strahlten sie bei niedrigen Auflösungen weitaus stärker als bei hohen. Wenn bei 640x480 Pixeln 1000 Sterne zu sehen waren, wurde es eng zwischen den hellen Pixeln und der Vorteil gegenüber Texture-Cubes verflüchtigte sich.

Auch in meinen Renderer hatte ich mich zuerst für Punktlisten entschieden. Eine Liste mit zufälligen Sternen war schnell generiert – und grauenhaft. Obwohl Sterne jeder Helligkeit vorhanden waren, in der Verteilung keine Muster auftauchten und die Anzahl der Sterne realistisch war, wirkte der Himmel sehr unnatürlich.

Bild
Abbildung 2: Ausschnitt des Nachthimmels in Bohemia Interactives Taktik-Shooter Operation Flashpoint aus dem Jahr 2001, einem der ersten Spiele mit einem realistischem Nachthimmel an dem man sich sogar orientieren konnte. (Der Schnappschuss wurde Gamma-korrigiert, weil auch das Spiel gammakorrigiert arbeitet.)


1.3 Sterne sammeln

Der Fehler war eben gerade, dass die Sterne zu gleichverteilt waren – sowohl in Helligkeit als auch in Position. Vom Anblick der Sterne sind wir schwache Haufen, helle Einzelgänger und eine Konzentration entlang der Milchstraße gewohnt. Ich hatte sowieso vor, einen realistischen Sternenhimmel einzubauen, also begab ich mich direkt auf die Suche nach Sternlisten.

Meine erste Anlaufstelle war der Yale Catalog of Bright Stars. Es handelt sich um eine Datensammlung der 9110 Sterne des gesamten Himmels, die man mit bloßem Auge erkennen kann. Jedem Stern liegen Beschreibungen zur Position und zur Erscheinung bei und den Katalog gibt es als kostenlosen Download – für diesen Zweck ideal.

Schwierig ist es dann aber doch, die Daten aus dem Katalog zu verwerten. Zum einen müssen alle unwichtigen Daten herausgefiltert werden – Name, Parallaxe, usw. Das ist nicht so schwer, weil das Format dokumentiert ist (die Dokumentation findet sich auf der Download-Seite); allerdings liegen diese Daten dann im falschen Endian vor und müssen erst geflippt werden. Außerdem sind es physikalische Daten – wer fertige Vektoren und Farben erwartet, irrt. Diese müssen erst aus vier Angaben rekonstruiert werden, nämlich der Deklination, der Rektaszension, der scheinbaren Helligkeit und der Spektralklasse.

Die Position eines Sterns als normalisierter dreidimensionaler Vektor ergibt sich aus seiner Deklination und seiner Rektaszension:

Code: Alles auswählen

x = cos(declination) * sin(rightAscension)
y = sin(declination)
z = cos(declination) * -cos(rightAscension)
Danach sollte der Nordstern genau auf der positiven Y-Achse liegen. Schwieriger wird es mit der Farbe: Man kann den Farbton aus der Spektralklasse schließen (beispielsweise über Lookup-Tabellen); die Helligkeit zu berechnen ist jedoch alles andere als trivial. Wer sich dafür interessiert oder es selber tun will, kann diesen Thread durcharbeiten, in dem Stephan Theisgen erklärt, wie man auf die ersehnten Leuchtdichten kommt. Eine dementsprechend vorberechnete Sternenliste samt Dokumentation (die auch für die Bilder in diesem Artikel verwendet wurde) steht im vierten Kapitel zum Herunterladen bereit.

Hier möchte ich noch eine Optimierungsmöglichkeit ansprechen: Anstatt Position und Farbe in 32-Bit-Floats zu speichern, kann man auch 16-Bit-Halfs verwenden – am einfachsten durch D3DXFLOAT16 und D3DXFloat32to16Array() (falls man D3D zum rendern benutzt). Bei 9110 Sternen im Katalog halbiert man die Größe des Vertex-Buffers so immerhin von 214 auf 107 KiB. Es schont Speicherplatz und kostet nichts – um Präzisionsverluste muss man sich keine Sorgen machen; Halfs können Sterne noch bis zu Auflösungen von rund 4000 Pixeln (bei 90° Blickfeld) pixelgenau auseinander halten.

Bild
Abbildung 3: Der aus einem Panorama erzeugte Texture-Cube mit der Milchstraße. Man beachte, wie kontrastreich er ist – die Textur wird erst im Shader abgedunkelt, um volle Bildqualität zu garantieren. Mehr dazu in der Diskussion zum Dithering.


1.4 Sterne sind nicht genug

Mit echten Sternen sieht der Himmel gleich um ein Vielfaches glaubwürdiger aus, wirkt aber dennoch seltsam steril: Wir sehen am Himmel nicht nur die sichtbaren Sterne, sondern vor allem noch Nebel und Sternhaufen (wie die Milchstraße), welche aus so vielen so schwachen Sternen bestehen, dass sie sich nur als Flecken abzeichnen und es nicht in den Bright Star Catalog schaffen. Das Universum ist zwischen den Sternen halt nicht schwarz, sondern milchig grau mit schwach erkennbaren Mustern.

Also musste ein Hintergrundbild her. Ich musste lange suchen, letztendlich habe ich aber eine Panoramaaufnahme der Milchstraße von überragender Qualität (und unter CC3-Lizenz) gefunden. Die kann man nicht direkt verwenden, das sie in einem anderen Koordinatensystem als die Sternenliste vorliegt – Tools wie HDRShop haben aber eine Rotationsfunktion, mit der sich das ändern lässt. (Eine fertig vortransformierte Textur gibt es in Kapitel 4). Die Transformation vom galaktischen Koordinatensystem der Aufnahme ins Äquatoriale der Sternenkataloge geschieht folgendermaßen:
  • 60 ° nach links rotieren (Shift/Wrap in HDRShop – keine Rotation um eine Bildschirmachse)
  • Horizontal spiegeln
  • Sphärische Rotation um die X-Achse: 62,871664 ° (90 ° minus galaktische Deklination)
  • Sphärische Rotation um die Y-Achse: 192,859508 ° (galaktische Rektaszension)
(Speziell bei der verlinkten Aufnahme muss noch nachkorrigiert werden; mehr dazu beim Download in Kapitel 4.)

Ich habe mich zwar für die Sterne gegen einen Texture-Cube entschieden - für die groben Schattierungen der Milchstraße u.ä. ist er aber perfekt. Da alles sehr niederfrequent ist, reichen schon 256 Pixel Seitenlänge; siehe Abb. 3 – wer höhere Ansprüche hat (z.B. weil noch Planeten, Nebel o.ä. eingezeichnet werden soll) kann natürlich auch höhere Auflösungen nutzen.

Dieser Texture-Cube muss irgendwo aufgetragen werden; ich suchte mir dazu ein Tetraeder aus (man kann es schnell und einfach on-the-fly im Shader erzeugen). Im Shader an sich nimmt man nur die Richtung des Pixels (da sich der Betrachter relativ zum Himmel immer an der Nullposition befindet, ist die Richtung gleich der Position) und nutzt sie direkt, um die Textur zu adressieren. Nach dem samplen wird sie mit einem Richtwert multipliziert, damit man die Helligkeit des Hintergrundbildes mit der der Sterne abstimmen kann. Weil die Map niedrig aufgelöst ist, kann sie ohne anisotropen Filter gesamplet werden.

Bild
Abbildung 4: Das Tetraeder mit der Milchstraßentextur von außerhalb gesehen. Da sich der Betrachter immer in der Mitte befindet, erscheint die Textur für ihn unverzerrt. Eigentlich ist der Himmel – wie auch hier – sehr farbenfroh; dass wir ihn nur in schwarz-weiß sehen liegt daran, dass unser Auge bei solchen geringen Helligkeit kaum Farben wahrnehmen kann.


1.5 Alles umsonst?

Mit Sternen und Milchstraße sieht der Himmel schon ganz gut aus. Allerdings nur, so lange er sich nicht bewegt – als ich meine Sterne das erste Mal in Bewegung sah, war ich regelrecht erschrocken: Das Bild begann furchtbar unruhig zu werden. Obwohl die Sternbewegungen minimal sind, sind sie doch groß genug, um alle paar Zehntelsekunden einen Stern von einem Pixel auf den anderen „überschwappen“ zu lassen. Weil das alle Sterne abwechselnd in ähnliche Richtungen tun, wabert das Bild.

Mein erster Gedanke: Antialiasing! Schnell hinzugeschaltet half es aber nicht, es verlagerte das Problem nur. Die Sterne rutschten nicht mehr von Pixel zu Pixel sondern von Subsample zu Subsample, weshalb ihre Helligkeit nun von Frame zu Frame flackerte. Bei langsamen Mausbewegungen grieselte und rauschte das Bild vor sich hin, und das trotz 8× Multisampling … nichts half.

Testweise fügte ich Motion Blur hinzu: Sterne wurden nicht mehr als Punkte, sondern als Linien zwischen ihrer Position in diesem und dem vorherigen Frame gezeichnet – aber auch das funktionierte nicht wie gewollt. Sterne verschwanden wenn sie sich nicht bewegten. Wenn sie sich bewegten, tauchten kleine Lücken zwischen den Linien der einzelnen Frames auf. Schuld war eine kleine, aber folgenschwere Änderung der D3D-API von Version 9 auf 10, nämlich das Entfernen des Renderstates D3DRS_LASTPIXEL, der dafür sorgte, dass der letzte Pixel einer Linie immer gezeichnet wurde, auch, wenn die Linie Nulllänge besaß. Ohne diesen Renderstate waren Linien von Nulllänge unsichtbar und in der Reihe des Motion Blurs fehlte der letzte Pixel.

Bild
Abbildung 5: Ausschnitt des Nachthimmels in Cryteks Ego-Shooter Crysis aus dem Jahr 2007. Man kann erkennen, dass alle Sterne mindestens zwei Pixel groß sind und hell leuchtende Sterne eine Halo besitzen; die Sterne werden also definitiv als Sprites gerendert.




2.1 Das Abtasttheorem

Ursache des Flackerns und Waberns war das Nyquist-Shannon-Abtasttheorem, welches besagt, dass ein Eingangssignal mit mindestens der doppelten Frequenz abgetastet werden muss, um es exakt rekonstruieren zu können. In unserem Fall war das Eingangssignal der Stern, der vom Bildschirm abgetastet wurde um ihn in ein Bildsignal umzuwandeln. Die Frequenz, mit welcher der Bildschirm den Stern abtastete, war ein Pixel (eigentlich höher, wegen des Multisamplings, dessen unregelmäßiges Raster machte das Antialiasing aber durch sein Flackern zunichte). Die Folge dieses Theorems ist: Wollen wir den Stern auf dem Bildschirm rekonstruieren, darf er nicht höherfrequent als zwei Bildschirmpixel sein. Weil Punkte nicht nur horizontal oder vertikal, sondern auch diagonal wandern können, müssen wir das sogar auf zwei Mal (Wurzel aus zwei) Pixel erweitern. Sterne müssen im Durchmesser mindestens 2,8 Pixel groß sein um nicht zu flackern! Interessanterweise ist das beim Rendern von Linien mit Antialiasing ein bekanntes Problem und der Grund dafür, dass es dafür eine separate Einstellung neben dem gewöhnlichen Multisampling gibt. Linien werden dann nämlich nach einer Methode gerendert, die das Abtasttheorem besonders stark zu unterdrücken versucht. Diese Technik kann man sich auch beim Rendern der Sterne zu Nutze machen.

In der ursprünglichen Version des Artikels hatte ich Point-Sprites mit einer Punkttextur vorgeschlagen, um die Sterne zu rendern (wie es auch Crysis tut; siehe Abb. 5). Das ist unter Direct3D 9 noch der einfachste Weg (weil diese API Point-Sprite-Funktionalität implementiert hat – im Gegensatz zu Direct3D 10 und später, wo man sie selber per Geometry-Shader emulieren muss) und liefert akzeptable Resultate. Point Sprites haben allerdings zwei Nachteile:

Zum einen wirken sie recht klobig, wenn sie nicht optimal gefiltert werden – zwar weitaus filigraner als z.B. ein Texture-Cube, aber dennoch größer, als sie sein müssten. Dafür muss man garnicht erst den Texturfilter vergessen: Es reicht bereits, eine Karte mit beschnittenem anisotropem Texturfilter zu haben (wie AMDs Radeon HD 5000-Serie), um selbst mit höchsten Texturfiltereinstellungen zu niedrige Mip-Levels und damit klobige Sterne zu erhalten.

Zum anderen sind Point Sprites unabhängig von der Perspektive immer gleich groß. Was erstmal überhaupt nicht verkehrt klingt, äußert sich als deutlicher Nachteil, wenn wir in die Weitwinkelperspektive gehen: Die perspektivische Verzerrung sorgt dafür, dass das Bild in der Mitte gestaucht und an den Außenrändern gezerrt wird. Die Sterndichte ist in der Bildmitte also höher als am Rande. „Echte“ Geometrie würde nun am Rand in die Größe gezerrt werden und die niedrige Dichte durch größere Fläche wettmachen; da Point-Sprites aber immer gleich groß sind, nimmt die sichtbare Sterndichte am Rand ab (siehe Abb. 6 & 7).

Darum habe ich mich entschieden, die Sprites als „echte“ Geometrie zu rendern. Wer keinen Geometry-Shader zur Verfügung hat oder sich nicht die Mühe machen will, kann ruhig gewöhnliche Point-Sprites nutzen – das Ergebnis ist nicht optimal, aber immernoch um Längen besser als bei konventionellen Ansätzen.

„Echte“ Geometrie bedeutet: Man berechnet das Koordinatensystem der Stern-Sprite (die Z-Achse hat man bereits, weil sie die Richtung des Sterns ist; die X-Achse ist ein beliebiger, senkrecht dazu stehender Vektor (der Bewegungsvektor des Sterns bietet sich an); die Y-Achse entspricht dem Kreuzprodukt der beiden anderen Achsen) und führt die Verschiebung der Eckpunkte vor der Multiplikation mit der Transformationsmatrix durch.

Bild
Abbildung 6a: Point-Sprites bei Weitwinkelansicht: die Helligkeit ballt sich in der Bildmitte.

Bild
Abbildung 6b: „Echte“ Sprites bei Weitwinkelansicht: die Sterne ballen sich weiterhin in der Bildmitte, aber diesmal ist die Helligkeit gleichverteilt. Man kann außerdem sehen, dass Point-Sprites etwas gröbere Sterne produzieren. (Ich musste leider andere Sternfarben nehmen, weil ich von der ursprünglichen Programmversion keinen Schnappschuss mehr hatte.)


2.2 Antialiasing für Punkte und Linien

Es gibt viele Möglichkeiten, effektiv Antialiasing auf Punkte (für Sterne) und Linien (für bewegte Sterne) anzuwenden. Ich habe mich für eine Methode aus GPU Gems 2 entschieden – Fast Prefiltered Lines.

Im Kern geht es darum, dass man eine Lookup-Tabelle (1D-Textur) erzeugt, in der die Intensität eines Punktes abhängig von der Entfernung zur Mitte angegeben ist. Dann rendert man eine Point-Sprite. Im Pixel-Shader rechnet man nun aus, wie weit der Pixel von der Mitte des Punktes (oder von der Linie) entfernt ist und schlägt den entsprechenden Wert in der Textur nach. Das Ergebnis sind wunderbar glatte Punkte und Linien. Da die Sprite erst im Geoshader erzeugt wird ist es sehr einfach, die Entfernung zur Mitte zu bestimmen: Man ordnet der linken unteren Ecke die Koordinate (-1|-1) zu; der rechten oberen Ecke (1|1). Diese Koordinaten übergibt man dem Pixel-Shader als Texturkoordinaten; sie werden für jeden Pixel interpoliert. Die Distanz vom Sternmittelpunkt ist nun ganz einfach die Länge der Koordinate, die im Pixel-Shader ankommt, und kann direkt als Texturkoordinate für die 1D-Lookup-Textur verwendet werden.

Hier ist meine 1D-Textur:

Code: Alles auswählen

static unsigned char const texels[32] = {
	255, 253, 250, 246, 241, 234, 226, 216,
	203, 189, 173, 156, 138, 120, 102,  85,
	 70,  56,  43,  32,  24,  18,  14,  11,
	  8,   6,   4,   3,   2,   1,   0,   0
};
Wie man sieht gibt sie – wenn man sie bei 0 samplet, der Pixel also genau auf der Sternposition liegt – Weiß zurück. Bei 1 – wenn der Pixel nicht mehr Teil des Sterns ist – gibt sie Schwarz zurück. Die Auslegung einer aus zwei Dreiecken erzeugten Stern-Sprite sieht folgendermaßen aus:

Bild
Abbildung 7a: 8×8 Pixel große Stern-Sprite

In diesem Beispiel ist die Sprite 8×8 Pixel groß. Das ist exemplarisch – die „echten“ Sprites sollten in der Größe so gewählt sein, dass sie in der Bildschirmmitte auf die in 2.1 berechneten 2,8 Pixel Seitenlänge kommen um minimal groß und maximal flimmerfrei zu sein.

Leider wird das Ganze etwas komplizierter, wenn Motion Blur ins Spiel kommt. Wenn die Sprite einfach entsprechend der Bewegung des Sterns gestreckt wird, sieht sie so aus:

Bild

Wenn sich der Stern acht Frames lang bewegt, sieht sein Motion Blur so aus:

Bild

Da sind Lücken zwischen, die wir nicht wollen. Darum teilen wir die Sprite in drei Teile – Anfang, Ende und Bewegungspfad:

Bild
Abbildung 7b: 8×44 Pixel große Stern-Sprite

Steht der Stern still, kollabiert der mittlere Teil zu Nulllänge und Vorder- und Rückseite bilden zusammen dasselbe Ergebnis wie zuvor. Bewegt sich der Stern hingegen, haben wir durchgängigen Motion-Blur:

Bild

Um zu zeigen, wie das in einer gewöhnlichen Szene aussieht, habe ich die Punkte, die mein Geoshader erzeugt, mal durch eine rote Linie verbunden ohne die Sterne selber zu zeichnen:

Bild
Abbildung 8a: Pfad durch die Vertices der Stern-Sprites, wenn sie um die Y-Achse rotieren. (Die Sprites sind hier dicker, als sie sein sollten, damit man die Pfade erkennen kann.)

Nun müssen die Sprites nur noch in die Szene eingewoben werden. Es sollte klar sein, dass man die Helligkeit, die man aus dem Antialiasing-Lookup liest, noch mit der Farbe des Sterns multiplizieren muss. Nicht so offensichtlich ist, dass man additives Blending einstellen muss. Aber man möchte schließlich nicht, dass sich Sterne gegenseitig verdecken können (was zu Flimmern führt, wenn sie gleich weit vom Betrachter entfernt sind), oder z.B. die Milchstraße.

Bild
Abbildung 8b: Die rohen Stern-Sprites bei schneller Rotation um die Y-Achse. (Hier wieder mit normaler Dicke.)




3.1 Dithering gegen Banding

Der Bildschirm hat nur eine begrenzte Farbtiefe. Beim Sternenhimmel grenzen wir diese Farbtiefe noch weiter ein: 95% der Pixel (nämlich alle, die zu keinem Stern gehören) werden unter einer Helligkeit von 5% liegen. Das bedeutet, dass für die Darstellung der Milchstraße gerade einmal 12 Helligkeitswerte pro Kanal zur Verfügung stehen! Man kann deshalb – ganz besonders, wenn sich das Bild langsam bewegt – deutlich die Grenzen zwischen den einzelnen Farben erkennen (siehe Abb. 2, 9). Diesen Effekt nennt man Banding. In meinen Beispielen liegt es nicht an der Textur – ich habe für die Milchstraße schließlich extra eine kontraststärkere Version gewählt, die im Shader abgedunkelt und in ein Float-Rendertarget geschrieben wird – sondern einzig und allein an der Farbtiefe des Ausgabegeräts. Da wir die Farbtiefe nicht frei wählen können (mehr als 8 Bits pro Kanal können lediglich ATIs Profi-GPUs wie die FirePro-Serie ausgeben, dann auch nur über spezielle Anschlüsse) müssen wir das Banding von Hand bezwingen. Die beste Methode dafür ist Dithering.

Dithering fügt kleine Fehler in das Bild ein, die sich über mehrere Pixel betrachtet wieder gegenseitig aufheben. Zwar sind viele Dithering-Algorithmen für die Implementierung in Hardware geeignet, für superparallele Architekturen wie heutige GPUs bleiben allerdings nur wenige zur Auswahl. Ich habe mich für gleichverteilten, zufälligen Noise entschieden. Das ist zwar eine der am wenigsten effektiven Methoden, sie lässt sich aber recht einfach implementieren. Es ist wirklich wichtig, dass der Noise gleichverteilt ist, damit möglichst viel Bildinformation erhalten bleibt. Meinen Algorithmus könnt ihr in diesem Thread nachlesen.

In meinem Renderer habe ich Dithering mit einer Stärke von ±1/255 angewendet – das bedeutet gerade mal einen Prozent Abweichung vom ungefilterten Bild (im schlimmsten Fall, durchschnittlich nur die Hälfte), die sich außerdem über mehrere Frames ausgleichen und ab 30 fps quasi unsichtbar sind. Dafür sind absolut keine Farbabstufungen mehr sichtbar (siehe Abb. 9) – insbesondere in Bewegung wirken die Farben weniger abgehackt und das Bild bleibt dennoch gestochen scharf. Meiner Meinung nach wird das Bild durch Dithering sogar noch natürlicher und wärmer, das ist aber Geschmackssache. Weil nicht nur die Milchstraße, sondern auch alles andere, was man rendert, davon profitieren kann, sollte man das Dithering als Nachbearbeitungseffekt auf den Frame anwenden, als allerletztes bevor er zum Bildschirm geschickt wird. (Tatsächlich wird Dithering an Sternen und Milchstraße überflüssig, wenn man Tonemapping mit Eigengrau implementiert. Es gibt aber auch jede Menge Helles, das von Dithering profitiert.)

Bild
Abbildung 9: Zwei Screenshots der Plejaden, links ohne und rechts mit Dithering. Unten jeweils eine 4 größere und 6,4× kontraststärkere Version. Dithering kann das Banding vollständig aufheben, obwohl es Pixel nur um höchstens einen Prozent (durchschnittlich halb soviel) verändert und unter Einsatzbedingungen quasi unsichtbar ist.


3.2 Glare

Glare ist der Strahlenkranz um grelle Lichtquellen – oder, besser – die Sichtbehinderung, die durch ihn entsteht. Glare ist das effektivste Werkzeug, um in der Computergrafik Überhelligkeiten zu simulieren und tritt auch an Sternen auf.

Um Glare zu implementieren gibt es tausend Möglichkeiten – von einfachem Aufaddieren downgesampleter Szenen über Bloom mit Gauss-Kernel und Strahlfilter bis hin zu komplexen dynamischen Glare-Modellen. Jedoch ist allen gemein, dass sie Nachbearbeitungseffekte sind und deshalb nicht nur auf die Sterne wirken, sondern auch auf alles andere, was man rendert – darum sollte der Glare immer primär auf die Szene abgestimmt werden und nicht bloß auf die Sterne. Die Methoden dieses Artikels sind problemlos mit Glare kombinierbar: der hohe Antialiasing-Grad verhindert großflächiges Flackern und die Sternenliste ist vollends HDR-fähig.

Für die Schnappschüsse in diesem Artikel habe ich einen relativ aufwändigen Ansatz gewählt; meine Erfahrungen könnt ihr hier nachlesen – für einfachen Sternenhimmel ist das aber ziemlicher Overkill.

Bild
Abbildung 10: Blick auf Orion ohne und mit Glare. Mit Glare fällt es deutlich leichter, Helligkeit einzuschätzen und Überhelligkeit zu erkennen.


3.3 Tonemapping

(Streng genommen hätte der Glare auch noch hierher gehört, aber dann wäre es zu viel geworden.)

Sterne und Milchstraße sind äußerst farbenfroh und das Verfahren, wie es bisher hier beschrieben wurde, liefert ebenfalls sehr farbkräftige Bilder. Tatsächlich ist unser Eindruck vom Sternenhimmel aber ein ganz anderer.

In heller Umgebung sehen wir photopisch, können also Farben unterscheiden. Dies entspricht den gängigen Tonemapping-Formeln.
Dämmert es, sehen wir mesopisch – die Farbunterscheidung fällt schwerer und die Sicht wird unschärfer. Das entspricht von der Leuchtdichte her einer Vollmondnacht, in der man gerade noch lesen kann. Die Lichtempfindlichkeit verschiebt sich ins Blaue.
Wird es noch dunkler, sehen wir nurnoch skotopisch, schwarz-weiß. Dabei wird fast nur noch blaues Licht registriert – was tagsüber rot war, sieht nun schwarz aus. Was tagsüber blau aussah, sieht nun weiß aus. (Darum sind Instrumente und Rücklichter rot – sie blenden den Teil unseres Sehapparates, der für Nachtsehen zuständig ist, im Gegensatz zu weißem oder gar blauen Licht kaum.)

Rendern wir Sterne, müssen wir alle drei Bereiche berücksichtigen: Der Mond, Signallichter und die Lichtverschmutzung durch Städte werden gerade noch photopisch wahrgenommen. Sterne u.Ä. werden mesopisch wahrgenommen – wir können ihre Farben, zumindest bei den hellsten Exemplaren, noch ein wenig unterscheiden (z.B. den Mars und Beteigeuze als schwach rot identifizieren). Die Milchstraße und die schwachen Sterne liegen im skotopischen Bereich (deshalb sind sie trotz ihrer Farbenvielfalt milchig und erscheinen weiß leuchtend).

Für uns bedeutet das: Jeder Pixel muss gemäß seiner Leuchtdichte danach kategorisiert werden, in welchem Wahrnehmungsbereich er liegt. Die Leuchtdichten, ab wann was was ist, stehen im Wikipedia-Artikel. Dann wird logarithmiert. Danach wird gemäß der Kategorie entsättigt (innerhalb skotopischen und mesopischen Sehens kann linear interpoliert werden, damit es nicht zu kompliziert wird). Abschließend muss die Farbe nachkorrigiert werden – obwohl wir physisch nur Grau sehen können, rechnen wir der Nacht psychisch einen blauen Farbton zu („Amerikanische Nacht“).

Da kommt noch ein Haufen anderer Effekte drauf: Verlust der Sehschärfe, Eigengrau etc. Das alles würde aber den Rahmen des Artikels sprengen … exzellente Arbeiten zum Thema sind (vor allem, falls man bodenbasiert rendert) Night Rendering und A Physically-Based Night Sky Model.

Auch Tonemapping ist üblicherweise ein Nachbearbeitungseffekt, wirkt also auf die komplette Szene und muss auch entsprechend abgestimmt werden. Wem das zu viel ist und wer lieber klassisch rendern will, der kann aber alle Helligkeitswerte schon beim Laden der Sternenliste und des Hintergrund-Texture-Cubes entsprechend bearbeiten und die so vorbereiteten Daten gewöhnlich rendern.

Bild
Abbildung 11: Erneut der Blick auf Orion – links nur mit Dithering und rechts mit Glare, Tonemapping und Eigengrau. Der Sternenhimmel sieht damit wesentlich vertrauter aus.




4.1 Ergebnisse

Für diese Screenshots interpretiert der Tonemapping-Operator Helligkeiten ab 0,3 cd/m² als photopisch. Skotopisches Sehen wird mit der (linearen!) Farbe 0,4R/0,53G/1,55B gefärbt.

Die Schnappschüsse wurden ohne Multisampling aufgenommen. Meine Methode ist ausschließlich GPU-basiert und stellt, abgesehen vom Geoshader, keine hohen Leistungsansprüche: Es gibt weder komplexe Geometrie noch hoch aufgelöste Texturen. Die Framerate der blanken Sterne liegt auf einer Radeon HD 4850 durchgängig bei 400 bis 1000 fps. Mit Tonemapping und Glare werden noch 40 fps auf einer Radeon HD 5770 erreicht (wobei das aber der ganzen Szene zugute kommt und nicht nur eine Anforderung des Sternenhimmels ist).

Bild
Abbildung 12: Zeitrafferaufnahme des Himmels (mit Glare) – oben der Himmelsnordpol, in der Mitte der Große Wagen.

Bild
Abbildung 13: Schneller schwenk (mit Glare und Tonemapping).

Bild
Abbildung 14: Blick auf Orion (mit Glare, Tonemapping und Eigengrau).

Bild
Abbildung 15: Der zusätzlich implementierte Mond und die Milchstraße (mit Glare, Tonemapping und Eigengrau).

Demos gibt es hier.


4.2 Schritt-für-Schritt-Anleitung
  • Weiter unten Sternenliste und Hintergrundbild herunterladen
  • Aus der Bildschirmauflösung und dem Öffnungswinkel den Helligkeitskoeffizienten für die Sternen-Sprites berechnen (wie das geht, steht bei der Sternenliste)
  • Aus der Bildschirmauflösung und dem Öffnungswinkel berechnen, wie groß der Radius einer Sprite sein muss, damit sie in der Bildschirmmitte 2,8 Pixel groß ist (tan())
  • Sternenliste in einen Vertex-Buffer laden, Hintergrundtextur in einen Texture-Cube; eine 1D-Textur als Helligkeitstabelle gemäß 2.2 erzeugen
    Falls kein HDR-Rendering oder kein Tonemapping-Operator zur Verfügung stehen:
    • Helligkeit der Sterne mit dem Helligkeitskoeffizienten für Sternen-Sprites multiplizieren
    • Farben der Sterne und der Hintergrundtextur entsättigen
    • vom linearen Farbraum in den gammakorrigierten Farbraum schieben
    • Helligkeitstabelle in den gammakorrigierten Farbraum schieben
    Falls kein Geometry-Shader zur Verfügung steht:
    • Für jeden Stern ein lokales Koordinatensystem berechnen
    • Damit eine Sprite der zuvor errechneten Mindestgröße aufspannen
    • Die relative Koordinate (zwischen -1 und +1) des Eckpunkts speichern
  • Transformationsmatrix des vorherigen und des aktuellen Frames sammeln und jeweils die Verschiebung entfernen
  • Tiefenpufferung abschalten
  • Texturadressierung für die Helligkeitstabelle auf Clamping schalten
  • Ein Tetraeder, einen Würfel, eine Kugel oder eine ähnliche primitive Form bauen und rendern (oder beides im Vertex-Shader kombinieren), dabei von innen den Hintergrund-Texture-Cube auftragen
  • Additives Blending einschalten
  • Alle Sterne aus dem Vertex-Buffer rendern
    Falls ein Geometry-Shader zur Verfügung steht:
    • Für jeden Stern ein lokales Koordinatensystem berechnen (derzeitige und letzte Transformationsmatrix für Motion-Blur nutzen)
    • Damit eine dreiteilige Sprite (sechs Dreiecke) der zuvor errechneten Mindestgröße aufspannen
    • Die Eckpunkte transformieren
    • Die relativen Koordinaten der Eckpunkte (zwischen -1 und +1) in einem Texturregister an den Pixel-Shader übergeben
    • Die Helligkeit des Sterns in einem Texturregister an den Pixel-Shader übergeben
    Sonst:
    • Eckpunkt transformieren
    • Relative Koordinate und Farbe an Pixel-Shader weiterreichen
  • Im Pixel-Shader die Länge der ankommenden Koordinaten ausrechnen und damit die Helligkeitstabelle adressieren
  • Helligkeit mit der ankommenden Sternhelligkeit multiplizieren
Und immer daran denken:
  • Die besten Effekte sind die, die nicht auffallen. Nicht ins Kitschige abrutschen – eine strahlende, bunte Milchstraße quer über den Himmel kann super aussehen – aber auch hoffnungslos übertrieben und aufgedrängt. (Das tun meine Screenshots hier zwar auch, aber sonst ist ja niemand dazu zu begeistern ;) )
  • Im Vollbildmodus in einem dunklen Raum wirkt alles ganz anders als auf einer hellen Website!
  • Wir mussten die Sterne wegen dem Abtasttheorem rund drei Pixel groß machen. Das ist gigantisch, auch wenn man es nicht merkt weil wir Menschen die Größe der Gestirne immer falsch einschätzen. Zum Vergleich: Die Sonne hat einen scheinbaren Durchmesser von 0,54°, bei einer Auflösung von 1280×1024 Pixeln wäre sie also nur 8x8 Pixel groß; da liegt nicht viel zwischen.

4.3 Sternenliste

Hier meine Sternenliste – die Helligkeiten sind gemäß dieses Threads berechnet; die Farben sind über die Farbtemperatur der Spektralklasse angenähert (die .txt-Dateiendung ignorieren – die muss ich nutzen, weil das Board keine beliebigen Dateitypen unterstützt):
stars.3S16_3F16.txt
(106.76 KiB) 2021-mal heruntergeladen
Layout:

Code: Alles auswählen

class snorm2; // 16-bit signed normalized value (two's complement, little endian)
class half; // 16-bit floating-point number (IEEE 754-2008 binary16)
// or otherwise
typedef short snorm2, half;

struct Star {
    snorm2 x, y, z; // declination and right ascension of 0 at -1,0,0; polaris at 0,1,0
    half r, g, b; // cd÷m² for 45° fov at 1920 pixels × 256 (to avoid denormalized numbers)
};

assert(fileSize == 9110 * sizeof(Star));
Wenn man die Datei direkt in einen Vertex-Buffer lädt, kann man unter D3D10/11 per folgendem Input-Layout darauf zugreifen (im Shader müssen die Paare und einzelnen Werte wieder zu Tripeln zusammengefasst werden, weil Grafik-Hardware keine Formate mit drei Komponenten unterstützt):

Code: Alles auswählen

::D3D11_INPUT_ELEMENT_DESC const starElements[] = {
	{ "DIRXY", 0, ::DXGI_FORMAT_R16G16_SNORM,	0, D3D11_APPEND_ALIGNED_ELEMENT, ::D3D11_INPUT_PER_VERTEX_DATA, 0, },
	{ "DIRZ" , 0, ::DXGI_FORMAT_R16_SNORM,		0, D3D11_APPEND_ALIGNED_ELEMENT, ::D3D11_INPUT_PER_VERTEX_DATA, 0, },
	{ "LUMR" , 0, ::DXGI_FORMAT_R16_FLOAT,		0, D3D11_APPEND_ALIGNED_ELEMENT, ::D3D11_INPUT_PER_VERTEX_DATA, 0, },
	{ "LUMGB", 0, ::DXGI_FORMAT_R16G16_FLOAT,	0, D3D11_APPEND_ALIGNED_ELEMENT, ::D3D11_INPUT_PER_VERTEX_DATA, 0, },
};
Um die Sterne richtig darzustellen muss man noch einen Helligkeitskoeffizienten als Ausgleichsfaktor für die Konvertierung zu half (1 ÷ 256), den Zoom (doppelt so groß gezoomt => halbe scheinbare Sprite-Größe => vierfache Leuchtdichte) und die Bildauflösung (halbe Auflösung => doppelte scheinbare Größe => viertel Leuchtdichte) anwenden:

Code: Alles auswählen

float const viewFactor = tan(fov);
float const resolutionFactor = resolution / 1920.0f;
float const luminanceScale = 1.0f / 256.0f / (viewFactor * viewFactor) * (resolutionFactor * resolutionFactor);
Man setzt luminanceScale als Shader-Konstante und multipliziert die Sprite-Leuchtdichte im Pixel-Shader damit.


4.4 Hintergrundbild

Für die Textur, die ich hier anbiete, habe ich diese Fotomontage, die unter Creative-Commons-3-Lizenz steht, vom European Southern Observatory / Serge Brunier, verwendet. Neben der Konvertierung vom galaktischen ins äquatoriale Koordinatensystem (wie in Kapitel 1.4 beschrieben) musste ich noch diese Korrekturen durchführen:
  • Sphärische Rotation um die Y-Achse: 50,76 °
  • Sphärische Rotation um die Z-Achse: 1,5 °
  • Sphärische Rotation um die Y-Achse: -50,76 °
Ich habe die Sterne nicht herausgefiltert, sondern nur die Planeten, die im Weg waren. Die Flächen liegen in der Reihenfolge +X, +Y, +Z, -X, -Y und -Z vor.
Milky Way texture cube.png



Ich hoffe, ich konnte denen, die Sterne in ihren Renderer einbauen möchten, mit diesem Artikel einen guten Einstieg in die Thematik und einen detaillierten Überblick über die vielen Fallstricke geben.
Falls es noch irgendwelche Fragen, Verbesserungsvorschläge, Lob oder Kritik gibt, scheut euch nicht es hier zu posten :)

Ich danke Jörg, Stephan Theisgen und eXile für ihre Hilfe.




Zusätzliche Schlagwörter: Milky Way, Galaxy, Star Rendering, Starfield Rendering, High-Quality Rendering, Sterne rendern
Zuletzt geändert von Krishty am 28.02.2021, 12:37, insgesamt 8-mal geändert.
Grund: Links und Bilder waren durch https-Umstellung kaputt
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: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Aramis »

Hoi,

endlich bin ich dazu gekommen es mal zu implementieren. Hat wunderbar geklappt, und ging richtig flott und ohne Probleme. Das ganze Finetuning (Helligkeit, Farbsättigung, etc.) hab ich erstmal ausgespart weil es mit HDR dann sowieso alles völlig anders aussieht :-)

Danke nochmals für den Artikel. Allen anderen hier sei das Verfahren auch an's Herz gelegt, man schafft es wirklich kaum einfacher einen realistisch wirkenden Sternenhimmel hinzukriegen :-)
Seraph
Site Admin
Beiträge: 1184
Registriert: 18.04.2002, 21:53

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Seraph »

Wuerdest Du bitte ein paar Resultate posten? Ich bin auch gerade auf der Suche nach einer Technik fuer das Rendern von Sternen, allerdings nicht aus der Sicht der Erde, sondern von verschiedenen Punkten des Weltraums aus.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Aramis »

Hier. Sternfarben größtenteils entsättigt, Helligkeitsspektrum eher gering.

Wie gesagt, ich erhoffe mir von HDR ziemlich realistische Sterne, die dann wenn kein großer Himmelskörper im Bild ist entsprechend hell und farbig wirken, bei Kameraeinstellungen mit Planet/Sonne/etc. drauf in den Hintergrund treten (quasi wie bei den Apollo-11-Bildern).
sshot4.PNG
moon.PNG
Mit der Sterngröße experimentiere ich grade noch etwas rum ... ziemlich schwer zu beurteilen was am besten aussieht. Ebenfalls Mühe hab ich mit dem Hintergrundbild .. Krishty's Cubemap gefällt mir optisch nicht, meine aktuelle Variante ist fast etwas zu neblig .... Zur Performance kann ich noch nichts sagen, in der Testapplikation hat es *fast* gar nichts gekostet weil das Bottleneck sowieso an anderer Stelle liegt.
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Huch, hier hat sich ja was getan … schön, dass der Artikel nicht in Vergessenheit geraten ist :)

@Aramis: Das ist mal ein fast surreales Déjà-vu … zum ersten Mal sehe ich die Sterne und die Milchstraße, die ich so auch täglich in meiner Engine sehe, in einem komplett anderen Umfeld …
Aramis hat geschrieben:Ebenfalls Mühe hab ich mit dem Hintergrundbild .. Krishty's Cubemap gefällt mir optisch nicht, meine aktuelle Variante ist fast etwas zu neblig ....
Ich bin vor ein paar Monaten auf eine weniger gesättigte Version umgestiegen, mit der ich ganz zufrieden bin … falls es also die Farbsättigung war, die dich gestört hat, kann ich dir gern eine neue schicken (aber die wird leider auch nicht höher aufgelöst sein). Ich rate dir auf jeden Fall, nicht zuviel Arbeit zu investieren, bevor HDR-Rendering implementiert ist – die Farbwirkung ist einfach zu unterschiedlich … aber das hast du ja selbst schon angemerkt.
Aramis hat geschrieben:Wie gesagt, ich erhoffe mir von HDR ziemlich realistische Sterne, die dann wenn kein großer Himmelskörper im Bild ist entsprechend hell und farbig wirken, bei Kameraeinstellungen mit Planet/Sonne/etc. drauf in den Hintergrund treten (quasi wie bei den Apollo-11-Bildern).
Mir ist das soweit ganz gut gelungen (nur ein einziger Stern ist zu hell, das könnte aber auch ein Bug im Sternkatalog sein) … die Formel kann ich dir dann gern zur Verfügung stellen.

Noch was zu den Mond-Screenshots: Ich habe hier eine hübsche, hochaufgelöste Normal- und Albedo-Map für den Mond …:
[2008-12-06-01-00]MoonComparison.png
Der Haken ist nur, dass es sich um eine Cubemap handelt (ich hasse Artefakte an den Polen) … falls du damit aber dennoch was anfangen kannst, melde dich.
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: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Aramis »

die Formel kann ich dir dann gern zur Verfügung stellen.
Da werde ich gerne drauf zurückkommen, wird aber vorraussichtlich noch ein Weilchen dauern. Hauptsächlich weil ich momentan noch keine sinnvolle, datengetriebene Möglichkeit habe Postprocessing auszuführen. Und weil vorher noch so gefühlte 200 andere Punkte auf der Todo-Liste stehen. Ich melde mich dann, es lohnt sich nicht drauf zu warten :D

Zum Mond&Sonnensystem -> das ist schlicht und einfach eine ganz gute Testszene, mit 120MB Texturen von Google schnellstmöglich zusammengefummelt. Ich kann mir nur wenig vorstellen, was sich zum Testen und Optimieren eines Szenengraphen besser eignet :-)
Matthias Gubisch
Establishment
Beiträge: 488
Registriert: 01.03.2009, 19:09

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Matthias Gubisch »

Der Link zu dem Tread mit dem Noise Algo funktioniert nicht (mehr)

Ansonsten, toller Artikel, glaub ich muss des auch mal implementieren wenn ich wieder etwas Luft hab :)
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Matthias Gubisch hat geschrieben:Der Link zu dem Tread mit dem Noise Algo funktioniert nicht (mehr)
Umzugsbedingt … gefixt :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Hier ein Screenshot von meinem Test-Terrain mit Atmosphäre und einem Tone-Mapper, der linear zwischen den drei Wahrnehmungstypen interpoliert:
Tonemapped.png
Mit normalem Tonemapping (und ohne Dithering, auch leider ein wenig heller) sieht es schon ein wenig anders aus:
Luminance.png
Das lässt viel Platz für künstlerische Gestaltung, je nachdem, wie man es mag.
Die Kategorisierung eines zufälligen Sternbilds samt Halbmond:
Cat.png
Und hier liefere ich meine weniger gesättigte Cubemap nach. Die Flächen sind in der Reihenfolge +X, -X, +Y, -Y, +Z, -Z (mittlerweile gibt es hier eine Bessere):
Background.png
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: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von eXile »

Mir viele noch eine kleine Anmerkung an Krishty, die mir beim Durchschauen des Threads aufgefallen ist:

Welches Beleuchtungsmodell für den Mond benutzt du? Da doch eine, zwar geringe, aber doch erkennbare Diskrepanz in der Vergleichsabbildung oben zu sehen ist, würde ich das Oren-Nayar-Reflektionsmodell vorschlagen, falls du es nicht schon benutzt. Das Oren-Nayar-Modell wurde gerade für sehr raue Oberflächen, wie eben die Mondoberfläche, entwickelt, und würde sich damit sehr gut anbieten. Vielleicht ist es ja den Versuch wert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Super Tipp, danke! Ich hatte mich kurz damit beschäftigt, aber angesichts der Masse an Formeln und Papers, die es zu den Reflexionseigenschaften der Mondoberfläche gibt, kapituliert. Atm komme ich an den Mond-Shader nicht mehr heran … sobald es wieder geht, probiere ich es aber aus.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Neues von der Cubemap

Beitrag von Krishty »

Nachtrag: Das Hintergrundbild befindet sich nun in Kapitel 4.4 des Artikels.
Ein kleines Update zum Hintergrundbild:

Ich arbeite gerade daran, echte Milchstraßen-Fotos zu integrieren statt (auf der Basis von Sternkatalogen) künstlich erzeugte. Ein großes Problem ist, dass Milchstraßenfotos oft keine vollen Panoramaaufnahmen sind und dass sie im falschen Koordinatensystem (dem galaktischen, gegenüber den Äquatorialen der Sternkataloge) vorliegen.

Bei ersterem Problem verweise ich auf diese Fotomontage, die unter einer Creative-Commons-3-Lizenz zur Verfügung steht und von überragender Qualität ist. Die Transformation in das Koordinatensystem der Sternkataloge funktioniert dann (z.B. mit Hilfe HDRShops) so:
– 60 ° nach links rotieren (Shift/Wrap in HDRShop, keine Rotation um eine Bildschirmachse)
– Horizontal spiegeln
– Sphärische Rotation um X: 62,871664 ° (90 ° - galaktische Deklination)
– Sphärische Rotation um Y: 192,859508 ° (galaktische Rektaszension)

Da fehlt noch irgendwo eine Rotation um ein Grad, das gibt dann einen netten Schliereneffekt:
MilkyWay.png
Damit lässt sich aber zumindest die korrekte Ausrichtung der Cubemap-Seiten verifizieren ;) Sobald ich die fehlende Rotation gefunden und die Sterne rausgefiltert habe, gibt es hier die beste Cubemap, die man dafür nur benutzen kann.

Edit: Erledigt. 50,76 ° auf der Y-Achse rotieren, dann 1,5 ° auf der Z-Achse, und wieder -50,76 auf der Y-Achse, dann ist alles in Flucht:
MilkyWayCorrect.png
Edit 2: Es ist vollbracht … diesmal habe ich die Sterne nicht herausgefiltert (nur die Planeten, die im Weg waren) … habe irgendwie Gefallen an dem Noise gefunden. Ist diesmal auch in höherer Auflösung, damit die schönen Details nicht verloren gehen. Die Flächen liegen wieder in der Reihenfolge +X, +Y, +Z, -X, -Y, -Z vor, die Quelle ist http://www.eso.org/public/images/eso0932a/ und ich hoffe, dass ihr mit der Cubemap etwas anfangen könnt:
Falls ihr eine High-Res-Version, Quelldaten oder sonstwas braucht, meldet euch bei mir.
Noch ein Screenshot zum Abschluss, ohne Tonemapping, damit die volle Farbkraft durchkommt … leider ist die Helligkeit der Sternsprites nicht an die des Hintergrunds angepasst, ich bitte, das zu entschuldigen.
MilkyWayWithScattering.png
Das reale Vorbild:
Bild
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Sternendemo

Beitrag von Krishty »

 


Veraltet – hier geht’s zur Neuen


Verdunkelt die Räume, ich habe eine Sternendemo gebastelt ;) Nichts Großartiges – keine Atmosphäre, keine Tag-Nacht-Zyklen, einfach der Algorithmus gemäß des Artikels.

Voraussetzungen:
  • Direct3D-10-kompatible Grafikkarte (getestet auf Radeon HD 4000, GeForce 8000 und einem Intel-Chipset)
  • DirectX SDK February 2010 oder, falls nicht installiert, DirectX Redistributable (February 2010)
  • DXGI 1.1, d.h. Vista SP2 oder höher.
Download:
BiederOzonblau20100416x86.7z
(1.2 MiB) 1938-mal heruntergeladen
Ich sehe nichts!
Mausrad hoch / runter ändert die Helligkeitsempfindlichkeit.

Ich sehe nur blauen Griesel!
Das ist die untere Helligkeitsgrenze der menschlichen Wahrnehmung, mittlere Maustaste bzw. Mausrad drücken und halten, um auf „Digitalkamera“-Tonemapping umzuschalten.

Bild
Bild

Technisches: Es gibt zwei Dinge, mit denen ich unzufrieden bin: Zum einen passt der Motion Blur nicht nahtlos aneinander; ich denke, dass die Projektion noch nicht so ganz gelingt. Bin aber noch dran. Zum anderen musste ich die Auflösung des Hintergrunds vierteln, damit es in den Anhang passt. Ich kann aber gern eine FullHD-Version bei einem Filehoster hochladen, falls jemand Interesse anmeldet.

So eine Demo hätte man mit DXUT wohl in ein paar Stunden basteln können … ich wollte die Möglichkeit aber nutzen, um das Grundgerüst meiner Engine in der Wildnis zu testen. Etwaige technische Probleme seien mir bitte mit angehängter Logdatei berichtet und vergeben …

Ich benutze nun keine Sternentextur mehr, sondern einen Anti-Aliasing-Lookup gemäß diesem GPU Gems-Artikel … funktioniert super, sieht noch besser aus und die Sterne sind dadurch noch kleiner und klarer.

Freue mich über Feedback, teile auch gern Quellcode – auch, wenn ich nichts direkt Kompilierbares vorlegen kann, weil die Chose relativ stark abhängig von meinem Framework ist.
Zuletzt geändert von Krishty am 08.03.2011, 19:28, 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: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Aramis »

Danke fuers Releasen der Demo, damit haben alle Leser deines Artikels endlich eine lauffaehige Referenz :-)

Sieht optisch natuerlich absolut perfekt aus. Kein Vergleich zu Crysis. Ich kann allen spaeteren Betrachtern nur empfehlen vorher wirklich alles abzudunkeln, dann ist die Wirkung um Welten besser als in einem hellen Raum mit viel Mausraddreherei.

Getestet auf Win7, February2010, Core i7 860 & einer HD5850. Hardware und Displaykonfiguration laut Logdatei korrekt erkannt.

Danke auch dafuer, dass ich seitdem du mit diesem Artikel angefangen hast in jedem Spiel aufs neue in den Himmel gucken muss. Ich will gar nicht erst wissen wie schlimm das dann erst bei dir sein muss :-)
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Jörg »

Schick schick!
Aber bei mir stimmt was mit dem Dithering-Noise nicht....extrem nervig gerade bei höheren Helligkeitsstufen, da es ebenfalls heller wird. Die Milchstrasse ist darin kaum zu erkennen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

@Aramis: Ich fühle mich (in dieser Reihenfolge) bestätigt, geschmeichelt, erleichtert, stolz und wehmütig.

@Jörg:
Krishty hat geschrieben:Ich sehe nur blauen Griesel!
Das ist die untere Helligkeitsgrenze der menschlichen Wahrnehmung, mittlere Maustaste bzw. Mausrad drücken und halten, um auf „Digitalkamera“-Tonemapping umzuschalten.
;) Das Dithering ist hochfrequenter, schwächer und, zumindest in dieser Demo, nicht erkennbar. Du kannst es getrennt über Numpad 3 / 9 runter- und hochregeln und per Numpad 6 abschalten oder resetten. (Willst du die Milchstraße trotzdem im natürlich-bläulichen Look, geh in Direct3D11\Tonemapping Operator (human) 10.0.hlsl und korrigier in Zeile 28 EigengrauMaximum um ein oder zwei Dekaden nach unten.) Und dankeschön natürlich.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Jörg »

Ah :) Ich hab hier keine Maus und das Scrollen hab ich ueber die Touchpad-Extension hinbekommen. Scheint so, als haette das mit dem mittleren Klick nicht gepasst. Da muss ich wohl mal eine 'echte' Maus anknüppern.

PS: Nun passt es! Das Noise hatte also nichts mit dem Dithering zu tun sondern ist ein zusaetzlicher Effekt.

Hast Du mal ueberlegt, die Sternen-"Sprites" ala Clear-Type sub-pixel-genau zu steuern ? Um diesen "Game-Of-Life"-Effekt bei langsamen Bewegungen mildern.
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Jörg hat geschrieben:Hast Du mal ueberlegt, die Sternen-"Sprites" ala Clear-Type sub-pixel-genau zu steuern ? Um diesen "Game-Of-Life"-Effekt bei langsamen Bewegungen mildern.
Der Gedanke kam mir mal, aber ich habe ihn schnell wieder verworfen – zum einen ist das Anti-Aliasing der Sterne ausreichend (bei der Demo ist es 32-fach AA mit Gauss-Kernel) und ich habe sichergestellt, dass das AA immer optimal funktioniert, indem ich die Sterne bei verschiedenen Auflösungen innerhalb eines Pixels hin- und herzittern ließ, ohne, dass es flimmerte (auch bei der Demo bewegen sich die Sterne noch zufällig innerhalb eines zehntel Pixels, selbst, wenn du die Maus still hälst). Zum anderen ist es technisch nicht machbar, weil das Rendering der Sterne vor dem Tone-Mapping erfolgt und ich deshalb nicht vorhersagen kann, mit welcher Helligkeit ein Subpixel am Ende tatsächlich dargestellt wird.

Alles, was du an Game-of-Life-Effekt beobachten kannst, sollte eine Auswirkung des Anti-Aliasings sein. Sollte es bei dir aber der umgekehrte Fall sein – dass das Aliasing dadurch verstärkt wird – dann habe ich da irgendwo einen Fehler gemacht. Es könnte auch sein, dass du im Treiber anisotrope Filterung erzwingst und dass der AA-Kernel dadurch aufgemischt wird …

… ich habe hier leider keine Nvidia-Karte, deshalb konnte ich nur testen, ob es auf nicht-ATI-Karten läuft – nicht, ob es dort auch korrekt läuft. Solltest du also eine nicht-ATI-Karte haben und/oder bist dir sicher, dass AF abgeschaltet ist und siehst Aliasing, schick Screenshots und Hardware-Konfiguration und ich sehe zu, was ich tun kann.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Jörg »

Ja, an das Tone-Mapping habe ich nicht gedacht, das stimmt. Wahrscheinlich bin ich nur zu pingelig und muesste mal wissen , wie es ohne AA aussieht. Kann man es im Programm deaktivieren? Oder muss ich im Treiber rumspielen?
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Ist nicht implementiert. Wenn du mir ein bisschen Zeit gibst, kann ich dir aber eine Version ohne AA schreiben …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Ging schnell, musste nur den Geo-Shader rausnehmen … damit ist Motion-Blur natürlich auch weg.

Da die Sterne ohne AA und ohne Bewegung natürlich perfekt aussehen, habe ich mal eine minimale Rotation um den Himmelsnordpol reingebracht … jetzt sieht man die Sprünge.

Sicherheitskopie machen, dann ersetzen
NoAA.7z
(865.73 KiB) 1691-mal heruntergeladen
Edit: Zu pingelig kann man kaum sein :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Jörg »

Danke, das macht den Unterschied wirklich deutlich. Aber dafuer muss ich auch echt nah an den Bildschirm ran :) hmm...ich lauf mal zum Fernseher, da sind die Pixel groesser.
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

Mal ein kleines Update der Demo …
… das meiste hat sich unter der Haube getan, aber zu den deutlich erkennbaren Veränderungen gehört:
  • Sonne und Mond enthalten
  • Sonne, Mond und Sterne bewegen sich auf realistischen Bahnen
  • Beschleunigen und bremsen der Zeit (z.B. für Motion Blur, Mondphasen im Zeitraffer und Rotation der Sterne um die Himmelspole)
  • Größerer Leistungshunger auf Direct3D-10.1- und -11-Chips
  • neu: Glare
Schnellstart:
  • Raum verdunkeln ;)
  • Direct3D-10- oder 11-taugliche Grafikkarte benötigt, außerdem die DirectX-Runtime Juni 2010 (falls kein aktuelles SDK installiert, Download hier)
  • Die Demo zeigt den Himmel zur aktuellen Systemzeit von Deutschland (genauer: NRW) aus
  • Mausrad hoch und runter macht heller und dunkler
  • Bild auf / Bild ab zoomt hinein oder weg
  • Plus- und Minustaste auf dem Numpad beschleunigen und verlangsamen die Zeit
  • Drücken und Halten der rechten Maustaste schaltet von menschlichem auf digitales Tonemapping um (farbenfroh, ohne Glare & ohne Griesel)
neu: D3D-11-only-Version mit Glare:
BiederOzonblau20110320.7z
(2.03 MiB) 7686-mal heruntergeladen
Alte D3D-11-only-Version ohne Glare:
BiederOzonblau20101125.7z
(4.86 MiB) 1869-mal heruntergeladen
Alte D3D-10-Version:
BiederOzonblau201009233.7z
(4.86 MiB) 1946-mal heruntergeladen


Ausführlich:
Im letzten halben Jahr hat sich viel an der Engine getan und ich wollte die kleinen Fortschritte am Sternenhimmel nutzen, um sie mal wieder „in der Wildnis“ zu testen. Die Sonne ist nur als einfarbige Scheibe implementiert; der Mond deutlich liebevoller, aber z.B. fehlt noch das von eXile vorgeschlagene Beleuchtungsmodell. Die Demo benutzt die aktuelle Systemzeit für Chronologie und Himmelsmechanik – leider nicht präzise genug, um z.B. Sonnenfinsternisse wiederzugeben, aber für den Spielealltag mehr als ausreichend. Da kein künstlicher Horizont drin ist, ist ernsthafte Navigation anstrengend, aber möglich – der Betrachter schaut beim Start genau nach Norden; die Y-Achse findet man durch hin- und herbewegen der Maus und der Nordstern ist relativ einfach zu finden, indem man die Zeit beschleunigt und schaut, worum die Sterne rotieren (falls man nicht fachkundig ist und ihn sowieso sofort erkennt).

Steuerung:
  • Alt+Eingabe zum Umschalten zwischen Vollbild- und Fenstermodus; Alt+F4 zum Beenden.
  • Maus zum Umsehen (manchmal ungünstig, wenn sie das Fenster verlässt. Ist mir als Fenstermodus-Fan aber lieber, als sie einzusperren).
  • Mausrad hoch/runter ändert die Belichtungszeit, macht also das Bild heller oder dunkler.
  • Drücken und Halten der rechten Maustaste deaktiviert menschliches Tonemapping und schaltet auf digitales um – die menschlichen Limitierungen entfallen (bei geringer Helligkeit Farben- statt Schwarz-Weiß-Sehen, kein Rauschen mehr) und man sieht den Himmel wie auf Fotos.
  • Bild-auf- und Bild-ab-Taste steuern den Zoom.
  • Plus- und Minustaste auf dem Numpad lassen die Zeit schneller und langsamer vergehen. Sehr nützlich, um den Motion Blur zu betrachten, den Nordstern zu finden, sich den Mond während verschiedener Phasen anzuschauen oder zu beobachten, wie die Sonne im Sommer aufsteigt. Ich habe die Maximalgeschwindigkeit auf drei Tage pro Sekunde – also ein halbes Jahr pro Minute – begrenzt, damit das Ganze auch bei niedrigen Frame-Raten kontrollierbar bleibt.
Schnellhilfe:

Alles ist weiß! (in der Version mit Glare)
Du schaust in die Sonne. Mausrad hoch / runter ändert die Helligkeitsempfindlichkeit.

Alles ist schwarz! (in den Versionen ohne Glare)
Mausrad hoch / runter ändert die Helligkeitsempfindlichkeit.

Ich sehe nur blauen Griesel!
Das ist die untere Helligkeitsgrenze der menschlichen Wahrnehmung; rechte Maustaste drücken und halten, um auf „Digitalkamera“-Tonemapping umzuschalten.

Sonne und Mond fehlen! (wahrscheinlich nur in den Versionen ohne Glare)
Höchstwahrscheinlich nicht; sie sind nur kleiner, als wir denken. Ranzoomen und genau hinschauen. Helligkeit runterdrehen, damit die meisten Sterne verschwinden und nur Sonne und Mond übrig bleiben. Zeit beschleunigen und ein paar Tage überspringen, um sicher zu gehen, dass nicht Neumond oder Sonnenfinsternis ist.

Probleme:
Ich habe die Demo auf Windows 7 mit einer GeForce 8600M GT und einer Radeon HD 5770 getestet, aber es kann natürlich immer mal vorkommen, dass was nicht läuft. In dem Fall schickt mir bitte ein Log und Eckdaten zum System – ist ja auch in meinem Interesse, dass die Engine überall wie erwartet funktioniert. Bekannt:
  • Gedrückte rechte Maustaste verträgt sich nicht mit dem Verlassen des Fensters. In dem Fall rechte Maustaste außerhalb des Fensters drücken und gedrückt haltend zurückkehren ;)
  • Bei hohen Auflösungen kann die Performance massiv einbrechen (von eigentlich 30 auf 4 fps), nachdem man das Fenster vergrößert hat. Die Ursache habe ich noch nicht gefunden, aber Maximieren und Wiederherstellen hilft meistens. Letzter Ausweg ist der Vollbildmodus, der funktioniert immer reibungslos. Ist in der Glare-Version behoben.
  • Die Performance ist schwach. Auf D3D-10.1- und 11-Karten schalte ich 2- bzw. 4-fach MSAA zu, um Mond und Sonne zu glätten. Bei Full-HD-Auflösungen bringt das aktuelle Karten schnell an die Grenze … es ist wirklich lächerlich, die Performance wegen der zwei Pünktchen auf ein Viertel (2×MSAA) / Achtel (4×MSAA) einbrechen zu lassen – aber ich sehe es positiv; für alles, was in nächster Zeit an Effekten und Geometrie nachkommt muss ich diesen Schritt früher oder später eh wagen und ist die Performance erst ruiniert, lebt es sich ganz ungeniert. Und so lange da nur Sonne, Mond und Sterne sind, sollte es nicht unspielbar langsam werden. Die D3D-11-Versionen sind mittlerweile ziemlich gut optimiert.
  • Beim Schalten in den Vollbildmodus verschiebt sich die Maus. Leider macht Direct3D das automatisch.
Technik:
Hachja, das ist wieder mal alles so wunderbar overengineered ;)

Bewegung in die Sterne zu bringen ist eigentlich ganz einfach. Man braucht nur das derzeitige Julianische Datum in koordinierter Weltzeit (ich empfehle GetSystemTimeAsFileTime()) und rechnet es dann auf die Epoche J2000.0 um (d.h., subtrahiert 2451545; lässt sich mit GetSystemTimeAsFileTime() kombinieren). Daraus berechnet man die derzeitige Sternzeit in Greenwich (GMST). Die Transformation der Sterne ist dann eine Rotation um die Y-Achse um GMST ÷ 24 × 2 × π + Länge des Beobachters gefolgt von einer Rotation um die X-Achse um 90 - Breite des Beobachters.

Mit der Sonne wird es schon schwieriger – aber auch hier liefert Wikipedia alles, was man braucht, inklusive Beispiel.

Kniffliger wird es mit dem Mond. Die Formel für die Mondbahn habe ich dem exzellenten Paper A Physically-Based Night Sky Model entnommen, und sie funktioniert zufriedenstellend.

Komplett selber gemacht ist das Rendern von Sonne und Mond. Textur und Normal-Map des Mondes habe ich, wie schon weiter vorne im Thread geschrieben, aus verschiedensten Quellen selber zusammenkombiniert. Gerendert werden die Gestirne als Sprites – dafür gibt es mehrere Gründe:
  • 50 MiB Texturdaten (Albedo und Normalen beim Mond, allerdings nicht in dieser Demo, um Bandbreite zu sparen) sind auch heute noch ziemlich viel; erst recht für einen letztendlich meist 15×15 Pixel kleinen Punkt.
  • Auf weniger Details kann man aber leider nicht ausweichen, weil sonst die Krater verloren gehen und die Qualität des Renderings zu leiden beginnt (erst recht, falls sich tatsächlich mal zufällig jemand den Mond angucken will).
  • Die Gestirne verändern sich sehr, sehr langsam – von Vollmond bis Neumond vergehen 14 Tage. Warum also 50 Mal pro Sekunde neu zeichnen?
Lange Rede, kurzer Sinn – die Gestirne stecken bei mir in einer 256² Pixel großen Sprite. Sie wird frühstens dann aktualisiert, wenn eine Stunde in-game-Zeit vergangen ist (obwohl man den Zeitraum sicher noch ausdehnen könnte). Obwohl eine riesige Menge Details im Mond steckt, von hochauflösenden Texturen bis – bald – einem detaillierten Beleuchtungsmodell, besteht die per-Frame-Arbeit also nur im Runterrendern einer stinknormalen Sprite. Hier ist mal das Exemplar von heute mittag:
Moon Sprite.png
Moon Sprite.png (337.82 KiB) 49288 mal betrachtet
Man sieht, dass gerade Vollmond ist :) Man beachte den Kranz: Der ist notwendig, um durch Texturfilterung bedingte Ränder zu vermeiden, wenn die Textur auf eine runde Sprite gerendert wird. Für eine runde Sprite habe ich mich aus dem schlichten Grund entschieden, dass mit einer eckigen Sprite und einem Alpha-Kanal kein Anti-Aliasing möglich ist – es handelt sich schließlich um ein HDR-Bild, was bedeutet, dass ein geantialiaster Rand in einem anderen Helligkeitsraum vorliegen würde als das finale Bild und nach dem Tonemapping wieder eckig aussehen würde (was sich auch nicht vermeiden lässt, da man beim Rendern der Sprite nicht weiß, mit welcher Helligkeitskurve das Bild letztendlich ausgegeben werden wird). Erzwingt man hingegen Antialiasing durch Multisampling, das nach dem Tonemapping aufgelöst wird, erhält man ein klares Bild wie dieses hier:
Moon.png
Moon.png (74.97 KiB) 49288 mal betrachtet
Zu guter Letzt noch ein Tipp, wie man so eine Sprite am effizientesten rendert (auch, wenn es unter Einsatzbedingungen wahrscheinlich keinen Unterschied macht ;) ). Achja, da ist auch meine größte Sauerei: Um mir Input-Layout und Vertex-Buffer zu sparen, habe ich den Winkel jedes Vertex als Gleitkommazahl in einen 32-Bit-Index-Buffer gesteckt, im Vertex-Shader SV_VertexID entgegengenommen und die ID wieder zu float uminterpretiert, um per Sinus und Kosinus die Position zu berechnen. Boah, war ich stolz und mein Schlüpfer nass, als das funktionierte.
Das alles erscheint wie ein bisschen viel Arbeit für einen Himmelskörper, der auf dem Bildschirm gerade mal ein paar Pixel einnimmt – aber imo ist gerade das ein Grund, so viel zu investieren: Wenn man es nicht tut, hat man nämlich einfach ein paar helle Pixel in der Luft hängen, die keiner als irgendwas erkennt.
Zuletzt geändert von Krishty am 20.03.2011, 19:53, insgesamt 11-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Despotist
Establishment
Beiträge: 394
Registriert: 19.02.2008, 16:33

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Despotist »

Da kann ich nur sagen Hut ab vor so viel Mühe und Liebe zum Detail. Ich könnte mir nicht wochenlang so viele Gedanken machen damit ein paar Pixel etwas schöner aussehen ;). Aber ich finds toll dass es Leute gibt die es tun, ihr Wissen teilen und damit auch anderen die Möglichkeit geben sich zu verbessern. Weiter so.
Alexander Kornrumpf
Moderator
Beiträge: 2136
Registriert: 25.02.2009, 13:37

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Alexander Kornrumpf »

Speziell für dich dürfte es interessant sein zu erfahren dass effizient eine binäre Kategorie ist. Effizienter als effizient geht es nicht und am effizientesten schon gar nicht.

SCNR.
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von eXile »

Sehr schön! Aber hier doch etwas Manöverkritik:

Sollte die Core.exe in einem Pfad mit Umlauten liegen, so findet er das Plugin nicht. Log-Datei:
Logdatei hat geschrieben:C:\asd ü\Core.exe
invalid ASCII sequence
The plugin's version information could not be loaded.
Add a valid VERSIONINFO resource to the module. The following fields are required:
• InternalName — the plugin's name.
• FileVersion — the plugin's version.
• LegalCopyright — copyright information.
the plugin factory "" in "C:\asd ü\Core.exe" failed
plugin (unknown) crashed; terminating
(Die Umlaute habe ich einfach mal so kopiert, wie WordPad mir die Datei angezeigt hat.) Eine andere Sache: Beim Wechsel zwischen Vollbildschirm und Fenstermodus wird die Kamerarichtung verändert. Vielleicht einfach bei einem solchen Wechsel die relative Mausposition zurücksetzen?
Krishty hat geschrieben:Für eine runde Sprite habe ich mich aus dem schlichten Grund entschieden, dass mit einer eckigen Sprite und einem Alpha-Kanal kein Anti-Aliasing möglich ist – es handelt sich schließlich um ein HDR-Bild, was bedeutet, dass ein geantialiaster Rand in einem anderen Helligkeitsraum vorliegen würde als das finale Bild und nach dem Tonemapping wieder eckig aussehen würde (was sich auch nicht vermeiden lässt, da man beim Rendern der Sprite nicht weiß, mit welcher Helligkeitskurve das Bild letztendlich ausgegeben werden wird).
Das kann ich mir graphisch irgendwie gerade nicht visualisieren. Sieht das dann eckig aus, weil der anti-aliaste Rand einfach durch das Tonemapping sehr, sehr dunkel wird, und man darum den Eindruck bekommt, es wird überhaupt gar kein Anti-Aliasing betrieben? Bei einem anderen Tonemapping könnte dann dementsprechend eine zu helle Korona an dem Anti-Aliasing-Rand erscheinen. Das prinzipielle Problem mit HDR und Alphakanälen ist mir aber klar, denn das Anti-Aliasing sollte in der Theorie erst nach dem Tonemapping erfolgen ;)
Benutzeravatar
Krishty
Establishment
Beiträge: 8311
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Krishty »

eXile hat geschrieben:Sollte die Core.exe in einem Pfad mit Umlauten liegen, so findet er das Plugin nicht.
Sehr schöner Fund, danke! Keine Typsicherheit bei der Unterscheidung von ASCII und UTF-8, weil C++ noch keine UTF-8-Literale anbietet, und schon passiert sowas. Ist gefixt.
eXile hat geschrieben:(Die Umlaute habe ich einfach mal so kopiert, wie WordPad mir die Datei angezeigt hat.)
Hmm, scheinbar kann Wordpad kein UTF-8 automatisch erkennen (aber immerhin packt es die Zeilenumbrüche). Btw ist Notepad++ klasse :)
eXile hat geschrieben:Eine andere Sache: Beim Wechsel zwischen Vollbildschirm und Fenstermodus wird die Kamerarichtung verändert. Vielleicht einfach bei einem solchen Wechsel die relative Mausposition zurücksetzen?
Oha. Tatsächlich setzt D3D die Maus beim Moduswechsel immer in die Mitte zurück. Werde zusehen, wie ich das unter Kontrolle kriege.
eXile hat geschrieben:Sieht das dann eckig aus, weil der anti-aliaste Rand einfach durch das Tonemapping sehr, sehr dunkel wird, und man darum den Eindruck bekommt, es wird überhaupt gar kein Anti-Aliasing betrieben?
Ja, nur andersrum – die Sprite wäre ständig überbelichtet, weil sie – vor allem nachts – das hellste Objekt am Himmel wäre. Dann „kriecht“ die Helligkeit im Extremfall in die geantialiasten Ränder hinein, bis die Pixel ganz ausgefüllt werden und nur der volltransparente Rand als pixelige Grenze bleibt; aber auch schon vorher wird die Helligkeitskurve so verbogen, dass es kantiger erscheint.
Alexander Kornrumpf hat geschrieben:Speziell für dich dürfte es interessant sein zu erfahren dass effizient eine binäre Kategorie ist. Effizienter als effizient geht es nicht und am effizientesten schon gar nicht.
Das Wort "effektiv" ist logischerweise nicht steigerbar; entweder hat etwas einen Effekt oder nicht. Bei "effizient" hingegen lassen sich durchaus Abstufungen unterscheiden, eine bestimmte Vorgehensweise kann effizienter sein als eine andere.
(Quelle) Mehr Glück beim nächsten Mal ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2136
Registriert: 25.02.2009, 13:37

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Alexander Kornrumpf »

Ich denke das jetzt ausführlich zu diskutieren, insbesondere die Kompetenz von Herrn Sick in dieser Frage, wäre wohl das größte Off-Topic aller Zeiten. Auch wenn es mir wirklich schwerfällt den Schmarrn vom Sick so stehen zu lassen. Nur um nicht völlig dumm dazustehen:

1) Der Unterschied zwischen effektiv und effizient ist mir bewusst.

2) Ich bezog mich jedenfalls auf diese Definition von Effizienz:
http://books.google.de/books?id=hqog9vj ... oQ6AEwATgK

Auch hier (weniger Quellencharakter, aber dafür kürzer):
http://img115.imageshack.us/img115/7441 ... ionzl5.jpg
via
http://de.answers.yahoo.com/question/in ... 229AAD5lPg
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von kimmi »

Kann mir mal jemand sagen, was die effektiv-against-effizient-Diskussion hier zu suchen hat?

Und ich kann mir leider deine Demo nicht ansehen, da ich hier im Büro XP benutze. Aber die Bilder schauen sehr vielversprechend aus und zu Hause stürze ich mich gleich darauf.

Gruß Kimmi
Alexander Kornrumpf
Moderator
Beiträge: 2136
Registriert: 25.02.2009, 13:37

Re: Kurzartikel: Hochwertiges Rendern von Sternen

Beitrag von Alexander Kornrumpf »

Hat hier nichts zu suchen, war nur eine Reaktion auf den inneren Stromschlag den ich verspürte als Krishty "am effizientesten" schrieb. Sorry.
Antworten