© Liashko/Shutterstock.com
Atmosphärendarstellung, Streueffekte und scheinbare Sonnenbahnen

From Dusk till Dawn


Gameplay-relevante Tag-Nacht-Wechsel gehören zu den neuesten Features in aktuellen Computerspielen. Von nun an müssen wir uns als Programmierer damit befassen, wie man die Bewegung der Sonne in Abhängigkeit von der Jahreszeit und dem gewählten Spiele-Setting simulieren kann, welchen Einfluss der Sonnenstand auf die Lichtverhältnisse in der Spielewelt hat und wie sich damit verbunden die Farbverläufe am Himmel berechnen lassen.

Seit dem Release des mittlerweile schon legendären Computerspiels Crysis im Jahr 2007 sind die Anforderungen an einen Spieleprogrammierer in vielerlei Hinsicht rasant gestiegen. Nachdem wir uns in den letzten Artikeln bereits mit dem HDR Rendering, dem Post Processing sowie mit realistischen Beleuchtungs- und Schattenberechnungen befasst haben, widmen wir uns heute der Atmosphärendarstellung und den damit verbundenen dynamischen Tag-Nacht-Wechseln, da beide Features in immer zahlreicheren Spieletiteln einen hohen Stellenwert einnehmen.

Sieht man einmal von Flugsimulationen ab, so wurden Hintergrundlandschaften samt Firmament über einen langen Zeitraum lediglich statisch in Form eines 360°-Panoramabilds in einen Spielelevel eingebunden. Hierfür wird beim Design der Spielewelt zunächst der Szenenhintergrund mittels kubischer Projektion auf sechs Texturen aufgeteilt, die dann im laufenden Spiel auf die Innenfläche einer so genannten Sky Box gemappt werden.

Entschuldigung, wie spät ist es?

Im richtigen Leben genügt ein kurzer Blick auf die Uhr, um die eingangs gestellte Frage zu beantworten. In einem Spiel hingegen ist das Problem der wechselseitigen Umrechnung von Simulationszeit – die Zeit, die seit dem Spielstart vergangen ist und die unter anderem für das Mission Scripting benötigt wird – und Uhrzeit jedoch ein klein wenig verzwickter. Da die Simulationszeit normalerweise in Sekundenintervallen angegeben wird, besteht unsere erste Aufgabe zunächst darin, aus der Anzahl der verstrichenen Minuten, Stunden und Tage die Anzahl der vergangenen Sekunden zu ermitteln:

  • Eine Minute hat 60 Sekunden.

  • Eine Stunde hat 60 Minuten bzw. 3 600 Sekunden.

  • Ein Tag hat 24 Stunden bzw. 1 440 Minuten bzw. 86 400 Sekunden.

ActualTime = (float)Seconds + (float)Minutes*60.0f + (float)Hours*3600.0f + (float)Days*86400f; Time_GameStart = (float)Seconds_GameStart + (float)Minutes_GameStart*60.0f + (float)Hours_GameStart*3600.0f + (float)Days_GameStart*86400f; SimulationTime = ActualTime - Time_GameStart

Um die aktuelle Simulationszeit in die zugehörige Uhrzeit umrechnen zu können, müssen wir zunächst die Anzahl der bereits vergangenen Tage aus der Zeitangabe herausrechnen, wobei es zu beachten gilt, dass nach jeweils 86 400 Sekunden ein neuer Tag anbricht:

ActualTime = SimulationTime + Time_GameStart – (float)Days*86400f

Teilt man nun die verbleibende Zeit (ActualTime: Sekundenzeit) durch den Wert 3 600 (3 600 Sekunden entsprechen einer Stunde) und verwirft im Anschluss daran den Nachkommaanteil (Ganzzahl-Division), so erhält man die aktuelle Stunde:

Hours = (long)(ActualTime/3600.0f);

Um die Anzahl der Minuten bestimmen zu können, muss man die Differenz aus der ActualTime und der zuvor berechneten Stundenanzahl (angegeben in Sekunden) ermitteln und das Ergebnis dann durch 60 (eine Minute hat 60 Sekunden) dividieren:

Minutes = (long)((ActualTime-Hours*3600.0f)/60.0f);

Die Zahl der verbleibenden Sekunden erhalten wir, indem wir von der aktuellen Sekundenzeit sowohl die Anzahl der verstrichenen Stunden als auch die der Minuten (beides angegeben in Sekunden) abzieht:

Seconds = (long)ActualTime-Hours*3600-Minutes*60;

Scheinbare Sonnenbahnen am Äquator und Nordpol

Bereits im Kindesalter lernen wir, dass die Sonne morgens im Osten aufgeht, zur Mittagszeit gen Süden zeigt und am Abend im Westen untergeht; dass die Sonne in den Sommermonaten deutlich höher am Firmament steht als im Winter und dass dies einen direkten Einfluss auf die jeweilige Tages- und Nachtlänge hat. Schön und gut, nur leider entsprechen unsere alltäglichen Erfahrungen in keiner Weise den Beobachtungen, die ein Bewohner beispielsweise am Äquator oder am Nordpol machen würde. Zum besseren Verständnis sind in den Abbildungen 1 und 2 jeweils drei Sonnenbahnen skizziert, wie man sie am Äquator (Latitude/Breitengrad 0°) und am Nordpol (Breitengrad 90°) am Frühlings- (21. März) bzw. Herbstanfang (23. September) sowie an den Tagen der Winter- (21. Dezember) und Sommersonnenwende (21. Juni) wahrnehmen würde.

rudolph_1.tif_fmt1.jpgAbb. 1: Sonnenbahnen am Äquator
rudolph_2.tif_fmt1.jpgAbb. 2: Sonnenbahnen am Nordpol

Wie Abbildung 1 zu entnehmen ist, verlaufen die Bahnen der Sonne am Äquator das ganze Jahr über senkrecht zum Horizont, was zu abrupten Tag-Nacht-Wechseln mit extrem kurzen Dämmerungsphasen führt. Während die Sonne am Frühlings- bzw. Herbstanfang zur Mittagszeit einen Höchststand von 90° erreicht (Zenit), beträgt die mittägliche Sonnenhöhe an den Sonnenwendtagen aufgrund der Erdachsenneigung von 23,5° lediglich 66,5° (90°–23,5°). Ein ganz anderes Bild zeigt sich hingegen an den Polen, denn dort verlaufen die Sonnenbahnen parallel zum Horizont. Am Nordpol (Abb. 2) befindet sich die Sonne in den Wintermonaten unterhalb und in den Sommermonaten oberhalb des Horizonts. Infolgedessen muss man im Winter ein halbes Jahr auf einen Sonnenaufgang warten (Polarnacht), wohingegen man im Sommer sechs Monate Tageslicht genießen kann (Polartag). Während die Sonne am Tag der Sommersonnenwende ihren Höchststand von 23,5° erreicht, befindet sie sich zur Wintersonnenwende, am Tag des niedrigsten Sonnenstands, 23,5° unterhalb des Horizonts.

Würde nun die Erdachse senkrecht zur Bewegungsrichtung bzw. zum Orbit der Erde orientiert sein (Erdachsenneigung von 0°), dann bliebe die Sonnenbahn das ganze Jahr über unverändert. Wechselnde Jahreszeiten existierten nicht, da der Einfallswinkel der Sonnenstrahlen im Verlauf des Jahres auf einem Breitenkreis zu einer festgelegten Uhrzeit immer konstant bliebe.

Sonnenbahnen unter Vernachlässigung der Erdachsenneigung

Ohne genaue Kenntnis von der Position der Sonne zum Zeitpunkt des Spielgeschehens ist es schlicht und einfach unmöglich, die Outdoor-Lichtverhältnisse in der Spielewelt glaubhaft zu simulieren. An dieser Stelle werden wir zunächst die Bewegung der Sonne unter Vernachlässigung der Erdachsenneigung berechnen. Jahreszeitliche Änderungen bleiben hierbei unberücksichtigt, da wir als Ergebnis lediglich die vom jeweiligen Breitengrad (also vom Ort des Spielgeschehens) abhängige Sonnenbahn zum Zeitpunkt des Frühlings- bzw. Herbstanfangs erhalten. Im ersten Schritt gilt es nun, die Rotationsachse der Sonne in Abhängigkeit vom Breitengrad zu berechnen, wobei wir in Übereinstimmung mit Abbildung 1 und 2 für den Nordpol (Latitude = 90°) eine Rotationsachse von (0, 1, 0) und für den Äquator (Latitude = 0°) eine Rotationsachse von (1, 0, 0) erhalten (Listing 1).

Listing 1

// Polarwinkel der Sonnen-Rotationsachse: float HorizontalAngle, VerticalAngle; // Rotationsachse: D3DXVECTOR3 SunRotationAxis; HorizontalAngle = 90.0f*D3DX_PI/180.0f; VerticalAngle = Latitude*D3DX_PI/180.0f; // Polarkoordinaten der Rotationsachse: SunRotationAxis.x = cos(VerticalAngle)*sin(HorizontalAngle); SunRotationAxis.y = sin(VerticalAngle); SunRotationAxis.z = cos(VerticalAngle)*cos(HorizontalAngle);

Mithilfe der zuvor berechneten Rotationsachse lässt sich im zweiten Schritt eine Rotationsmatrix (SunRotationMatrix) konstruieren, aus der wir dann die Position der Sonne bzw. die zugehörige Himmelsrichtung (SunDirectionUncorrected) auslesen können. Hierbei machen wir uns zunutze, dass die Sonne in 24 Stunden (86 400 Sekunden) eine vollständige Drehung um die Rotationsachse (Drehwinkel = 2PI) vollführt, und berücksichtigen ferner die Tatsache, dass die Sonne am Äquator um exakt 18 Uhr (18 Uhr * 60 Minuten * 60 Sekunden = 64 800) im Westen – mit anderen Worten in Richtung (0, 0, 1) – untergeht (Listing 2).

Listing 2

float SolarRotation_PerSecond = 2.0f*D3DX_PI/86400.0f; float ActualSolarRotationAngle = SolarRotation_PerSecond * (ActualTime - 64800.0f); // Himmelsrichtung ohne Berücksichtigung der Erdachsenneigung: D3DXVECTOR3 SunDirectionUncorrected; D3DXMATRIXA16 SunRotationMatrix; D3DXMatrixRotationAxis(&SunRotationMatrix, &SunRotationAxis, ActualSolarRotationAngle); // Himmelsrichtung aus der Rotationsmatrix auslesen: SunDirectionUncorrected.x = SunRotationMatrix._31; SunDirectionUncorrected.y = SunRotationMatrix._32; SunDirectionUncorrected.z = SunRotationMatrix._33;

Wechselnde Jahreszeiten

Möchte man im Spielverlauf, im Rahmen einer mehrmonatigen Kampagne (typisches Beispiel: ein Weltkriegsszenario), gleichermaßen sowohl unterschiedliche Orte als auch wechselnde Jahreszeiten berücksichtigen, dann müssen wir in unsere Berechnung der Sonnenstände zusätzlich zum Breitengrad auch die Erdachsenneigung von 23,5° (AxialTilt) einbeziehen. Anhand von Abbildung 1 und 2 können Sie den Einfluss dieser Neigung auf die äquatorialen bzw. polaren Sonnenbahnen nach...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang