This is an old revision of the document!
Tema 2 - Sketch Effect
Responsabili: Vlad Novetschi, Robert Caragicu, Cristian Lambru
Lansare: 14 decembrie 2024
Termen de predare: 14 ianuarie 2025, ora 23:55
-
Notă: Orice informație ce nu a fost acoperită în acest document este la latitudinea voastră!
Descriere generală
În cadrul acestei teme urmărim implementarea unui efect de blur de profunzime (Depth of Field / Bokeh Blur) aplicat unei imagini 2D, cu zonă de focus controlabilă interactiv de către utilizator.
Efectul urmărit este inspirat din tehnicile folosite în motoare grafice moderne (ex. Frostbite), unde zonele din afara planului de focus sunt estompate folosind kernel-uri de blur gaussian (sau combinații de mai multe gaussiene), pentru a simula comportamentul unei lentile reale.
În cadrul temei trebuie:
să implementați un blur gaussian separabil (orizontal + vertical);
să controlați dinamic raza de blur în funcție de distanța față de un punct de focus;
să realizați o interfață interactivă în care utilizatorul poate muta punctul de focus cu mouse-ul și poate modifica raza de focus;
să evidențiați vizual zona de focus (de exemplu prin desenarea unor cercuri concentrice în jurul cursorului).
Efectul final trebuie să arate ca un blur radial: zona din jurul cursorului este clară, iar blurul crește progresiv odată cu distanța față de aceasta.
Arhitectura generală
Pentru a obține efectul dorit se vor folosi două treceri (2 pass-uri) de procesare pe GPU, pe un quad pe tot ecranul:
Primul pass – blur gaussian orizontal + stocarea valorii de blur;
Al doilea pass – blur gaussian vertical și compunerea rezultatului final.
În plus, se va folosi un shader simplu pentru:
Pașii principali ai algoritmului:
1. Încărcarea imaginii inițiale ca textură.
2. Primul pass:
* se calculează, pentru fiecare pixel, distanța până la punctul de focus;
* se determină „cantitatea de blur” (''blurAmount'') pe baza acestei distanțe;
* se aplică un blur gaussian orizontal, cu o rază care depinde de ''blurAmount'';
* se scriu în două texturi:
* **textura 0**: rezultatul blurului orizontal;
* **textura 1**: culoarea originală + ''blurAmount'' stocat în canalul alfa.
3. Al doilea pass:
* se citește ''blurAmount'' din canalul alfa al texturii cu culoarea originală;
* se calculează din nou o rază de blur în funcție de ''blurAmount'';
* se aplică blur gaussian vertical peste rezultatul orizontal;
* se scrie rezultatul final într-o textură de output.
4. Afișare:
* se afișează fie imaginea originală, fie imaginea procesată;
* se desenează, opțional, cercuri concentrice în jurul punctului de focus, pentru a marca vizual zona clară.
Calculul cantității de blur
Punctul de focus este dat de poziția cursorului (mousePos) în coordonate de ecran. Pentru un pixel cu poziția $(x, y)$, convertită în coordonate de ecran, se calculează distanța:
$$
dist = \left\| (x, y) - mousePos \right\|
$$
Se definește un parametru focusRadius:
Un model simplu este:
$$
normalizedDist = \frac{dist - focusRadius}{focusRadius \cdot 2.0}
$$
$$
blurAmount = clamp(normalizedDist, 0.0, 1.0)
$$
Raza efectivă a blurului este:
$$
dynamicBlurRadius = int(MAX\_BLUR\_RADIUS \cdot blurAmount)
$$
unde MAX_BLUR_RADIUS este o constantă (ex: 40).
Filtru de netezire separabil (blur gaussian)
Pentru blur se folosește un filtru gaussian separabil:
Aceasta reduce complexitatea de la $O(N^2)$ la $O(2N)$ pentru un kernel de dimensiune $N$.
Exemplu de kernel gaussian 1D:
$$
G(x) = \frac{exp\left(-0.5 \cdot \frac{x^2}{\sigma^2}\right)}{\sqrt{2\pi} \cdot \sigma}
$$
Raza blurului și $\sigma$ se pot raporta la blurAmount:
În implementare se poate folosi:
Model de bokeh / blur radial
Pentru a obține un efect de bokeh / blur radial:
cantitatea de blur depinde strict de distanța față de punctul de focus;
zonele apropiate de focus rămân clare;
zonele îndepărtate sunt estompate din ce în ce mai mult.
Opțional, se poate implementa combinarea mai multor gaussiene (mixtură) pentru a simula forme de kernel mai complexe, inspirate de tehnici de tip Circular Separable Convolution Depth of Field utilizate în industria jocurilor (ex. Frostbite – EA).
Interacțiune cu utilizatorul
Poziția mouse-ului definește centrul zonei de focus.
Raza zonei de focus poate fi modificată din tastatură.
La apăsarea unui buton de mouse se poate comuta între:
Pentru a vizualiza mai ușor zona de focus, se desenează cercuri concentrice în jurul mouse-ului, în shaderul de afișare:
se consideră pixelul curent în coordonate de ecran;
se testează dacă pixelul se află la o distanță „aproape egală” cu o rază dată (ex: $r$, $r/2$, $r/4$);
dacă testul este adevărat, acel pixel este colorat alb (sau altă culoare), obținându-se cercuri de ghidaj.
Prezentare rezultat
Aplicația trebuie să permită vizualizarea rezultatelor în mai multe moduri, folosind tastele de pe tastatură:
Tasta 0 – Vizualizare imagine originală;
Tasta 1 – Vizualizare rezultat după primul pass (blur gaussian orizontal + stocarea blurAmount);
Tasta 2 – Vizualizare rezultat final după al doilea pass (blur gaussian vertical);
Tasta 3 – Vizualizare rezultat final + desenarea zonelor de focus (cercuri concentrice);
Tasta 4 – Vizualizare mod interactiv complet (mutarea mouse-ului, modificarea focusRadius, blur actualizat dinamic).
În plus:
Tasta + – creșterea razei de focus (focusRadius);
Tasta - – scăderea razei de focus (focusRadius);
Click stânga – comutare între imaginea originală și imaginea blurată (sau declanșarea procesării blurului).
Implicit, aplicația va porni în modul interactiv complet (tasta 4).
Implementare și restricții
Tema trebuie implementată în C/C++ pentru partea de aplicație și GLSL pentru shadere.
NU este permisă utilizarea de biblioteci de procesare de imagine pentru implementarea efectului de blur. Efectul trebuie implementat în shaderele voastre (GLSL).
Se pot folosi biblioteci pentru:
încărcarea imaginilor (texturi);
managementul ferestrei și contextului OpenGL;
dialoguri de selectare a fișierelor etc.
Comportamentul interactiv (citirea input-ului de mouse/tastatură) se va realiza în C++ și se vor trimite datele relevante (mousePos, focusRadius etc.) în GLSL prin uniform-uri.
Notare (200p)
+40p – Implementare blur gaussian separabil (orizontal + vertical).
+40p – Calcul dinamic al cantității de blur în funcție de distanța față de punctul de focus.
+40p – Integrare completă a celor două pass-uri (FirstCompute + SecondCompute) și afișarea corectă a rezultatului final.
+30p – Interfață interactivă:
mutarea punctului de focus cu mouse-ul;
modificarea razei de focus din tastatură;
comutare între imagine originală / imagine blurată.
+25p – Vizualizarea zonei de focus prin cercuri concentrice (sau alt overlay clar).
+25p – Organizarea codului și claritatea implementării (structură fișiere, comentarii, tratarea corectă a rezoluției imaginii și a aspect ratio-ului).
Bonusuri posibile
+10–20p – Utilizarea unei combinații de mai multe gaussiene pentru kernel (mixtură de gaussiene) pentru un efect de bokeh mai realist.
+10–20p – Optimizări suplimentare inspirate din tehnici de tip Circular Separable Convolution Depth of Field:
+10p – Interfață îmbunătățită (ex: afișarea numerică a focusRadius, moduri de vizualizare suplimentare).
Indicații suplimentare
Este indicat să folosiți framework-ul laboratorului și Visual Studio.
Pentru implementarea temei, în folderul src/lab_m2 puteți crea un nou folder, de exemplu Tema2Bokeh, cu fișierele Tema2Bokeh.cpp și Tema2Bokeh.h (pentru implementare POO, este indicat să aveți și alte fișiere).
Pentru a vedea fișierele nou create în Visual Studio în Solution Explorer:
click dreapta pe filtrul lab_m2 și selectați Add → New Filter;
creați un nou filtru, de exemplu Tema2Bokeh;
click dreapta pe noul filtru și selectați Add → Existing Item;
adăugați toate fișierele din folderul nou creat.
În fișierul lab_list.h trebuie adăugată și calea către header-ul temei, de exemplu:
Arhivarea proiectului
În mod normal arhiva trebuie să conțină toate resursele necesare compilării și rulării.
Înainte de a face arhiva asigurați-vă că ați curățat proiectul Visual Studio:
click dreapta pe proiect în Solution Explorer → Clean Solution
și ștergeți folderul /build/.vs (dacă nu îl vedeți, este posibil să fie ascuns)
SAU ștergeți complet folderul /build.
În cazul în care arhiva tot depășește limita de 50MB, puteți să ștergeți și folderele /deps sau /assets, întrucât se pot adăuga la testare. Nu este recomandat să faceți acest lucru întrucât îngreunează mult testarea în cazul în care versiunea curentă a bibliotecilor/resurselor diferă de versiunea utilizată la momentul scrierii temei.