Home

Flexible Heightfields

Montag, 28. April 2008 | Autor:

Wer schon einmal versucht hat ein, importiertes Terrain, also ein Heightfield, wie in TG0.9 über den gesamten Planeten zu spannen, wird Probleme bekommen haben, denn im Normalfall passen sich die Heightfields der Krümmung des Planeten nicht an.

Wo genau liegt eigentlich das Problem? Ganz einfach. Lädt man ein Heightfield und skaliert es hoch, kommt Folgendes dabei heraus:

hf-prob-01.jpg

Nicht genug damit, dass das Terrain so gar keine Anstalten macht, die Krümmung des Planeten zu beachten, zu allem Übel ergibt sich auch ein Konflikt mit dem Surface-System, welches die Kugelform sehr wohl mit einberechnet. (Genau genommen könnte man das abstellen, indem man in den Surface Layern jeweils „Use Y for altitude“ einstellt)

Vielleicht erinnert sich aber der ein oder andere an die Option „Flatten surface first“ (dt.: Oberfläche vorher einebnen). Sie befindet sich in den Optionen des Heightfield Shader im Displacement-Tab und produziert eine vollkommen plane Fläche, bevor das Heightfield darauf gesetzt wird. Stellt man sie ab, kommt folgendes heraus:

hf-prob-02.jpg

Problem gelöst! .. oder? Tatsächlich reicht diese Lösung mitunter schon aus.

Einige Probleme bestehen allerdings weiterhin. Zum einen wird das Heightfield an den Ecken stark gestreckt. Dadurch ist das Terrain dort niedriger aufgelöst und verzerrt. Zum anderen geschieht das Displacement bei Heightfields immer in Y-Richtung, also direkt nach oben.

hf-prob-031.jpg

Gut zu erkennen: statt senkrecht zur Erdoberfläche (blau), findet das Displacement in Y-Richtung (rot) statt.

Diese Dinge scheinen nun nicht so schlimm zu sein. Will man das Terrain allerdings noch weiter strecken, um beispielsweise den halben Planeten abzudecken, bekommt man durchaus Probleme.

Die Lösung

Vor nicht all zu langer Zeit gab es bei uns einen Artikel, in dem wir geschrieben hatten, dass man via „Heightfield load“ nicht nur Terrains, sondern auch normale Bilder laden kann. Wenn das funktioniert.. kann man dann auch Terrains mit dem Image Map-Shader (im folgenden IMS genannt) laden? Nehmen wir erstmal an das ginge. Dann könnten wir eine Kamera in die Mitte unseres Planeten setzen und das Terrain quasi von innen an den Planeten projizieren!

camplanet.jpg

Wer sich mit den Möglichkeiten des Image map shaders auskennt, wird sicherlich schon ahnen was kommt – wir nutzen dessen Displacement-Funktion. Die Vorteile liegen auf der Hand:

  • das Displacement des IMS wirkt senkrecht zur Planetenoberfläche
  • weniger Verzerrungen – wir nutzen die Projektion der Kamera
  • wollen wir das Displacement genauer kontrollieren, können wir den Output des IMS an einen Displacement shader anschließen und dessen Funktionen nutzen
  • das Heightfield kann frei rotiert werden, indem wir die Kamera drehen

Einen Nachteil gibt es allerdings auch: Das Heightfield ist wegen der Projektion von innen heraus spiegelverkehrt.

Wir haben bisher einfach angenommen, dass das so alles geht – aber tut es das nun? Die Antwort lautet: Ja, mit ein paar Handgriffen schon.

Der IMS kann keine Heightfields laden, sondern nur Bilder. Wenn wir also ein Terrain im .ter-Format haben, nützt uns dieses zunächst nichts. Terrain-Editoren beherrschen aber in der Regel noch andere Formate. Diese unterscheiden sich vor allem in der Genauigkeit/Farbtiefe (8-bit, 16-bit, …) und im Maß in dem sie von anderen Programmen unterstützt werden.

Vorarbeit und Hintergrund

.ter-Terrains haben 16 Bit. Ein Terrain mittels Editor als Bitmap (.bmp) oder ein anderes normales Bildormat abzuspeichern stellt keine Hürde dar. Allerdings haben diese Farb-Formate meist 8 Bit pro Kanal (3 Kanäle * 8 bit = 24 Bit). Wir benötigen aber ein Format, dass alle Bits nur für die Helligkeit=Höheninformation nutzt. Für gute Resultate sollte man immer auf die 16-bit-Varianten zurückgreifen, denn diese können die Höhe über 200 mal genauer angeben, als ein 8-bit-Format. An folgendem, absichtlich hässlich eingestellten, Beispiel kann man den Unterschied gut erkennen:

Bei 8-bit-Genauigkeit ist die Differenz zwischen zwei Pixeln immer hoch, bei 16-bit-Formaten hingegen können auch sehr kleine Höhenänderungen akkurat wiedergegeben werden.

Ein solches Format mit 16 Bit „Farb“tiefe ist TIFF (.tif oder .tiff), ein anderes ist PNG. Da beide Formate auch für 3 * 8 Bit Farbbilder genutzt werden können, sollte man darauf achten, dass der Terraineditor tatsächlich die 16-bit-Variante einsetzt (was er in der Regel tun wird). World Machine beispielsweise zeigt beim Speichern eine Übersicht, welches Format 16 bit hat und welches nur 8.

Leider lässt TG2 diese Formate nicht zu, man bekommt eine Fehlermeldung:

Please convert image to SGI for non-standard bit depths.

Auf Deutsch: „Bitte konvertiere das Bild ins SGI-Format für nicht-standard Farbtiefen.“ Das SGI-Format wird man als normaler Mensch kaum kennen. Glücklicherweise aber gibt es im Netz Konverter dafür. Auch hier gilt allerdings wieder: nicht alle speichern mit 16 Bit. Wer irgendeine Version von Photoshop besitzt, hat Glück gehabt und kann auf das freie SGI-Format-Plugin von Toby Thain zurückgreifen! Es lädt und speichert Dateien im SGI-Format, optional auch komprimiert.

Implementierung in TG2

Nun, da wir unser Bild als SGI vorliegen haben, können wir loslegen! Zuerst muss, falls noch nicht geschehen, ein Image map shader hinzugefügt werden. Das geht, wie sonst auch, im Terrain-Tab mit Add Terrain > Displacement Shader > Image map shader. Ein eventuell vorhandener Heightfield shader kann danach gelöscht werden.

Für die Projektion wird noch eine Kamera benötigt. Diese erzeugen wir im Netzwerk mit Rechtsklick > Create Other > Camera und schließen sie direkt an den mittleren Port des IMS an.

Dann aktivieren wir im Displacement-Tab des IMS gleich mal „Apply displacement“ und stellen Displacement amplitude auf eine Millionen. Das ist unrealistisch, hilft uns aber den Erfolg unserer Arbeit zu sehen. Außerdem stellen wir unter Color „Unpremultiply“ aus, „Data is linear“ an und stellen ganz unten für Border blending den gewünschten Wert ein, beispielsweise den Standardwert des Heightfield shader: 0.1.

Nun müssen wir noch einige Einstellungen an der Kamera vornehmen (siehe Screenshot), damit sie tatsächlich vom Erdmittelpunkt aus projiziert. Dazu öffnen wir die Optionen des Planeten und die der Kamera (ggf. Stay Open aktivieren).

Die Position des Erdmittelpunkt übertragen wir direkt vom Planeten. Besonders wichtig ist der mittlere, der Y-Wert. Die anderen beiden sollten auf Null eingestellt werden. Die Rotation der Kamera sollte auf 90; 0; 0 geändert werden, damit die Kamera direkt nach oben zeigt. Hier kann man natürlich auch andere Werte nehmen, je nachdem, wo man am Ende das Terrain hin haben will.

Ganz unten kann man noch den Winkel einstellen, den unsere Kamera, und somit unser Terrain, abdeckt.

Fertig!

Das ganze sieht jetzt so aus:

Gut zu erkennen: Das Displacement wirkt nun senkrecht zur Planetenoberfläche (blau). Man kann auch gut sehen, wie die Kamera im Erdmittelpunkt das Terrain aufspannt.

Nachteil

Ein Problem gibt es noch. Das Heightfield ist spiegelverkehrt. Sobald die „Flip x/y“ -Option des IMS funktioniert, kann man das durch Aktivierung einer der beiden Optionen lösen. Bis dahin muss das Heightfield in einem externen Programm gespiegelt werden. Das könnte man beispielsweise in Photoshop vor dem Speichern als SGI erledigen.

Fazit

Mit dieser Methode kann man so einiges anstellen, Heightfields rotieren beispielsweise.. oder ein Heightfield sich um den Planeten herum wiederholen lassen. (Repeat x/y)

Der Image map shader bietet hier viel Raum zum experimentieren,
Viel Spaß dabei!

Tags »

Trackback: