Tutorial - Terrestrische Planeten - Teil 1
| Veröffentlicht: |
06.11.2025 |
Schritt für Schritt Anleitung, wie mit Povray realistische Abbilder von terrestrischen Planeten erzeugt werden können, für die hochauflösende Karten zur Verfügung stehen.
In
Teil 1 wird die reine Entwicklung des Skriptes mit dem nötigen Code und Kommentaren erklärt.
Teil 2 spricht diverse Verbesserungen an, mögliche Datenquellen, und einiges mehr.
Die 1600x900 Pixel großen Bilder auf dieser Seite sind allesamt originale Resultate der Skripte, ohne jede Veränderung. Lediglich die runterskalierten Versionen habe ich ein wenig scharfzeichnen lassen.
Ziel
Ziel ist es, rechteckige Karten in eine runde Form zu bringen, und obendrein Povray realistische Schatten erzeugen zu lassen. Dafür brauchen wir zwei Karten eines Himmelskörpers, in unserem Fall dem Mond.
Erstens eine möglichst reine Farb-Karte der
Oberfläche. Diese sollte
keine Schatten enthalten, sondern nur die Farbwerte der Oberfläche. Als wäre jeder Bereich genau von oben bzw. senkrecht von der Sonne beschienen.
Zweitens benötigen wir eine Höhenkarte, im englischen
DEM genannt (Digital Elevation Map). Bei ihr steht schwarz für den tiefsten Punkt, weiß für den höchsten, Grauwerte bilden die Werte dazwischen.
Beide Karten sind doppelt so breit wie hoch und wirken in der rechteckigen Version zu den Polen hin in der Breite verzerrt. Das ist ganz normal, da die rechteckigen Karten um eine Kugel gelegt und die Polregionen von Povray zusammengestaucht werden.

Mond Oberfläche

Mond Höhenkarte
Download
Damit die hier gezeigten Skripte gleich ausprobiert und nachvollzogen werden können, sind sämtliche Dateien im untenstehenden Zip-File enthalten. Um die Dateigröße klein zu halten, wurde auf hochauflösende Bilder verzichtet und maximal 4000x2000 Pixel große Karten verwendet.
⬇
tutorial_povray_planets.zip => 9 Dateien - 17 MB
Die einzelnen Schritte können mit Kommandozeilen ausgeführt werden, die ganz oben im jeweiligen Skript hinterlegt sind. Beispiel:
povray +Ima_tutorial_planet_step1.pov +Otest/step1.png +w1600 +h1200 -GR +A
Schritt 1 - Image-Map
Basis aller Beispiele ist eine Kugel, die auf <0,0,0> erzeugt und deren Textur mit jedem Schritt verändert wird.
#version 3.7;
global_settings { assumed_gamma 1.0 charset utf8 }
#local oPlanet = sphere {
<0,0,0> 1
texture {
pigment {
image_map {
jpeg "map_moon_4k_surface.jpg"
map_type 1 //1 = spherical
}
}
finish { ambient rgb (<2,1,1> * 0.01) }
}
}
object {
oPlanet
rotate y*-90
}
light_source {
<0,0,100000>
color <1,1,1>
rotate y*130
}
camera { perspective right x*image_width/image_height sky <0,1,0>
location <0,0,-20>
look_at <0,0,0>
angle 10
}
In dem Beispiel nehmen wir eine handelsübliche Kugel mit einem Radius von 1 Units, statt einer farblichen Textur verwenden wir eine
Image-Map mit dem Name
map_moon_surface.jpg.
Diese
Image-Map legt das gewählte Bild kugelförmig mit
map_type 1 um die Kugel. Das
Finish-Statement regelt die Farbgebung der Bereiche, die im Schatten liegen.
Siehe auch:
Povray Dokumentation: Bitmap Modifiers
texture {
pigment {
image_map {
jpeg "map_moon_4k_surface.jpg"
map_type 1 //1 = spherical
}
}
finish { ambient rgb (<2,1,1> * 0.01) }
}
Anschließend geben wird das Objekt aus und drehen es um -90 Grad, damit die Vorderseite des Mondes nach Z- ausgerichtet ist. Wer die Rückseite sehen möchte, trage +90 Grad ein.
object {
oPlanet
rotate y*-90
}
Die Lichtquelle wird auf Z+ gesetzt (hinter die Kugel) und frei nach Wunsch rotiert.
rotate y*90 steht für zunehmenden Halbmond,
y*180 für Vollmond, wir entscheiden uns für eine Zwischenvariante.
light_source {
<0,0,100000>
color <1,1,1>
rotate y*130
}
Die Kamera wird auf Z = -20 positioniert.
camera { perspective right x*image_width/image_height sky <0,1,0>
location <0,0,-20>
look_at <0,0,0>
angle 10
}
Das Ergebnis ist schonmal interessant, aber noch nicht, was wir haben wollen.
Schritt 2 - Image-Map + Bump-Map
Nur mit der Image-Map erhalten wir eine absolut runde Kugel, ohne jeden Schattenwurf. Außer natürlich, das die der Lichtquelle abgewandte Seite im Schatten liegt, aber keiner der Krater und Berge erzeugt dunkle Bereiche.
Um erste Schattenwürfe zu erzeugen, fügen wir zwischen
Pigment und
Finish ein
Normal-Statement ein.
pigment { ... } //unverändert wie Schritt 1
normal {
bump_map {
png "map_moon_4k_dem.png"
map_type 1
interpolate 2
bump_size 100 once //Height of the DEM
}
}
finish { ... } //unverändert wie Schritt 1
Die
Bump-Map sorgt für "simulierte" Schattenwürfe. Natürlich ist in Povray alles simuliert, aber diese Schattenwürfe noch ein bisschen mehr als sonst.
Der Wert hinter
bump_size stellt die Höhe der Schattenwürfe ein, die hier überzogen eingestellt sind.
Damit bekommen wir bereits ein besseres Ergebnis.
Vergrößern wir einen Bereich nahe des Terminators (der Tag/Nacht-Grenze), passen dafür die Kamera-Einstellung an - unsere Ziele sind das
Mare Humorum und der auf 12 Uhr liegende Krater
Gassendi.
camera { perspective right x*image_width/image_height sky <0,1,0>
location <0,0,-20>
look_at <-.5,-.4,-.5>
angle 2
}
Gleich wird eine der Unzulänglichkeiten von
Bump-Maps sichtbar:
Die runde Kugel ist noch immer absolut rund.
Es gibt keine herausragende Höhen/Beulen für Berge und keine Einschnitte für Täler und Krater. Der beleuchtete Teil der Kugel hat einen scharfen Rand, selbst riesig hohe, dahinterliegende Bereiche bekommen nichtmal an der Spitze Licht ab.
Die Schatten sind nur simuliert, Povray tut als ob und ändert lediglich die Farbe der Oberfläche, Pi mal Daumen, damit es von weitem nach einem Schattenwurf aussieht.
Schritt 3 - Spherical Heightfield
Echte und realistische Schattenwürfe lassen sich mit Bump-Maps nicht erzeugen, dafür benötigen wir
Spherical Heightfields.
Ändern wird das komplette Skript ab. Dabei kümmern wir uns nur um die Schattenwürfe, lassen die Surface-Map erstmal weg und verwenden an dessen Stelle eine simple Farb-Textur.
//Dateianfang wie zuvor
#local nRadius = 1;
#local nFactor = 0.35;
#local nHeightDiff = 50; // the more the higher the contrast between valleys and hills
#local PlanetSphere_F = function {internal(61)}
#local PlanetHeightfield_F = function {
pigment {
image_map {
png "map_moon_4k_dem.png"
map_type 1
interpolate 2
}
}
}
#local oPlanet = isosurface {
function {
PlanetSphere_F(x,y,z, nRadius)
- PlanetHeightfield_F(x,y,z).gray*nHeightDiff/1000*nRadius
+ nFactor*nRadius
}
contained_by { sphere{0, nRadius} }
max_gradient 1.3
accuracy 0.0001
texture {
pigment {
color rgb (<1,1,1>*.5) //Instead the surface-map
}
}
finish { ambient rgb (<2,1,1> * 0.004) }
scale 1/(1-nFactor)
}
//Ausgabe, Kamera und Lichtquelle wie zuvor
Und Voila, da sind unsere Schattenwürfe.
Schon auf den ersten Blick wirkt der Bereich um den Terminator zerfranzt, wie er sein sollte.
Was passiert in den neuen Zeilen?
Ehrlich gesagt ... so genau hab ich das selbst nicht kapiert.
Ich hab mir damals ziemlich einen abgebrochen, war auf dem richtigen Weg, habe hin und her probiert, mal wurde es besser und mal schlechter. Schließlich bin ich in einem fertigen Skript auf die richtigen Zeilen gestoßen.
Tatsache ist, es wird eine
Isosurface mit Hilfe der bereitgestellten Funktionen erzeugt. Die Funktion
PlanetHeightfield_F liefert für jeden Punkt der Kugel einen Höhenwert, der weiter verarbeitet wird. Wie genau, da muss ich irgendwann nochmal bei.
Spielt keine Rolle, die Zeilen funktionieren und wir haben echte Schattenwürfe.
Schritt 4 - radiale Bildfehler
Unser bisheriges Resultat hat jedoch einen nervigen Makel.
Zoomen wir hinein, wieder auf das
Mare Humorum im unteren Bereich, ändern dafür in der Datei
Step-3 die Einstellungen der Kamera.
camera { perspective right x*image_width/image_height sky <0,1,0>
location <0,0,-20>
look_at <-.51,-.41,-.5>
angle 2
}
Sieht auf den ersten Blick sehr nett aus, hell beleuchtet Bergspitzen auf dunklem Boden.
Beim zweiten Blick (nach Klick auf das Bild) tauchen direkt am Terminator seltsame Schatten auf, die da nichts zu suchen haben. Radial um kleine Krater und drumherum, die nichts mit dem Kartenmaterial oder (für mich) rational erklärbaren Povray-Einstellungen zu tun haben.
Alles richtig gemacht, müsste funktionieren, und doch sind sie da.
Auch da habe ich ziemlich dran gearbeitet und getüftelt, bis mir das
Povray-Forum die rettende Idee lieferte.
An der Stelle eine ganz klare Erkenntnis:
SIZE - DOES - MATTER
Der
Radius unseres Planeten muss deutlich erhöht werden. Nicht von 1 auf 10 oder 100, gehen wir gleich auf
1000.
Nachteil: Die Renderzeit steigt deutlich an. Zu sehr sollte man es mit der Objektgröße nicht übertreiben.
Natürlich muss dann auch die Kamera um einen ähnlichen Faktor verschoben werden.
camera { perspective right x*image_width/image_height sky <0,1,0>
location <0,0,-20000>
look_at <-510,-410,-500>
angle 2
}
Sieht gleich wesentlich besser aus.
Als letztes ersetzen wir das Pigment durch eine Image-Map, damit die originalen Oberflächen-Farben zu Geltung kommen.
pigment {
//color rgb (<1,1,1>*.5) //Test-Farbe
image_map {
jpeg "map_moon_4k_surface.jpg"
map_type 1
}
}
That's it!
Abgesehen von der pixeligen Darstellung, was definitiv an den nur 4000x2000 großen Karten liegt, haben wir einen fertigen Planeten bzw. fertigen Mond.
- - -
Job erledigt, Mond lebt,
Teil 1 des Tutorials ist absolviert.
Für finale Bilder und abschließende Informationen siehe
Teil 2.