Redirecționarea înainte și versiunea amânată

Dacă sunteți un dezvoltator de jocuri 3D, probabil ați întâlnit termenii transmiterea în avans și amânarea redării în cercetarea motoarelor grafice moderne. Și, adesea, va trebui să alegeți una care să fie utilizată în joc. Dar ce sunt acestea, cum diferă ele și cine ar trebui să alegeți?

Rendering amânat pentru multe lumini (Imagine de la curtea lui Hannes Nevalainen)

Conducte grafice moderne

Pentru a începe, trebuie să înțelegem mai mult despre conductele grafice moderne sau programabile.

Înapoi în zi, am fost limitați în ceea ce a avut graficul grafic al plăcii video. Nu am putut schimba modul în care a atras fiecare pixel, în afară de a trimite o textură diferită, și nu am putut să distrugem nodurile după ce erau pe carte. Dar vremurile s-au schimbat și acum avem canale grafice programabile. Acum putem trimite codul pe placa video pentru a schimba modul în care arată pixelii, oferindu-le o apariție neclară cu hărțile normale și adăugând reflecții (și o mare realitate).

Acest cod este în formă de geometrie, zenit, și fragmentare shadere, și schimba în mod esențial modul în care placa video redă obiectele.


Vizualizare simplificată a unei conducte grafice programabile

Redirecționarea înainte

Transmiterea în avans este tehnica standard de redare, care este utilizată de majoritatea motoarelor. Furnizați placă grafică geometria, o proiectează și o descompune în noduri și apoi acestea sunt transformate și împărțite în fragmente sau pixeli care primesc tratamentul final de redare înainte de a trece pe ecran.


Redirecționarea înainte: Shader-ul geometriei pentru a shader-ul de vârf pentru a fragmenta Shader

Este destul de liniar, iar fiecare geometrie este trecută în jos pe conductă unul câte unul pentru a produce imaginea finală.


Repartizarea amânată

În redarea retrospectivă, după cum sugerează și numele, randarea este amânată puțin până când toate geometriile au trecut în jos pe conductă; imaginea finală este apoi produsă prin aplicarea umbririi la sfârșit.

Acum, de ce am face asta??


Ediția amânată: Geometria la vârf pentru a fragmenta shadere. A trecut la mai multe ținte de randare, apoi la umbră cu iluminare. Luminile amânate este o modificare a randării amânate care reduce dimensiunea bufferului G utilizând mai multe treceri pe scenă.

Performanță de iluminare

Lumina este principalul motiv pentru a merge pe o rută față de cealaltă. Într-o conductă standard de transmitere în avans, calculele de iluminare trebuie să fie efectuate pe fiecare vârf și pe fiecare fragment din scena vizibilă, pentru fiecare lumină din scenă.

Dacă aveți o scenă cu 100 de geometrii și fiecare geometrie are 1.000 de vârfuri, atunci este posibil să aveți aproximativ 100.000 de poligoane (o estimare foarte brută). Cardurile video pot gestiona acest lucru destul de ușor. Dar când aceste poligoane sunt trimise la shader-ul fragmentului, acolo se întâmplă calculele scumpe de iluminare și se poate produce o încetinire reală.

Dezvoltatorii încearcă să împingă cât mai multe calcule de iluminare în shader-ul Vertex posibil pentru a reduce cantitatea de lucru pe care trebuie să o facă fragmentul shader.

Calculele scumpe de iluminare trebuie executate pentru fiecare fragment vizibil al fiecărui poligon de pe ecran, indiferent dacă acesta se suprapune sau este ascuns de fragmentele unui alt poligon. Dacă ecranul dvs. are o rezoluție de 1024x768 (care este, în orice caz, nu este foarte mare res), aveți aproape 800.000 de pixeli care trebuie să fie redate. Ați putea ajunge cu ușurință la un milion de fragmente care funcționează în fiecare cadru. De asemenea, multe dintre fragmente nu vor ajunge niciodată pe ecran deoarece au fost îndepărtate cu teste de adâncime și, prin urmare, calculul iluminării a fost irosit pe ele.

Dacă aveți un milion din acele fragmente și deodată trebuie să redați acea scenă din nou pentru fiecare lumină, ați sărit [numere lumini] x 1.000.000 operațiuni fragment pe cadru! Imaginați-vă dacă ați avut un oraș plin de lumini de stradă, în cazul în care fiecare dintre ele este o sursă de lumină punctuală ...

Formula de estimare a acestei complexități de redare în avans poate fi scrisă, în notația O mare, ca O (num_geometry_fragments * num_lights). Puteți vedea aici că complexitatea este direct legată de numărul de geometrii și de numărul de lumini.

fragmente sunt pixeli potențiali care se vor termina pe ecran dacă nu vor fi sacrificați de testul de adâncime.

Acum, unele motoare optimizează acest lucru, prin tăierea unor lumini care sunt departe, prin combinarea luminilor sau prin utilizarea hărților luminoase (foarte populare, dar statice). Dar dacă doriți lumini dinamice și multe dintre ele, avem nevoie de o soluție mai bună.


Amânarea redusă la salvare

Renderingul amânat este o abordare foarte interesantă care reduce numărul de obiecte și, în special, numărul de fragmente totale și efectuează calculele de iluminare pe pixeli de pe ecran, utilizând astfel dimensiunea rezoluției în locul numărului total de fragmente.

Complexitatea redactării amânate, în nota O mare, este: O (ecran_resoluție * num_lights).

Puteți vedea că acum nu contează cât de multe obiecte ai pe ecran care determină numărul de luminări pe care le folosești, astfel încât să poți mări cu fermitate numărul de iluminat. (Aceasta nu înseamnă că puteți avea obiecte nelimitate - acestea trebuie încă să fie atrase de tampoane pentru a produce rezultatul final de redare.)

Să vedem cum funcționează.


Guts of rendering amânată

Fiecare geometrie este redată, fără o umbrire a luminii, la mai multe tampoane de spațiu de ecran care utilizează multiple obiective de randare. În special, adâncimea, normalele și culoarea sunt toate înscrise în tampoane separate (imagini). Aceste tampoane sunt apoi combinate pentru a furniza suficiente informații pentru fiecare lumină pentru a lumina pixelii.


Colour, Depth și Buffers normal. (Imagini de astrofa, prin intermediul Wikimedia Commons.)
Rezultatul final de iluminare (umbrire) generat folosind cele trei tampoane. (Imagine de astrofa, prin intermediul Wikimedia Commons.)

Cunoscând cât de departe este un pixel și vectorul său normal, putem combina culoarea acelui pixel cu lumina pentru a produce randamentul final.


Care să alegeți?

Răspunsul scurt este că, dacă utilizați mai multe lumini dinamice, atunci ar trebui să utilizați randarea amânată. Cu toate acestea, există unele dezavantaje semnificative:

  • Acest proces necesită o placă video cu mai multe ținte de redare. Vechile carduri video nu au acest lucru, deci nu va funcționa pe ele. Nu există soluție pentru acest lucru.
  • Este nevoie de lățime de bandă mare. Trimiteți tampoane mari și vechile carduri video, din nou, s-ar putea să nu reușești să rezolvi asta. De asemenea, nu există nici o soluție.
  • Nu puteți folosi obiecte transparente. (Cu excepția cazului în care combinați randarea amânată cu Forward Rendering doar pentru acele obiecte transparente, atunci puteți rezolva această problemă.)
  • Nu există anti-aliasing. Ei bine, unele motoare ar fi să crezi asta, dar există soluții la această problemă: detectarea margini, FXAA.
  • Este permisă numai un singur tip de material, cu excepția cazului în care utilizați o modificare a randamentului amânat numit Lighting Deferred.
  • Umbrele sunt încă dependente de numărul de lumini, iar randarea amânată nu rezolvă nimic aici.

Dacă nu aveți multe lumini sau doriți să puteți rula pe hardware mai vechi, atunci ar trebui să vă lipiți de redarea înainte și să înlocuiți multele lumini cu hărți luminoase statice. Rezultatele pot părea uimitoare.


Concluzie

Sper că a aruncat o lumină asupra subiectului. Opțiunile dvs. sunt pentru rezolvarea problemelor dvs. de redare, însă este foarte important să alegeți cea potrivită la începutul dezvoltării jocului pentru a evita ulterior modificările dificile.