Pentru a desena obiecte iluminate 3D metoda studiată până acum este prin aplicarea directă a calculelor de iluminare (iluminare în vertex sau fragment shader) pentru a determina culorile pixelilor suprafețelor desenate. Această tehnică se numește forward rendering.
Tehnica forward rendering nu se scalează bine când sunt multe surse de lumină deoarece se realizează calculele de iluminare și pentru pixelii unor suprafețe care sunt pe urmă obturați de pixelii altor suprafețe care sunt mai apropiați de observator.
Pentru multe surse de lumină este avantajos să realizăm calculele de iluminare doar pentru pixelii care râmăn afișați în final pe ecran.
Deferred Rendering este o tehnică avansată, extensibilă si versatilă de sinteză în timp real de imagini ale obiectelor dintr-o scenă 3D. Cu un nume sugestiv, 'intârziat' sau 'amânat', tehnica se bazează pe desenarea de informație a geometriei din fiecare pixel(poziție in spațiul lume, vectorul normal în spațiul lume, constanta difuză, constanta speculară, strălucirea etc.) în texturi separate într-un prim pas, amânând procesul de iluminare pentru un pas urmator. Astfel când începe procesul de iluminare se vor folosi informațiile pixelilor celor mai apropiați de observator.
In forward rendering culoarea finală a unui pixel se obține prin contribuția fiecărui fragment afișat in acel pixel, iar pentru culoarea fragmentelor se evaluează contribuția de la fiecare lumină din scenă. Din cauza aceasta, sunt evaluate fragmente ce vor fi acoperite ulterior sau se calculează contribuția neglijabilă a unei lumini îndepărtate.
In deferred rendering, ecuația de iluminare nu se mai execută pentru fiecare combinație posibilă (obiect, lumina), ci doar pentru luminile ce garantat au o contribuție ne-neglijabila.
Acest lucru se face in 3 etape:
Pentru a implementa deferred rendering, vom folosi un frame buffer mare, denumit Geometry Buffer, sau G-Buffer. Acesta are atașate mai multe render textures utilizând GL_COLOR_ATTACHMENT_i.
In această etapă sunt completate urmatoarele render targets din G-buffer:
In această etapă sunt completate intrările din G-buffer pentru acumularea de lumină.
Pentru a calcula intersecția intre obiecte și lumini vom folosi obiecte geometrice aferente luminilor: sfera cu rază egala cu distanța maximă de influență pentru lumina omnidirectională, con cu sferă în baza pentru spot light(nu e implementat in laborator).
Pentru fiecare fragment de obiect ce reprezintă o lumină se încarcă poziția si normala din G-buffer și se evaluează ecuația de iluminare. Rezultatul este acumulat in bufferul de acumulare din G-buffer.
In aceasta etapă se calculează rezultatul final per pixel. Culoarea nu se scrie in G-buffer, ci direct in framebuffer-ul default (cel al ferestrei grafice) sau în altul pregatit pentru postprocesare. Se combină culoarea pixelului cu iluminarea calculată și cu lumina ambientală.
Forward: for (obiect in obiecte): for (lumina in lumini): calculeaza_iluminarea(lumina, obiect)
Deferred: for (obiect in obiecte): deseneaza(obiect, Gbuffer) for (lumina in lumini): deseneaza(lumina)
Init
, atribuirea pentru fiecare din cele 40 de surse de lumină din scenă a unei poziții, a unei raze și a unei culori alese aleator.light_position
, light_color
și light_radius
, de tipul uniform, cu informațiile sursei de lumină.LightPass.FS.glsl
eșantionați texturile din G-buffer și folosiți metoda PhongLight pentru a calcula influența sursei de lumină ce va fi acumulată.Composition.FS.glsl
, calculul de compoziție între culoarea obiectelor și influența luminilor asupra obiectelor.