donderdag 4 juni 2009

Buoyancy en renders

In de vorige blogpost werd aangehaald hoe een 2D-3D koppeling met een 2D hard boundary voor problemen kan zorgen. De voorgestelde oplossing bestaat erin om de hard boundary weg te laten. De particles moeten wel nog dienen om het oppervlakte detail te verhogen, dus deze worden met een artificiële buoyancy kracht terug naar het oppervlak geduwd.

Om deze implementatie mogelijk te maken moeten we allereerste een koppeling tussen particles en heightfield uitwerken. Wanneer een particle in het heightfield gaat, moet zijn massa worden toegevoegd. Dit houdt in dat 1 particle een soort uitmiddeling van zijn massa moet doen over verschillende heightfieldkolommen. Zowel een kernel die over alle particles itereert als een kernel die over alle heightfieldkolommen itereert kan dit op parallelle hardware niet verwezenlijken: er moet in beide gevallen op verschillende plaatsen tegelijk geschreven worden.

Om dit probleem op te lossen nemen we om te beginnen de particlediameter even groot als de breedte/lengte van een heightfieldkolom. We maken dan de abstractie dat een particle slechts in een heightfieldkolom tegelijkertijd kan zitten. Een kernel over alle particles berekent dan hoe diep elke particle in de heightfield zit. Hierna kan een kernel over alle heightfieldkolommen berekenen wat de uitgemiddelde massatoevoeging van ieder particle voor deze specifieke kolom is (elke particle verdeeld zijn massa over meerdere kolommen, afhankelijk van de SPH smoothinglength).

Particles vallen nu door de heightfield en de heightfield genereert golven. Om ze realistisch te laten bewegen moet nog een drag force geïmplementeerd worden die de particles in het watervolume afremt en een buoyancy force, die we groter veronderstellen dan ze echt is, zodat de particles terug aan het oppervlak komen.

Enkele dagen van implementatie en debuggen (onder andere een quick fix aan de heightfield en enkele uren undefined behaviour opsporen met Valgrind) leverde de gewenste resultaten:


Ook het NVIDIA Marching Cubes algoritme werd geïntegreerd in ons systeem (alsook een betere camera control, instelbare parameters, een heleboel refactors om de leesbaarheid te verhogen en extra particle emitters (in de vorm van kubussen en bollen)). De scene kan nu dus ook met een oppervlak bekeken worden:


Een samengestelde screenshot levert dan volgende concept-art op:


Wanneer we de data van Marching Cubes exporteren naar een povray formaat, zijn we ook in staat om mooie renders te maken. Een ray trace van dezelfde scene ziet er als volgt uit:


Dit type renders kunnen we gebruiken om nog een highres filmpje te maken.

Ook geavanceerdere ray traces zijn mogelijk, zoals met photon mapping:


Omwille van ruis kunnen dit soort renders niet gebruikt worden voor een filmpje. Voordat we een filmpje kunnen opnemen moeten we nog enkele artifacts uit de scene halen (zoals rechts op de render het zwarte lijntje, dit is een artifact van het heightfield). Ook werkt Marching Cubes nog niet goed wanneer particles verwijderd worden. Aan het algoritme zelf moet niet veel meer gedaan worden, alleen komt het met de huidige maximale tijdstap nog niet helemaal tot een rustsituatie (de particles blijven wat schommelen op het water). Wanneer deze zaken opgelost zijn kunnen we onze versnelling vergelijken met een particle-only simulatie en alles evalueren.

Geen opmerkingen: