Proceduell planet med atmosfär

Proceduell planet med atmosfär
Toms Vulfs
[email protected]
Sammanfattning
Rapporten beskriver hur en realistisk atmosfär genereras utifrån fysikaliska egenskaper hos ljus och luft partiklar i en atmosfär.
Atmosfärisk ljusspridning förklaras samt tidigare arbeten inom området undersöks. En algoritm utvecklas ur teorin för att passa in
i beräkningar på en GPU i form av vertex och pixel shaders. Andra proceduella metoder för att skapa ett visuellt tilltalande
karaktär på planeten finns också beskrivna.
1. Inledning
I utomhusscener i datorgrafik är det viktigt att beräkna
atmosfärisk spridning av ljus för att åstadkomma en realistisk
miljö. På dagtid upplever vi att himlen blir blå och vid
solnedgång och soluppgång blir himlen gulaktig och röd.
Dessa färger och ljusheten bestäms av ljusspridningen i
atmosfären.
Från rymden varierar färgen på atmosfären beroende på var
åskådaren och solen befinner sig därav ser vi i satellitbilder att
jorden är ”blå”. Vid kanten av skuggan på jorden blir
atmosfären rödaktig även från rymden. Färgen på molnen
varierar också beroende på var solen befinner sig.
Färgen inifrån atmosfären varierar inte bara från solens
position men även föroreningen, vädret och andra faktorer som
förändrar partiklarna i luften gör att vi upplever utomhus
färgerna olika. På planeter med olika gaser och partiklar i
luften, jämfört med jordens, förändras dessa effekter avsevärt.
2. Tidigare arbete
Tidigare inom datorgrafik har bilder på jorden gjorts utan
att ta hänsyn till dom fysikaliska egenskaper av partiklarna i
luften men i 1993 föreslog Nishita en metod där man
beräknade dessa optiska effekter för att ta fram en mer
realistisk bild på jorden. Dessa bilder tog mellan 4 – 12
minuter att generera på en IRIS Indigo dator med Elan grafik,
som på den tiden var ganska bra men den saknade textur
minne, och datorns processor på 150Mhz. I denna
implementation en tvådimensionell uppslagstabell skapades
för att beräkna den optiska längden för att accelerera
renderingen.
Senare vid 2001 föreslog Hoffman tillsammans med
Preetham[2] ett effektivt sätt att beräkna atmosfärisk spridning
för utomhusscener. Här beräknades både ut- och inljusspridning samt absorbering av ljus i partiklarna i luften.
Det var alltså möjligt att rendera disig och förorenad atmosfär
såsom klar och ren atmosfär. Spridningen av ljus beräknades
också mot avlägsna objekt som berg. Ekvationerna
implementerades i fragment och vertex shaders så att realtids
rendering var möjlig. Denna implementation var dock enbart
för låga kamera positioner dvs. kameran var placerad nära ytan
detta gör att atmosfären kan antas ha konstant densitet över
alla höjder och därför förenklar ekvationer introducerade från
Nishita.
Sean O'Neil, 2004 skrevs[3] det om implementation av de
fullständiga ekvationer från Nishita. Även här användes det en
förberäknad två dimensionell uppslagstabell med fyra kanaler
för beräkning av färg för varje vertex. Denna implementation
kördes på CPU för att vid den tidpunkt som atrikeln skrevs
fanns det inga grafikkort som klarade av dessa beräkningar i
shaders. I denna implementation kunde man dock flyga ut och
in från atmosfären och få en korrekt visualisering då densiteten
föll exponentiellt när höjden från ytan ökade.
I denna rapport baseras implementationen på Sean
O'Neil[4] förslag till lösning av atmosfärisk spriding på GPU
med fragment och vertex shaders för att åstadkomma realtids
rendering och interaktion.
3. Atmosfärisk ljusspridning
Solljus som tränger sig genom atmosfären kan absorberas,
spridas, reflekteras och brytas innan de når någon yta.
Människor upplever olika starkt ljus och olika färg beroende
på vilken våglängd de strålande ljuset är. Dämpningen av
solljuset i atmosfären uppstår vid absorption och spridning och
kan indelas i två olika effekter som antingen tar bort ljus eller
lägger till ljus i observationsriktningen. Absorptionen i
atmosfären kan försummas (förutom vid ozon-lagret) och
därav kan den vara enbart ett spridnings medium. Spridning av
solljus i atmosfären uppstår när ljuset träffar luftmolekyler
eller större partiklar som finns i gaser.
Ljusspridning på grund av molekyler i luften kallas
Rayleigh ljusspridning som sprider ljuset kraftigt vid kortare
våglängder. Himlen blir blå på dagen då de blåa ljuset studsar
överallt och till slut når ögonen från alla håll medan. På
kvällen blir himlen gul och rödaktig för att blå och gröna
våglängder studsar iväg innan dom når ögat på grund av att
ljuset färdas långt genom atmosfären.
För de större partiklar sprids ljuset med Mie ljusspridning
som sprider alla våglängder av ljus lika mycket. När mycket
partiklar finns i atmosfären får solen en solgård. Med denna
egenskap kan man göra många olika spännande effekter som
regnbåge och simulera ljusspridning för små is partiklar i
luften.
4. Teori
Henyey-Greenstein funktionen är en välkänd fas-funktion
som kan modifieras för ett rimligt fysikaliskt uttryck för
karaktären av ljusspridningens riktning. Denna funktion
beskriver hur mycket ljus som sprids mot åskådaren beroende
på vinkeln mellan den och ljusets riktning samt en konstant g
som påverkar spridningen symmetri. Det finns många olika
varianter av fas funktioner, Nishita's[1] modifikation av denna
fas-funktion är:
2
F  , g  =
2
3 1− g  1cos 
∗
∗
2 2 g 2  1 g 2−2gcos 3 /2
(1)
Om konstanten g sätts till noll kan Rayleigh ljusspridning
approximeras med denna funktion vilket betyder att positiva
och negativa vinklar ger samma svar i ekvation 1. Positiva
värden på g sprider ljuset framåt medan negativa sprider ljuset
bakåt och För Mie ljusspridning används värden mellan -0.75
och -0.99.
Konceptet optisk djup används i samband med atmosfärisk
ljusspridning. De optiska djupet för en given ljusväg kan
beräknas som en integral för spridnings koefficienten över alla
underelement ds på den givna ljusvägen gånger densitets
förändringen av atmosfären:
S
t S ,  = ∫  s s ds =
0
4 K
4

S
∫  s ds
(2)
0
−h
 s=exp 

H0
(3)
Integral delen i ekvation 2 beräknar de optiska djupet för
avståndet S. Spridnings koefficienten utvecklas i förändring av
ljusets väg i förhållande till våglängden. Densitets beräkningen
beskrivs med ekvation 3 där h är höjden av punkten där ljuset
träffar en partikel och H0 är höjden där atmosfärens medel
densitet ligger. Konstanten λ beskriver våglängden av ljuset
och K är spridnings konstanten som är olika beroende på om
de är Rayleigh eller Mie ljusspridning.
Eftersom dessa ekvationer ska appliceras i datorgrafik kan
åskådaren vara kameran och synfältet vara en stråle. Om en
stråle börjar i kamerans position Pv och pekar mot planeten.
Det finns två fall då strålen går bara genom atmosfären eller att
strålen träffar planetens yta.
I första fallet där strålen går bara genom atmosfären.
Punkten P kan vara en punkt i atmosfären där ljuset sprids
från partikeln och punkter Pa och Pb kan vara strålens närmsta
respektive längsta skärningspunkt. Punkten Pc sätts till
solstrålens skärningspunkt på atmosfären mot punkten P.
Intensiteten av ljuset som har spridits i punkten P mot
kamerans position måste beräknas. Det görs med intensiteten
som anländer från solen till P genom att sätta integrations
intervallet till PcP i ekvation 2 och multiplicera det med
intensiteten från Rayleigh ljusspridningen. Avståndet till solen
från atmosfären kan ses som en parallell balk därav kan
spridnings vinkeln hos varje punkt längs med PaPb vara
konstant. Detta medför att intensiteten som når kameran på Pv
kan beräknas med att integrera de ljuset som spridits på grund
av luft molekyler på PaPb med:
I v = I s 
KF r 

4
Pb
∫  e−t  PPc , −t PPa ,  ds
(4)
Pa
Is(λ) är intensiteten på solen. Ekvation 4 kallas också för inspridnings ekvationen samt ekvation 3 kallas för ut-spridnings
ekvationen.
I det andra fallet skär strålen, från kameran, planeten i
punkten Pb. Intensiteten som har spridits på grund av
molekylerna i luften beräknas på likadan sätt som i första
fallet. När punkten P sammanfaller med punkten Pb beräknas
ljuset med att lägga till de reflekterade ljuset från planetens yta
till ljusets spridning på strålen PaPb. Alltså intensiteten som
når kameran blir:
'
I v = I v I e  e
−t  PaPb , 
(5)
I ekvation 5 är Iv de ljuset som spridits av ekvation 4 och Ie
är de reflekterade ljuset från planeten alltså de omgivande
ljuset av planeten och de direkta solljuset tillsammans.
5. Implementation
Om ekvationerna från ovan skulle implementeras rakt av så
skulle det krävas väldigt mycket beräkningar. Om ekvation 5
ska lösas så kan man komma upp till 3000 beräkningar per
vertex och detta är ganska tungt om beräkningar ska ske på
CPU. En två dimensionell tabell kan snabba på beräkningen
genom att ersätta en av ut-spridnings integralerna med höjd
och vinkel till solen i förhållande till en godtycklig punkt i
atmosfären. Detta är möjligt med att solen befinner så pass
långt bort att strålarna kan antas vara parallella. Med denna
tabell kunde Nishita skära ner beräkningar till hälften. O'Neil
2004 introducerade en förbättrad version av tabellen med att
eliminera den andra ut-spridnings beräkningen. Med denna nya
tabell var det möjligt att förminska de 3000 beräkningar till 60
per vertex. Denna förbättrade metod gjorde det möjligt att köra
atmosfärisk spridning i interaktiva hastigheter med 50-100 fps.
Denna metod att lösa ekvationerna skulle kunna
implementeras i shaders för att uppnå mer fps. I O'Neil 2005
gjordes det matematiska undersökningar av dessa ekvationer
för att kunna lösa ekvationer med en annorlunda
tillvägagångssätt.
Genom
att
grafiskt
undersöka
uppslagstabellens resultat med partikel höjden på x-axeln och
de optiska djupet på y-axeln såg grafen ut att minska
exponentiellt då höjden gick från noll till ett men skalan på
varje linje varierade avsevärt. Denna graf normaliserades och
varje kurva fick likadana resultat nämligen exp(-4x). Denna
resultat är logisk då höjden på atmosfärens medel densitet
ligger på 0.25 i O'Neils implementering. Det fanns variationer
på kurvorna som beror på att vinkeln från kamera strålen till
partikeln i atmosfären varierar över 90 grader men dessa
variationer är försumbara då strålen passerar genom planeten
vid denna vinkel. Alltså är resultatet exp(-4x) ett bra resultat
för att eliminera höjd beräkningen i uppslagstabellen.
Efter att höjdens beräkning är ersatt måste man titta på
vinkeln beräkning i tabellen. Delen som inte behandlas med
exp(-4x) är skalan som används för att normalisera höjd
beräkningen alltså värdet som de optiska djupet har när x=0.
En Ny graf kan skapas med genom att undersöka vinkeln på
x-axeln och skalan för varje vinkel på y-axeln. Det som visade
sig vara en växande kurva som liknade en exponentiell kurva.
Genom att skala upp grafens startvärde till ett och logaritmera
kurvan kunde en annan växande kurva uppnås. Denna kurva
krävde dock en mjukvara för att uppskatta och resultatet blev
en polynomisk kurva som kan användas istället för
uppslagstabellen. Detta medför också till att om höjden på
atmosfärens medeldensitet ändras från att vara 0.25 till ett
annat värde så måste en ny kurva uppskattas. Så länge som
atmosfärens tjocklek är 2.5% av planetens radie och skalan på
höjden är 25% av atmosfärens tjocklek kan planeten vara hur
stor eller liten som helst.
Med dessa approximationer kan man nu implementera
atmosfärisk ljusspridning i fragment och vertex shaders.
Programspråket C++ tillsammans med OpenGL används för
att skapa en körbar demo tillsammans med GLSL shaders. Två
stycken sfärer skapas med gluSphere() som representerar
atmosfären och planeten. Shaders skapas för båda sfären när
man är inne i atmosfären med kameran och när man befinner
sig i rymden. De mesta av beräkningar för intensiteten mot
kameran efter spridningen utförs i vertex shadern förutom fas
funktionen då artefakter uppstår när fas funktionen beräknas
per vertex. Fas funktionens beräkning hanteras av fragment
shadern med de beräknade färgen från vertex shadern.
HDR rendering används för att förbättra bilden då den kan
vara för mörk eller för ljus utan det. HDR rendering används
ofta tillsammans med en pixel-buffer som renderas på en textur
för att kunna jämna ut färgen till en given skala. I denna
implementation används dock en simpel exponerings ekvation
i slutet av varje fragment shader som beräknar den slutgiltiga
färgen. Exponerings konstanten fungerar som en bländare gör i
kameror eller i pupillen.
En generell implementering görs först med GLFW som
hanterar OpenGL kontext, samt att biblioteket GLEW används
för att hantera GLSL anknytning till OpenGL. Sedan flyttas
implementeringen till wxWidgets för att kunna skapa ett
användargränssnitt och kunna kontrollera vissa parametrar i
realtid.
För att förbättra utseendet på planeten används Perlin Noise
implementerat i shaders[5] för att lägga till terräng och moln.
Molnen implementeras med hjälp av metoden som
introduceras av[6] där fraktal summor av noise används. En
exponentiell funktion används för att kontrollera skärpa och
fluffighet av molnen samt att en extra turbulens fraktal summa
implementeras för att skapa större moln och icke moln
områden. Denna shader appliceras på en sfär som har en radie
större än planetens men mindre än atmosfärens radie. Ingen
ljusspridning beräknas på molnen från rymden däremot vanlig
diffus belysning och skuggning beräknas. När kameran
befinner sig i atmosfären ökas moln fraktal frekvensen för att
skapa en mer realistisk visuell karaktär.
Terrängen är också implementerad med fraktal summor av
noise i vertex shadern för att ändra på höjden av planetens yta.
Ingen färgläggning eller texturering av marken utförs förutom
den som ljusspridningen tillför med.
6. Resultat
Programmeringen och demo körningen utfördes på en
bärbar dator i linux operativ system med nvidia 330GT GPU,
2.13 Ghz intel core i3 CPU och 4 Gb ram.
Implementation i GLFW utan användargränssnitt:
122fps, med terräng, med moln
Figur 1. 99.5fps, kamera i rymden
305fps, utan terräng, utan moln
Figur 2. 52.5fps, kamera i atmosfären
Implementation I wxWidgets:
100fps, utan terräng, med moln
7. Diskussion
99.5fps, kamera i rymden
Resultatet är ganska visuellt attraktiv och körs i rimlig fps,
tillräckligt för att det inte ska uppkomma fördröjningar medan
man interagerar med programmet. Genom att användaren kan
ändra på de olika parametrar kan programmet upplevas som en
spännande och underhållande program. Man kan ändra
våglängderna så att planetens atmosfär ser ut som jorden både
på dagen och vid solnedgång men även så att planeten ser ut
som någon utomjordisk planet med olika färger på himlen.
Texturer kan användas på planeten för att se hur
spridningen av ljus påverkar till exempel texturen på jorden.
Prodeduella sfärer skulle kunna användas tillsammans med
LOD för att ge bättre upplösning på terrängen när kameran
närmar sig planetens yta. Det finns många mer spännande
saker man kan göra med terrängen bl. a. lägga till vatten med
reflektioner.
Molnen går att förbättra avsevärt med till exempel
volymetriska moln eller använda ljusspridnings teorin på
molnen som är redan implementerade för att åstadkomma mer
realistiska färger vid solnedgång. Här kan man öka på antalet
termer i fraktal summan för att åstadkomma bättre upplösning
på molnen. Ett försök gjordes på att göra virvlar[9] av molnens
fraktal summan men ett visuellt tilltalande resultat uppnåddes
ej.
Man kan också tillägga dis och annat väder för att förbättra
atmosfärens känsla. Utöka skalningsfunktionen så att den inte
bara beror på en viss höjd. Dela upp Rayleigh och Mie
ljusspridning så att de har olika djup(hänger ihop med att göra
dis). Denna implementation har gjorts med singel ljusspridning
då förloras ljuset som har spridits bort från kamerans stråle
därav kan man utöka den med multipel ljusspridning.
Regnbågar[7] och åskväder[8] är också möjligt att tillägga. Vi
upplever objekt som suddiga när dem ligger långt bort i
atmosfären denna effekt skulle kunna läggas till i HDR
renderingen.
Ett försök gjordes också på att göra planetringar med point
sprites tillsammans med shaders men det visade sig vara
svårare än trott. Denna del är dock kvar i de slutgiltiga
programmet då det ändå skapar en bra känsla för en planet i
rymden, från längre håll.
8. Referenser
[1] Nishita T., T. Sirai, K. Tadamura, and E. Nakamae. 1993.
"Display of the Earth Taking into Account Atmospheric
Scattering.",
SIGGRAPH
93,
pp.
175–182.
http://nis-lab.is.s.u-tokyo.ac.jp/~nis/cdrom/sig93_nis.pdf
[2] Hoffman, N. and A. J. Preetham. 2002. "Rendering
Outdoor Scattering in Real Time." ATI Corporation.
http://www.ati.com/developer/dx9/ATI-LightScattering.pdf
[3] O'Neil, Sean. 2004. "Real-Time Atmospheric Scattering."
GameDev.net.
http://www.gamedev.net/columns/hardcore/atmscattering/
[4] O'Neil, Sean. 2005. GPU gems 2, ”Chapter 16. Accurate
Atmospheric
Scattering”.
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter1
6.html
[5] Gustavson, Stefan.
http://staffwww.itn.liu.se/~stegu/simplexnoise/
[6] Sazzad K., Mahmud H., and Emdad A. 2005.”Generating
and Rendering Procedural Clouds in Real Time on
Programmable 3D Graphics Hardware”. In Proceedings of
9th IEEE International Multi Topic Conference.
http://paris.cs.wayne.edu/~ay2703/research/publications/getPDF2
INMIC2005.pdf
[7] Brewer Clint. 2004. "Rainbows and Fogbows: Adding
Natural Phenomena." NVIDIA Corporation. SDK white paper.
http://download.nvidia.com/developer/SDK/Individual_Samples/
DEMOS/Direct3D9/src/HLSL_RainbowFogbow/docs/RainbowFo
gbow.pdf
[8] Dobashi Y., T. Yamamoto, and T. Nishita. 2001. "Efficient
Rendering of Lightning Taking into Account Scattering Effects
due to Clouds and Atmospheric Particles." http://nis-lab.is.s.utokyo.ac.jp/~nis/cdrom/pg/pg01_lightning.pdf
[9] Texturing and Modeling: A Procedural Approach (third
edition) Ebert, Musgrave, Peachey, Perlin, Worley Morgan
Kaufmann Publishers, 2003 ISBN 1-55860-848-6