Ok, o mica detaliere.
Ce am facut in mare a fost sa scriu tot "engine"-ul din spate (spun "engine" pt. ca design-ul nu pot sa ma laud ca este excelent). Este destul de minimal dar are cateva lucruri care sa faca viata mai usoara (un CEntity, functii pt. pozitie/rotatie/scale, clasa pt. materiale s.a.m.d.).
Exemplu de cod:
Cod sursă:
MyTerrain = new CTerrain;
MyTerrain->Load("..\Data\terrain3.tga");
MyTerrain->Material.AddTexture(CTexture::LoadTex("..\Data\Grass3.tga"));
MyTerrain->Material.AddTexture(CTexture::LoadTex("..\Data\Stone2.tga"));
MyTerrain->Material.AddTexture(CTexture::LoadTex("..\Data\snow.tga"));
Nu e ceva miraculos, dar in fine.
Sectiunea de hacks:
Precizia terenuluiFolosesc niste calcule in plus prin shader astfel incat in loc de un byte (1 canal de culoare din textura) folosesc 2 bytes si alcatuiesc din el o inaltime. In felul asta, cam dispar "scaritele" de pe teren.
Care era problema:
Cum terenul este calculat in timp-real si heightmap-ul este tinut intr-un FBO, in momentul in care desenez peste el cu un brush (pt. deformare) eroarea de precizie din brush se propaga direct proportional cu puterea efectului aplicat. Ex: Daca fac un varf inalt dintr-un teren plat o sa am scarite de sus pana jos in loc sa fie lin.
PickingPt. picking m-am chinuit cateva ore sa fac ceva mai normal. Citire din depth, intersectie de vectori cu terenul, etc. Nu mi-a iesit. Asa ca m-am gandit cum l-as putea face repede. Am gasit o metoda destul de usoara, dar imprecisa de a face chestia asta:
Se deseneaza teenul cu un shader special intr-un buffer (sau chiar pe ecran). Shader-ul respectiv, in pseudocod, face "output = position", adica incodeaza in culoarea de pe ecran pozitia din spatiu a respectivului pixel. Precizia de 8 biti e cam nasoala dar in cazul asta a mers. Odata desenat terenul, se citeste pixelul de sub mouse si se interpreteaza. Problem solved.
ValuriMai intai cateva cuvinte despre apa. Apa in aplicatia mea foloseste in principiu 3 texturi: normalmap, "effectsmap" si cubemap-ul pt. reflexie.
Effects map-ul este alcatuit in felul urmator:
Rosu - Sunt desenate/calculate valurile (adaptare pt. GPU la codul de aici:
http://freespace.virgin.net/hugo.elias/graphics/x_water.htm )
Verde - Defineste unde este teren si unde este apa (folosita pt. coliziunea cu valurile)
Albastru - Un depth al terenului de sub apa, folosit doar pt. a adauga inca o textura la marginea apei (spuma, crengi, toxic waste or whatever one wishes) dar poate fi folosit si la altceva (refraction factor, etc.)
Codul de valuri din link functioneaza foarte bine la a reflecta valurile de marginile gridului. Asadar tot ce am facut ca sa reactioneze cu terenul a fost sa mai adaug conditia ca pixelul din "verde" sa fie "true".
Cum sunt un "real-time freak", am vrut ca totul sa fie in timp real/generat. Just because it's awesome

Asa a aparut calculul de teren/valurile/reflexia
De asemenea, pe cand eram tinerel si inca lucram la Ubisoft, am vazut un coleg care lucra la un sistem de apa pe CPU, si facea tot ce putea pt. a-l optimiza. Atunci i-am spus ca se poate si direct din textura, dar nu a fost prea incantat de idee. Asa ca am luat-o ca pe un challenge, dar nu am avut timp sa il incerc pana cand a aparut ocazia asta. Eu zic ca mi-a iesit binisor
