The Procedural Arctic



Relevanta dokument
PROCEDUELL TERRÄNG. Proceduella metoder för bilder (TNM084) Jimmy Liikala Institutionen för teknik och naturvetenskap

Procedurell grottgenerator och eld i GLSL. Marcus Widegren

Procedurell Terräng med LOD i OpenGL 4

Försättsblad till skriftlig tentamen vid Linköpings Universitet

Procedurell renderingsmotor i Javascript och HTML5

Procedurella Grottor TNM084. Sammanfattning. Alexander Steen

Tentamen TNM061, 3D-grafik och animering för MT2. Tisdag 3/ kl 8-12 TP51, TP52, TP54, TP56, TP41, TP43. Inga hjälpmedel

Procedurell 3D-eld på grafikkortet

Grafiska pipelinen. Edvin Fischer

HAND TRACKING MED DJUPKAMERA

TNM022 Proceduella Bilder Rendering av proceduell päls i realtid

Tentamen TNM061, 3D-grafik och animering för MT2. Onsdag 20/ kl SP71. Inga hjälpmedel

Projekt i TNM084, Procedurella bilder

Grafiska pipelinens funktion

Procedurell stad. Projekt i kursen TNM022 Procedurella metoder för bilder. Tobias Heldring, tobhe

Spelutveckling 3d-grafik och modellering. Grunder för 3d-grafik Blender Animering

Kort introduktion till POV-Ray, del 1

Inledning. Kapitel Bakgrund. 1.2 Syfte

Generering av L-system fraktaler med Processing.js

Omtentamen. TNM077 3D-datorgrafik och animering kl 8-12 Inga hjälpmedel. (samt även TNM008 3D-datorgrafik och VR)

Shaders. Renderingssystem. Renderingssystem. Renderingssystem. Hårdvara för 3D-rendering. Hårdvara för 3D-rendering

Grafik raytracing. Mattias Axblom.

Robin Wahlstedt Datavetenskap / Spel Vetenskapsmetodik rwt07001@student.mdh.se. Datorgrafik i spel

Designing a Shading System. David Larsson

Strömsholmen. Mårten Svensson, Peter Zhu, Andreas Wetteborn,

Spelutveckling - Scenegrafer. Scenegrafer Optimeringar Culling

Fotorealistiska bilder 1 PV360 kap 1 7: Grunder samt material och dekaler i Photoview 360

Omtentamen TNM077, 3D datorgrafik och animering (samt även TNM008, 3D datorgrafik och VR)

Introduktion till Terragen 3 TNM084 Lab4 2013

TAIU07 Matematiska beräkningar med Matlab

Datorgrafik Ray tracing. Mattias Ekström, Västerås,

Kv. Ogräset. Martin Stenmarck,

Gel esimulering 22 mars 2008

Teknik för avancerade datorspel!

Shaders. Gustav Taxén

TUTORIAL: SAMLING & KONSOLL

Grunderna i C++ T A. Skapad av Matz Johansson BergströmLIMY

RoomDesigner Manual... 1

TANA17 Matematiska beräkningar med Matlab

Fotorealism, animering, SW resurser

Programmering. Scratch - grundövningar

Tor Sterner-Johansson Thomas Johansson Daniel Henriksson

Precis som var fallet med förra artikeln, Geogebra för de yngre i Nämnaren

Kort introduktion till POV-Ray, del 5

MATEMATIK GU. LLMA60 MATEMATIK FÖR LÄRARE, GYMNASIET Analys, ht Block 5, översikt

Rendera med mental ray

Realtidsalgoritmer för ljusets spridning och absorption mot partiklar i luften P E T E R L Ö N N Q U I S T

Laboration 3 HI1024, Programmering, grundkurs, 8.0 hp

Tentamen ID1004 Objektorienterad programmering October 29, 2013

C-UPPSATS. Revitalizing classic art using real-time game technology

Teknik för avancerade datorspel!

Giraffen & ballongen

Slutrapport Get it going contracts

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

varandra. Vi börjar med att behandla en linjes ekvation med hjälp av figur 7 och dess bildtext.

SF1626 Flervariabelanalys Lösningsförslag till tentamen DEL A. 1. En svängningsrörelse beskrivs av

Föreläsning 5-6 Innehåll

Föreläsningen ger en introduktion till differentialekvationer och behandlar stoff från delkapitel 18.1, 18.3 och 7.9 i Adams. 18.

Att använda pekare i. C-kod

BACHELOR THESIS. Efficient Optimizations Inside the Digital Advertise Production Pipeline. Michal Marcinkowski Mehmet Özdemir

Laboration - Shaders

I rastergrafikens barndom...gjorde man grafik genom att skriva i ett videominne. Operationer på buffert och pixlar. Idag... Varför grafikkort?

Avalanche Studios. OpenGL. Vår teknik. Våra spel. Lite inspiration... Stora, öppna spelvärldar. Sandbox-gameplay. Hög audiovisuell standard

PROGRAMMERINGSTEKNIK TIN212

Skinning. Ännu fler koordinatsystem att hålla reda på. SUPPLEMENT 2 till "So How Can We Make Them Scream?" 1. Olika metoder för kroppsanimation

Institutionen för matematik och datavetenskap Karlstads universitet. GeoGebra. ett digitalt verktyg för framtidens matematikundervisning

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Texturmappningsalgoritmer

LUNDS UNIVERSITET. Parallell exekvering av Float32 och INT32 operationer

Programmering B med Visual C

Innehållsförteckning

Laboration 3 HI1024, Programmering, grundkurs, 8.0 hp

PROCEDURELL GENERERING AV VOLYMETRISK TERRÄNG PÅ OLIKA BERÄKNINGSENHETER

Kort introduktion till POV-Ray, del 3

Tynker gratisapp på AppStore

Linjär Algebra, Föreläsning 2

bilder för användning

Byggnationen av Cheopspyramiden - ett visualiseringsprojekt. Mathias Bergqvist, Rikard Gehlin, Henrik Gunnarsson

För studenter i Flervariabelanalys Flervariabelanalys MA012B ATM-Matematik Mikael Forsberg

Vektorgeometri för gymnasister

UPG5 och UPG8 Miniprojekt 1: 2D datorgrafik

Projekt i Bildanalys: Automatisk detektion av lungemboli ur scintbilder

Simulering och rendering av gräs och vind i realtid

Visualisering med Rhino/Vray/Photoshop av modell som skapats i Revit. AADA15 Revit Workshop 2017 LTH Ludvig Hofsten

Just nu pågår flera satsningar för att förbättra svenska elevers måluppfyllelse

Word-guide Introduktion

2. Avgör om x och z är implicit definierade som funktion av y via följande ekvationssystem. x 3 + xy + y 2 + z 2 = 0 x + x 3 y + xy 3 + xz 3 = 0

f(x, y) = ln(x 2 + y 2 + 1). 3. Hitta maximala arean för en rektangel inskriven i en ellips på formen x 2 a 2 + y2

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Final i Wallenbergs Fysikpris

TNM011 Grafisk teknik Laboration 3 - Färg

A comparison study between OpenGL 4.3, OpenGL ES 3.0 and WebGL 1.0 With focus on rendering pipeline and texture handling

Projekt Rapport. RaidPlanner. Jeanette Karlsson UD10

VRay för SketchUp Camilla Ravenna / André Ravenna Alto Punto 2014 Alto Punto Askims Stationsväg Askim

Karta över Jorden - viktigt exempel. Sfär i (x, y, z) koordinater Funktionen som beskriver detta ser ut till att vara

Procedurella metoder för bilder

Information Coding / Computer Graphics, ISY, LiTH. Compute shaders!! Framtiden för GPU computing eller sen efterapning av Direct Compute?

Jag tror att alla lärare introducerar bråk

GeoGebra i matematikundervisningen - Inspirationsdagar för gymnasielärare. Karlstads universitet april

Transkript:

The Procedural Arctic Realtidsrendering och generering av en animerad havsyta och himmel, samt en isbergsformation med hjälp av GPU:n och Simplex Noise.

Inledning Denna rapport utgör en del i ett projekt ur kursen TNM084 Procedurella metoder för bilder som hölls av Stefan Gustavson vid ITN. Projektet utfördes under slutet av höstterminen 2008 vid Linköpings Universitet, Campus Norrköping. Rapporten utgår från att läsaren har förkunskaper från kursen samt bred kunskap inom datorgrafik och programmering i allmänhet. Mål Mitt först generella mål var enbart att skapa en procedurell rendering av en havsyta i realtid med hjälp av att använda Stefan s noise-implementationer i en GLSL fragment shader. I början av projektet var jag inställd på att havsytan skulle utgöras av en höjdkarta med effekter såsom reflektioner, refraktioner samt bump mapping från en genererad normal map(utifrån höjdkartan). Det skulle även vara möjligt att interaktivt kunna variera mängden brus eller t.om. om tid fanns att ändra metoden för hur bruset genereras, t.ex. genom att även använda FFT utöver noisegenerering. Huvudmålet var i alla fall att vad jag en utförde så skulle jag inte använda någon form av statiska texturer eller modeller i programmet. Metodval & Implemenationsordning Implementering utfördes i C++ med hjälp av OpenGL [1] och GLSL [2]. Jag utgick ifrån Stefan exempelapplikation GLSL-noise där han renderar en sfär med en yta som består av rörligt brus från en fragment shader. Stefan kom tidigt med tipset att istället för att beräkna fram en normal map så skulle jag använda en nyligen implementerad version av simplex noise med analytiska gradienter som han implementerat i programmeringsspråket C. Citerat från Stefan: Att beräkna gradienten analytiskt är i runda tal tre gånger så snabbt som att göra finita differenser i två riktningar.. Detta gjorde att jag även valde att försöka använda mig av denna implementation som Stefan producerat. Med dessa hjälpmedel valde jag att utföra implementationen enligt ordningen nedan(i stort sätt): Utforma en platt yta med en yta av rörligt brus liknande vattnets rörelse. Utforma en klass för en flyttbar kamera. Skapa en omgivning med animerade himmel av simplex noise. Producera reflektioner på ytan. Genera en terräng med hjälp av simplex noise. Producera refraktioner i ytan. Applicera Fresnels effekter. Implementera bump mapping med hjälp av analytiska gradienter av simplex noise. Implementera animerat vatten i tre dimensioner(höjdkarta) Använd FFTW biblioteket(http://www.fftw.org/) för att generera havsytan med denna metod. OBS! De två sista punkterna blev aldrig utförda, se diskussion för mer om detta. 1

Teori & Implementation Vattenytan Ytan implementerades som en enda stor texturerad fyrkant med hjälp av GL_QUADS från OpenGL. Sedan skapades en fragment shader(ocean.frag) och en vertex shader(ocean.vert) för att färglägga ytan med användning av Stefan s 3D simplex noise implementation och användning av texturkoordinaterna (s,t) samt värdet från funktionen glfwgettime() (den interna klockan) som variabler för bruset. För att få bruset att se ut som animerat osymmetriskt vatten adderar jag olika oktaver med olika vikter och amplituder enligt ekvationen nedan(generarer alltså Fractal Noise ). N n i i i = 0.5 snoise( tid + a texcoord. x,0.5* a texcoord. y, tid ) i= 0 N = totala bruset, n = antal oktaver, a = baspotens för amplituden Att tiden appliceras på x-koordinaten gör att den rör sig i den riktningen och sedan applicerar jag e skalning av y-koordinaten för att få utsträckta mönster, liknande vågor. En skärmdump av ytan med endast en blåaktig färg multiplicerad med bruset (n = a = 4) visas nedan. 2

Himmel För att skapa en någorlunda tolkning av en himmel med rörliga dimmiga moln så använda jag mig först enkelt av att använda Stefans egna implementation av texturerad sfär och skapa ett molnliknande mönster genom en fragment shader(sky.frag), en vertex shader(sky.vert) och samma metod som beskrivet i delen om vattenytan. Enda skillnaden är att man måste ta hänsyn till sfärens struktur och utforma parametrarna så molnens rörelse cirkulerar runt sfären. För att få så att texturering görs på insidan av sfären använder man funktionen glcullface. Enda nackdelen med de flesta texturerade sfärer är att det bildas fula sömmar när man applicerar en tvådimensionell textur om man inte har åtgärdat detta i valet av texturkoordinater på ytan. Efter en del webbsökning så hittade jag istället en implementation av en så kallad SkyDome [1], eller helt enkelt halvsfär som används för att representera en himmel. Kodad med hjälp av en vertex array och fin åtgärd av problemet med sömmarna gjorde att jag valde att använda mig av hans implementering. Ett flertal statiska texturer som representerar en omgivning brukar ofta innehålla en sol. Utifrån solens position kan man positionera en ljuskälla och skapa en mer realistisk miljö. Jag fastnade då för att implementera en procedurell representation av solen på himlen. Genom att färglägga himlen med en gulaktig färg en specifik radie runt nuvarande position i object space så kunde jag få fram en cirkulär form som följde kamerans rörelser längs himlen. För att få solen att stanna på en specifik position på himlen och kunna röra kameran utan att den rör sig måste man skicka in solens position till vertex shadern, transformera position till object space genom att multiplicera med gl_modelviewmatrix och sedan dra ifrån den nuvarande positionen med solens position för att få fram var den ska ritas ut i förhållande till kameran. Positionen måste också viktas genom att subtrahera kamerans Z-koordinat (eller den koordinat som representerar uppåt i världen). Koden för att få fram den vektorn: P=normalize(vec3((1.0-cameraPos.z)*sunPosObjSpace.xposx,(1.0-cameraPos.z)*sunPosObjSpace.y-pos.y, (1.0+0.5)*sunPosObjSpace.z-pos.z)); Detta är en lösning jag har testa fram för att en interaktivt flyttbar sol som ändå kan upplevas statisk på himlen. Den är inte buggfri men fungerar någorlunda bra. Himlen visas på en skärmdump nedan. 3

Terräng För att få en mer intressant scen med fler reflektioner än himlen och möjligheten att få någon användning med att implementera refraktioner i vattenytan är terräng som befinner sig både över och under vattennivån att föredra. För att framställa terrängen procedurellt valde jag att fortsätta använda mig av simplex noise, fast i kombination med F.Kenton Musgrave s funktion multifractal[2]. Genom att översätta Kenton s funktion till GLSL samt modifiera den något så att fler distinkta toppar uppenbarade sig, vilket är tänkt att representera större isbergformationer som sticker upp ur vattnet på olika ställen. Nedan presenterar jag stegen jag tog för att gå ifrån en höjdkarta till ett tredimensionellt objekt. Detta sker innan programmet körs: Ställ om vystorlek till att motsvara den storleken(b*h) som du vill ha på texturen. Rendera en GL_QUADS med vertex positionerna från -1 till 1 texturerad med fragment och vertex shadern där man räknar ut höjdkartan. Spara undan alla pixelvärden i ett fält med hjälp av OpenGL funktion glreadpixels(). Skapa ett fält av en egen struktur (som utformas t.ex. med struct) som innehåller tre variabler (x,y,z) (a.k.a vertex array) samt ett annat fält med en struktur som innehåller två variabler (s,t). Loopa igenom (B*H) gånger och spara undan i storleksordning två trianglar(6 punkter) per position samt den texturkoordinat som denna position avser. (Här används även en enkel Level of Detail metod för att hålla ner antalet trianglar genom att bara hoppa över ett visst antal texturkoordinater under loopningen). Lagra båda fälten i var sitt VBO(vertex buffer object) för att återanvändas i renderingen senare. Under programkörning(rendering) Bind en buffert (med hjälp av glenableclientstate och glbindbuffer) till alla texturkoordinater och sedan en till alla hörnpunkter och rita sedan utan alla hörnpunkter som GL_TRIANGLE_STRIPS med funktion gldrawarrays. De fyra sista av dessa punkter har jag lärt mig genom att följa en tutorial [3]. Enda skillnaden mot det jag utfört är att denna tutorial utgår från att man har en statisk höjdkarta som man läser in från en fil. För att sedan färglägga höjdfältet valde jag att använda ett ytterligare shaderpar (ice.frag, ice.vert). Snygg färgläggning får man enklast om man vet strukturen på objektet man färglägger (om man inte använder sig av belysning i scenen). Därför valde jag att samtidigt som jag läser innan alla pixelvärden för den renderade höjdkartan också spara undan scenen som en textur i en texturkanal med hjälp av funktionen glcopytexsubimage2d. Denna textur skickar jag sedan in i shaderparet som nämndes tidigare och då kan jag färglägga höjdfältet beroende på höjd eller lutning. Eftersom värdet från texturen är mellan 0 & 1 så kan man skapa en överföringsfunktion med GLSL funktionerna mix och smootstep där olika värden motsvarar olika färger. 4

För att förbättra utseendet ytterligare valde jag att även lägga in en mörkare toning på de ställen där lutningen är kraftig. För att undersöka detta bör man dock ha tillgång till ytans normaler (man behöver alltså en normal map). Eftersom en höjdkarta har skickats in som en textur kan man räkna ut dessa normaler. Uträkningarna kan ske på flera sätt. Nedan visas två av dem. Det sista är något snabbare(också det som jag implementerat) än det första som ni nog känner till sen tidigare. Första sättet(klassiska sättet): Ta fram den 9 värden som omgiver vår nuvarande position i texturen(lagra i matris M). Följande lösningar ger oss dx & dy vilket är vår normal. 1 0 1 1 2 1 N. x = M 2 0 2 N. y = M 0 0 0 1 0 1 1 2 1 Andra sättet(något snabbare): Utför finita differenser i två riktningar enligt följande figurer och formler. C B 0 A XY i proportion till Z : D s = S xy S z N. x = C. z A. z N. y = D. z B. z N. z = 2* s Nedan visas en skärmdump av endast den renderade terrängen. 5

Reflektion För att återge reflektioner från en perfekt yta [4] skulle en av de mest snyggast metoderna säkert vara raytracing. Men för att hålla de enkelt och i bra prestanda så valde jag en mycket enklare metod. Att helt enkelt rendera världen upp och ner, spara undan scenen som en textur och sedan skicka in den i shadern för vattenytan. Mer noggrann utförelse finns listad nedan. Precis som tidigare som måste man specificera vystorleken till storleken på texturen. Sedan vänder man på hela vyn med hjälp av OpenGL funktion glscalef(1.0, 1.0,-1.0); Parametrarna i funktionen motsvarar koordinataxlarna och i programmet har jag valt att z-axeln ska representera uppåt i världen och därför har den värdet -1.0. För bara terrängen som är ovanför vattenytan ska reflekteras måste man specificera ett glclipplane. Med denna funktion kan ett plan i scenen där allt över eller under planet inte ska tas med i renderingen. OBS! Om man använder sig av GLSL så måste man också specificera vilken position man är på för den inbyggda variabeln gl_clipvertex i en vertex shader: T.ex: gl_clipvertex = gl_modelviewmatrix * gl_vertex; Sedan är det bara att rendera sin värld och spara undan scenen som en textur. Skicka in texturen till shadern. Eftersom man ser scenen ur ett speciellt perspektiv måste man använda sig av projicerade texturkoordinater för att plocka fram rätt färgvärde. I GLSL skickar man då en variabel från vertex shadern enligt: projection = gl_modelviewprojectionmatrix * gl_vertex I fragment shadern måste man sedan normera projection.w komponenten genom att ta projection / projection.w och sedan flytta koordinaterna så de ligger mellan 0 och 1. Nedan visas en skärmdump av reflektionen i vattenytan från den renderade terrängen och himlen. Refraktion & Djup Refraktion benämns även vid ordet ljusbrytning, vilket beskriver fenomenet att ljuset ändrar riktning när det går från ett medium till ett annat. Detta fenomen gör så att ett sugrör ser brutet ut om det halva är i luften och halva i vatten. Eftersom ljuset bryts så ser man mindre och mindre av ett föremål om det t.ex. sjunker djupare ner i vattnet. Hade man använt sig av en cube map för att representera omgivningen hade man enkelt kunna utföra både korrekt reflektion och refraktion i GLSL shadern då det finns ett kapitel i GLSL bibeln [2] om 6

detta. Men så är inte fallet i denna applikation. Vad man kan göra är att använda sig av en du/dv map [7] vilket är en textur som innehåller derivatan av en normal map. Men min tanke med vattenytan är att jag inte vill flytta massa texturer mellan olika shaders för att få till vattenytan utan endast använda mig av ett shaderpar för vattenytan. Därför valde jag inte detta heller. För att uppnå en känsla av ljusbrytning kan man enligt [8] skala scenen med förhållandet mellan brytningsindexen, i detta fall 1.00029(luft)/1.33(vatten) i riktning med Z-axeln. Sedan behöver man bara spara undan det som är under vattenytan på samma sätt som med reflektion i en texturkanal samt spara undan en textur som endast innehåller en komponent som beskrivet djupet. Djupkomponenten kan återfås om man specificerar GL_DEPTH_COMPONENT i funktionen glcopytexsubimage2d. Genom att sedan slå upp texturkoordinaterna på samma sätt som med reflektionen i shadern så kan man skapa en yta där man ser mindre och mindre det som finns under vattenytan ju längre ifrån man kommer. Nedan visas en skärmdump av hur refraktionen och djupet påverkar vattenytan med hänsyn till den renderade terrängen och himlen. Fresnels ekvationer Utseendet på vattnet beror mycket på den vinkel du tittar ifrån. Detta fenomen studerades av Augustin- Jean Fresnel vilket resulterade i Fresnels ekvationer [8]. För att skapa den effekt måste man räkna fram ett värde som man använder för att avgöra hur mycket reflektion som ska visas i förhållande till refraktionen. Jag valde att använda mig av ett sätt som tas upp i GLSL bibeln [2]. 7

Fresnel bump mapping med analytiska gradienter av ytans brus. Som de flesta redan känner till så är bump mapping ett sätt att få ytan att se ojämn ut genom att förändra ytans normal och beräkna ytans egenskaper utifrån den nya normalen. I området realtids renderig kan detta utföras genom att räkna ut en normal map enligt något av de sätten som togs upp i avsnittet om terrängrenderingen. Men detta kräver att man har tillgång till närliggande komponenter och eftersom jag utgått från att skapa en yta med simplex noise i GLSL måste jag då spara undan hela ytan för att skicka in till en annan shader för att uppnå denna effekt. Precis som jag beskrev i början av rapporten när jag tog upp målen så kom Stefan Gustavson med förslaget att jag skulle använda hans simplex noise implementation med analytiska gradienter som han skrivit i C-kod. Det jag gjorde då var att översätta delen där han räknade ut de analytiska gradienterna till hans tidigare implementering av simplex noise i GLSL. Först använde jag en teknik som kallas Fresnels term [9] för att få reflektionen och refraktion att anpassa sig till en förändring av normalen. Sedan genom att bara ta de analytiska gradienterna från det bruset som tidigare hade implementerats och addera dem med ytans tidigare normal(med en viss skalning) så kan man urskilja bruset effekt på vattenytan. Distorsion av reflektionen och refraktionen. Det är sällan reflektioner och refraktioner är helt perfekta. För att skapa en syn av att vattnets rörelse förändrar reflektionerna och refraktionen kan man enligt [8] förändra texturkoordinaterna som man använder för att slå upp färgerna i texturerna för reflektion och refraktion. För att förändring ska följa vattnets rörelse adderar man normalen(skalad för ett bra utseende) och då uppstår det rörelser i både reflektionen och refraktionen enligt bilden nedan. Som synes uppstår ofta artefakter såsom att terrängen ser ut att ha hål i hörnen samt när texturen tar en punkt utanför någon del av reflektionen. 8

Diskussion & Vidareutveckling Jag är mycket nöjd med resultatet och känner att jag fått in många olika varianter av vad man kan Simplex Noise till samt beräkningskraften hos en GPU via GLSL. För att få mer realistiskt vatten var jag också inne på att utföra vertex displacement mapping vilket skulle ersatt bump mappingen. Detta utfördes dock aldrig men hänsyn till tid samt den optimering som antog skulle behöva utföras för att programmet skulle få tillfredställande prestanda. Även jämförelsen med att använda FFT till genereringen av havsytan hanns aldrig med på grund av tidsbrist. Mycket av realismen ligger i färgläggningen vilket också kunde lagts ner mer tid för att t.ex. få till en soluppgång med naturliga färger eller liknande. Måste passa på att tacka Stefan för att han tillhandhöll en implementation av simplex noise i GLSL samt gav mig tillgång till hans nyligen implementerade version med analytiska graidenter i C-kod. Det var lite pilligt att få det att fungera i GLSL då man får vara försiktig så inte antalet temporaries(variabler/värden som lagras under uträckningen) överstiger antalet som kompilatorn rekommenderar. Referenser [1]. Shreiner, Dave, o.a. OpenGL Programming Guide, Sixth Edition. [2]. Rost, J. Randi. OpenGL Shading Language, Second Edition. [3]. Flannery, Simon. SkyDome. [Online] http://www.codesampler.com/usersrc/usersrc_6.ht. [4]. Ebert, David S., o.a. Texturing & Modelling : A Procedural Approach. u.o. : Morgan Kaufmann Publishers, Third Edition. [5]. Swiftless Terrarin Tutorial. http://www.swiftless.com/tutorials/terrain/terraintuts.html. [Online] [6]. Watt, Alan. 3D Computer Graphics, Third Edition. 2000. [7]. Humphrey, Ben DigiBen. Realistic Water Using Bump Mapping and Refraction. http://www.gametutorials.com/articles/realisticwater.htm. [Online] [8]. Johanson, Claes. Real-time water rendering. http://graphics.cs.lth.se/theses/projects/projgrid/projgrid-lq.pdf. [Online] [9]. Wikipedia. Fresnel equations. http://en.wikipedia.org/wiki/fresnel_equations. [Online] [10]. Hu, Yaohua, o.a. Realistic, Real Time Rendering of Ocean Waves. http://www.visgraf.impa.br/data/refbib/ps_pdf/lvelho-cavw04/rtwave.pdf. [Online] 10