Richtlijn voor het maken van 3D modellen voor Ultimate Stunts
Inleiding
Ultimate Stunts is een 3D-spel, en het gebruikt 3D-modellen om de baan uit op
te bouwen en voor de auto's. Deze 3D-modellen kunnen in externe 3D
modelleer-software gemaakt worden, geïmporteerd worden met het stunts3dedit
programma, getransformeerd en gekleurd worden, en opgeslagen worden in
Ultimate Stunts' interne .glb formaat. Dit document beschrijft niet hoe u dit
kunt doen. In plaats daarvan beschrijft het wat voor soort 3D-modellen passen
bij de doelstellingen van Ultimate Stunts.
Doelstellingen voor goede 3D-modellen
Een 3D-model is goed als het aan twee eisen voldoet: het moet er goed uit zien,
en het moet snel weergegeven kunnen worden. Deze twee eisen hebben natuurlijk
vaak een tegengesteld effect op het 3D-model: een model dat er goed uit ziet
wordt vaak traag weergegeven, en een snel weergegeven model ziet er vaak slecht
uit. In dit document worden enkele trucs vermeld om 3D-modellen zowel snel als
mooi te laten zijn.
Snelheids-eisen, en doel-platforms
Het juiste evenwicht tussen snelheid en detail hangt natuurlijk af van de
hardware. Ultimate Stunts gebruikt OpenGL, en dat kan vele malen sneller zijn
als het hardware-versnelling gebruikt. Het Ultimate Stunts project probeert
erg flexibel te zijn in de hardware-eisen: mensen met slechte hardware moeten
in staat zijn om een acceptabele frame rate te krijgen (met slechte graphics),
en mensen met goede hardware moeten hoge kwaliteit graphics kunnen krijgen.
De gebruiker kan verschillende grafische instellingen wijzigen in Ultimate
Stunts, zoals de texture-Level-Of-Detail, aan/uitschakelen van blenden van
doorschijnende oppervlakken, en zelfs aan/uitschakelen van de Z-buffer.
Level Of Detail (LOD)
Voor de 3D-geometrie ontwerper is het belangrijk om te weten dat Ultimate
Stunts verschillende Levels Of Detail (LOD) gebruikt in verschillende
situaties. De 3D-geometrie van elke LOD moet gedefinieerd worden in het
.glb-bestand (natuurlijk kunt u een enkel model gebruiken in elke LOD,
maar dat is niet de optimale situatie). Op dit moment zijn er zes LODs:
1 (meeste detail) tot 4 (minste detail), c (voor botsings-detectie) en s (voor
rij-oppervlaktes).
Polygon count
Zelfs op goede hardware kan het aantal polygonen in een model het te traag maken.
Elke polygon heeft een aantal vertices, en voor elke vertex moet er een
aantal transformaties en tests gedaan worden om het te projecteren op
het scherm-oppervlak. In feite is de vertex count belangrijker dan de
polygon count; er kan een verschil zijn als vertices gedeeld worden tussen
polygonen.
Een model met minder polygonen is altijd minder gedetailleerd dan een model met
meer polygonen. Vooral gekromde oppervlaktes kunnen er slecht uit zien als ze
zijn opgebouwd uit te weinig polygonen. Er zijn een aantal trucs die toegepast
kunnen worden om te verhullen dat een model maar een paar polygonen heeft:
-
Gekromde oppervlaktes kunne gemaakt worden met gladde schaduwen, of
"Gouraud shading". Normaal gesproken kan het oog alleen de grens tussen
de vlakken zien doordat de vlakken verschillende kleur-intensiteiten
hebben, wat veroorzaakt wordt door de verschillende oriëntaties van de
vlakken ten opzichte van de lichtbron. Met "flat shading" heeft elke
polygon een uniforme kleur, waardoor de gebruiker een intensiteitsverschil
kan zien op de grens tussen polygonen. Met "smooth shading" wordt de
schaduw-intensiteit niet berekend per vlak, maar per vertex. Binnen
een polygon wordt de intensiteit geïnterpoleerd tussen vertices.
Als nu twee polygonen van een gekromd oppervlak die naast elkaar liggen
vertices gemeenschappelijk hebben, dan wordt hun kleurintensiteit op
de grens ook het zelfde. Het resultaat is dat de gebruiker de grens tussen
de polygonen niet kan zien.
Om dit te laten werken moet er een "normaalvector" gedefinieerd worden voor
elke vertex. De normaalvector definieert de richting van het oppervlak
op de positie van de vertex, die gebruikt wordt om de schaduw-intensiteit
te berekenen. Veel 3D-modelleerprogramma's kunnen deze normaalvectoren
automatisch genereren, als "smooth shading" wordt aangeschakeld voor een
groep polygonen.
Het effect van smooth shading kan echt spectaculair zijn. Een cylinder kan
gemaakt worden uit 10 polygonen, terwijl het aantal polygonen alleen
zichtbaar is aan de platte kanten van de cylinder. Meestal is het een goed
idee om meer polygonen te gebruiken voor grote en belangrijke objecten, zoals
loopings en wielen, en minder polygonen voor kleine onbelangrijke objecten,
zoals in scenery. U zou het ook verschillend kunnen maken in verschillende
LODs.
-
Veel details kunnen gedaan worden met textures in plaats van polygonen.
Bijvoorbeeld, een deur van een gebouw kan een enkele polygon zijn met een
deur-texture erop. Een hek kan opgebouwd worden uit een groot aantal
cylinders, elk bestaande uit een groot aantal polygonen, maar het kan ook
gemaakt worden met een enkele polygon met een hek-texture erop.
Textures worden op polygonen geplakt door "texture coördinaten" te
definiëren voor elke vertex. Voor elke pixel in de polygon worden de
texture-coördinaten geïnterpoleerd, en de kleur die overeen komt met
die coördinaten wordt gevonden in de texture-afbeelding. Deze operaties
hangen niet zo sterk af van de texture-afmetingen, dus ze kunnen veel
sneller gedaan worden dan 3D vertex-transformaties voor een net zo
gedetailleerd model dat uit polygonen is opgebouwd in plaats van textures.
Dus, als u zowel snelheid als kwaliteit wilt: gebruik textures.
Textures
Textures kunnen dus gebruikt worden om gedetailleerde modellen te maken met
een klein aantal polygonen. Het nadeel is het extra aantal per-pixel berekeningen
dat nodig is om de kleur van de pixel te bepalen. Op hardware-versnelde systemen
worden deze operaties gedaan door de videokaart-processor in plaats van de
centrale processor. De videokaart-processor is geoptimaliseerd om de zelfde
taak vele malen tegelijkertijd uit te voeren, en daardoor kan het de per-pixel
berekeningen veel sneller uitvoeren dan de centrale processor. Het probleem is
dat de video-processor toegang moet hebben tot de texture-data. Met moderne
AGP/PCIe-poorten is de communicatie tussen videokaart en CPU / werkgeheugen erg snel,
maar alle textures op een 25 fps snelheid versturen zou nog steeds te veel
bandbreedte nodig hebben. Dat is waarom textures in het geheugen van de videokaart
geplaatst moeten worden, en dat is waarom het belangrijk is om genoeg
videokaart-geheugen te hebben.
Voor de 3D-modeller is het belangrijk om zich te realiseren dat de prestaties
zullen dalen als niet alle textures in het videogeheugen passen. Het
geheugengebruik kan natuurlijk beperkt worden door kleinere textures te
gebruiken (zelfs de gebruiker kan dit doen in Ultimate Stunts' instellingen:
Ultimate Stunts schaalt de textures voordat het ze aan OpenGL doorgeeft).
Dit herschalen is zo eenvoudig dat het niet echt belangrijk is voor de modeller.
Een andere manier om texture-geheugen te verminderen is belangrijk
om te weten: het delen van textures tussen modellen. Een texture die door veel
modellen gebruikt wordt, wordt maar één keer geladen, dus het gebruikt het
geheugen maar één keer. Dus in plaats van op elke tile een andere gras-texture
te gebruiken, is het beter om overal de zelfde gras-texture te gebruiken.
Textures voor Ultimate Stunts kunnen ook een alpha-kanaal hebben, dat gebruikt
kan worden voor doorzichtigheids-effecten. Bijvoorbeeld, de bladeren van een
boom kunnen getekend worden in een texture met een alpha-kanaal, waarbij het deel
van de texture buiten de bladeren doorzichtig is. Een boom kan dan gemaakt worden
met maar een paar polygonen, terwijl het nog steeds erg gedetailleerd kan zijn.
Een nadeel van textures met grote doorzichtige gebieden is dat er voor veel pixels
een hoop berekeningen gedaan worden om tot de conclusie te komen dat er niets
getekend hoeft te worden. Voor grote objecten (die er groot uitzien op het scherm,
zodat ze veel pixels bevatten) zou het beter kunnen zijn om een meer gedetailleerd
polygon-model te maken om het aantal onnodige piexl-operaties te verminderen.
Een ander nadeel is dat voor mensen die de doorzichtigheids-blending uitschakelen,
de doorzichtige gebieden er ondoorzichtig uit zien. Voor deze gebruikers zou een
meer gedetailleerd polygon-model een betere oplossing kunnen zijn.
De z-buffer
In een correct gerenderd 3D-beeld bedekken objecten die voor andere objecten staan
deze andere objecten, zodat ze niet zichtbaar zijn. Er zijn een aantal manieren
om dit doel te bereiken. Één manier is om de objecten te sorteren en ze van achter
naar voren te tekenen. Zodra een object bovenop een ander object getekend wordt,
vervangt het de pixels, en het resultaat is correct. Een andere manier om het te
doen is door de diepte van elke getekende pixel te onthouden (de z-coördinaat) te
onthouden in een buffer, de z-buffer. Als een pixel getekend wordt, wordt de diepte
vergeleken met de bestaande pixel, en de nieuwe pixel wordt alleen getekend als deze
zich voor de oude bevindt. Deze methode is nauwkeuriger dan de andere, doordat het
per-pixel vergelijkt in plaats van per-object. In theorie zou het altijd het juiste
resultaat moeten geven, maar in werkelijkheid zijn er wat problemen.
Één van deze problemen is dat de z-buffer een beperkte nauwkeurigheid heeft.
Polygonen die vlak achter elkaar staan, zoals een raam bovenop een muur,
worden soms op een lelijke manier samengevoegd, doordat de z-buffer niet kan
bepalen welke van de twee dichter bij de camera staat.
Een ander probleem doet zich voor bij doorschijnende oppervlaktes.
Als deze oppervlaktes getekend worden voordat de objecten achter de
oppervlaktes getekend zijn, dan worden de objecten achter de oppervlaktes
niet getekend, omdat de z-buffer waarden ingesteld zijn op de diepte van
het doorschijnende oppervlak. Ultimate Stunts lost dit op door te proberen
om objecten zo veel mogelijk van achter naar voren te tekenen, maar binnen
een object verandert het de teken-volgorde niet. De tekenvolgorde zou op
zo'n manier ingesteld moeten worden dat het een correct resultaat geeft vanuit
de meeste standpunten. De tekenvolgorde is ook belangrijk als er geen
doorschijnende oppervlaktes zijn in een object, omdat de z-buffer om
performance-redenen uitgeschakeld kan worden. In zulke situaties is de
tekenvolgorde het enige dat de dingen nog een beetje goed houdt.
Ontwerpbeslissingen
Dus, ter conclusie, de volgende beslissingen moeten gemaakt worden:
-
Het aantal vlakken voor ronde vormen. U kunt dit variëren voor
verschillende LODs. In het algemeen is een klein aantal voldoende
als u gebruik maakt van smooth shading.
-
Details die in de textures zitten versus details die in de geometrie
zitten. Textures zijn meestal beter als de speler geen
diepte-verschil hoeft te zien.
-
Recycling van textures: gebruik textures die al vaker gebruikt zijn
in Ultimate Stunts, of gebruik textures die in de toekomst
hergebruikt kunnen worden.
Botsingsdetectie
Ik ben vergeten om over de botsingsdetectie te vertellen. Tot nu toe gebben we
het alleen gehad over de graphics, maar de geometrie van objecten is ook
van invloed op hun fysieke interactie via botsingen. Er zijn aparte LODs
("c" en "s") voor het botsingsmodel.
De botsingsmodellen voor tiles, auto-vormen en auto-wielen zijn op verschillende
manieren gedefinieerd. Tile-botsingsmodellen zijn een set polygonen, net zoals
het graphics-model, dus voor veel tiles kan het graphics-model ook gebruikt
worden voor botsingsdetectie.
Het enige bijzondere aan tiles is dat "oppervlakte"-polygonen in de "s" LOD
geplaatst moeten worden, en niet in de normale "c" LOD. Dit is omdat Ultimate
Stunts berijdbare oppervlaktes anders behandelt dan botsings-oppervlaktes.
Water-oppervlaktes moeten onderdeel zijn van zowel "s" als "c".
Het botsingsmodel van een auto is een "bounding volume", dat de vorm van
de auto benadert met een aantal vlakken. Elk vlak deelt de hele ruimte
op in twee delen, en zegt "de auto is aan deze kant van het vlak".
Met genoeg vlakken (met slim gekozen oriëntaties) blijft er maar een
klein volume over, en dit volume zou een benadering moeten zijn voor de
vorm van de auto.
De vlakken zijn gedefinieerd met polygonen in de "c" LOD. In de bestaande
auto's kunt u voorbeelden van botsingsmodellen zien, waarbij de
botsingsvlakken meestal doorschijnend blauw zijn.
De wielen hebben cylindrische botsingsmodellen. De cylinder wordt gedefinieerd
met twee polygonen op de posities van de "eindvlakken" van de cylinder.
(de symmetrie-as van een wiel is de x-as, dus de polygonen moeten loodrecht
op de x-as staan.) Ook hier kunt u voorbeelden vinden in bestaande auto's.
Een erg gedetailleerd botsingsmodel kan de botsingsdetectie erg tijdrovend
maken, en gelukkig is een gedetailleerd botsingsmodel niet zo hard nodig als
een gedetailleerd graphics-model. Sommige complexe vormen met veel polygonen
kunnen benaderd worden met een eenvoudiger botsingsmodel, en sommige
objecten hebben geen botsingsmodel nodig omdat auto's er nooit mee zullen
botsen. In sommige situaties is het zelfs ongewenst dat een object
botsingseffecten genereert, bijv. met struiken of bloemen.