Notă: Orice informație ce nu a fost acoperită în acest document este la latitudinea voastră!
Descriere generală
Scopul acestei teme va fi implementarea unui efect de blur de profunzime (Depth of Field / Bokeh Blur) aplicat unei imagini 2D, în care zona de focus va fi controlabilă interactiv de către utilizator.
Puteți studia în următorul videoclip o posibilă implementare a cerințelor.
Efectul urmărit este inspirat din tehnicile folosite în motoare grafice moderne (de exemplu, 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ță grafică interactivă în care utilizatorul poate muta punctul de focus cu mouse-ul și poate modifica raza de focus de la tastatură;
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ă
În cadrul temei, puteți alege dacă doriți să implementați pe CPU sau pe GPU (considerat bonus). În cazul implementării pe GPU, pentru a obține efectul dorit se vor folosi două treceri (2 pass-uri) de procesare pe GPU, pe un quad randat pe tot ecranul, astfel:
Primul pass: blur gaussian orizontal și salvarea valorii de blur;
Al doilea pass: blur gaussian vertical și compunerea rezultatului final.
În plus, se va folosi un shader simplu pentru afișarea texturii procesate și pentru desenarea zonelor de focus (cercurile concentrice).
Pașii principali ai algoritmului sunt următorii:
Se încărcă imaginea inițială (ca textură în cazul implementării pe GPU).
Prima etapă de procesare (primul pass în cazul implementării pe GPU):
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 procesează 2 imagini (în cazul implementării pe GPU, se scrie în două texturi):
A doua etapă de procesare (al doilea pass în cazul implementării pe GPU):
Se citește blurAmount din canalul alfa al imaginii (texturii) cu culoarea originală;
Se utilizeazăblurAmount pentru a recalcula dimensiunea măștii de filtrare;
Se aplică un blur gaussian vertical peste rezultatul orizontal;
Se scrie rezultatul final într-o imagine (textură) de output.
Afișare:
Se afișează fie imaginea originală, fie un rezultat intermediar, fie imaginea procesată;
Se desenează cercuri concentrice în jurul punctului de focus, pentru a marca vizual zona clară a imaginii.
Puteți începe cu oricare dintre cele două tipuri de blur. Varianta de mai sus pornește cu filtrul de blur orizontal.
Calculul cantității de blur
Punctul de focus este dat de poziția cursorului (mousePos) în coordonate ecran. Pentru un pixel cu poziția $(x, y)$, convertită în coordonate ecran, se calculează distanța:
$$
dist = \left\| (x, y) - mousePos \right\|
$$
Se definește un parametru focusRadius:
Pentru $dist < focusRadius$: pixelul este considerat în focus $\Rightarrow blurAmount = 0$.
Pentru $dist \ge focusRadius$: blurAmount crește odată cu distanța.
Un model simplu pentru calculul blurAmount ar putea fi:
În implementare se poate folosi un singur kernel gaussian sau o combinație de mai multe gaussiene cu $\sigma$ diferite și ponderi diferite, pentru un efect de bokeh mai interesant (de exemplu: 3 gaussiene cu $\sigma$ mic, mediu și mare).
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 pentru a simula forme de kernel mai complexe, inspirate de tehnici de tip Circular Separable Convolution Depth of Field utilizate în industria jocurilor (de exemplu, Frostbite).
Interacțiune cu utilizatorul
Poziția mouse-ului definește centrul zonei de focus, iar raza zonei de focus poate fi modificată de la tastatură. La apăsarea unui buton al mouse-ului se calculează imaginea blurată în funcție de poziția mouse-ului.
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 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 tastatura:
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;
Tasta 4 – Vizualizare rezultat final + desenarea zonelor de focus (cercuri concentrice).
În plus:
Tasta + – creșterea razei de focus (focusRadius);
Tasta - – scăderea razei de focus (focusRadius);
Click stânga – declanșarea procesării blurului.
Implementare și restricții
Tema trebuie implementată în limbajul de programare C/C++, în situația în care se realizează o rezolvare ce se execută pe unitatea centrală de procesare, CPU, sau într-un limbaj specializat pentru implementarea pe procesorul grafic, precum GLSL.
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 ca variabile uniforme.
Notare (200p)
Implementare blur gaussian separabil (50p)
Orizontal (25p)
Vertical (25p)
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 și afișarea corectă a rezultatului final (40p)
Vizualizarea zonei de focus prin cercuri concentrice (sau alt overlay clar) (40p)
Bonusuri posibile
Implementare pe GPU (25p)
Utilizarea unei combinații de mai multe gaussiene pentru kernel pentru un efect de bokeh mai realist (10-20p)
Optimizări suplimentare inspirate din tehnici de tip Circular Separable Convolution Depth of Field (10-20p)
Kernel-uri circulare;
Optimizări de sampling;
Păstrarea unor detalii speciale în zonele foarte blurate.
Interfață îmbunătățită (de exemplu: afișarea numerică a focusRadius, moduri de vizualizare suplimentare) (10p)
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:
#include “lab_m2/Tema2Bokeh/Tema2Bokeh.h”
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.