This shows you the differences between two versions of the page.
|
pgapi:teme:2024:02 [2025/12/09 01:25] andrei.voicu2409 [Prezentare rezultat] |
pgapi:teme:2024:02 [2025/12/09 10:54] (current) andrei.voicu2409 |
||
|---|---|---|---|
| Line 9: | Line 9: | ||
| ===== Descriere generală ===== | ===== 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. | + | În cadrul acestei teme, urmărim procesarea unei imagini pentru a obține o variantă stilizată a acesteia sub formă de schiță. |
| - | 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. | + | O imagine sub formă de schiță are următoarele caracteristici: |
| + | * Este alb-negru fără nuanțe de gri | ||
| + | * Păstrează contururile imaginii. Contururile sunt realizate folosind filtrul Sobel + binarizare | ||
| + | * [[https://www1.udel.edu/artfoundations/drawing/crosshatch.html|Linii de hașură]] arată locurile unde imaginea este mai închisă la culoare. Liniile de hașură sunt cu atât mai dese într-o zonă cu atât culorile imaginii sunt mai întunecate în acea zonă. | ||
| - | În cadrul temei trebuie: | + | În imaginea mai jos, puteți vizualiza mai multe rezultate obținute în urma aplicării abordării pe care trebuie să o implementați în cadrul acestei teme. |
| - | * 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. | + | {{ :pgapi:teme:2024:colaj_tema_2_2.png?600 |}} |
| - | {{ :pgapi:teme:2024:bokeh_examples.png?600 |Exemple de rezultate pentru efectul de Interactive Bokeh Blur}} | + | În cadrul temei, trebuie să implementați o anumită metodă propusă, ce este descrisă în secțiunile următoare. O privire de ansamblu asupra pașilor de realizare ai schiței prin această metodă poate fi vizualizată în imaginea de mai jos. Acești pași sunt prezentați în detaliu în secțiunile urmatoare. |
| - | ===== Arhitectura generală ===== | + | {{ :pgapi:teme:2024:sketch.png?600 |}} |
| - | Pentru a obține efectul dorit se vor folosi două treceri (2 pass-uri) de procesare pe GPU, pe un ''quad'' pe tot ecranul: | + | <note important>Algoritmii de mai jos au ca parametrii diferite valori de prag, direcții de hașurare, densitatea hașurării etc. Aceste valori sunt la libertatea voastră de a îi seta cu condiția ca programul vostru să aibă rezultate vizuale pe diferite imagini în care să se vadă clar contururi ale imaginii și linii de hașură.</note> |
| - | - **Primul pass** – blur gaussian orizontal + stocarea valorii de blur; | + | ===== Filtru Sobel + binarizare ===== |
| - | - **Al doilea pass** – blur gaussian vertical și compunerea rezultatului final. | + | |
| - | În plus, se va folosi un shader simplu pentru: | + | Pentru a construi contururile schiței, vom aplica filtrul Sobel pe imaginea originală și vom binariza ([[pgapi:laboratoare:09|]]). |
| - | * afișarea texturii procesate; | + | Pentru a binariză, vom stabili că un pixel este negru dacă în urma filtrului Sobel valoarea este mai mare decât un prag. Dacă valoarea este mai mică decât un prag, atunci pixelul va fi alb. |
| - | * desenarea zonelor de focus (cercurile concentrice). | + | Valoarea de prag este la alegerea voastră. |
| - | **Pașii principali ai algoritmului:** | + | {{ :pgapi:teme:2024:sobel.png?600 |}} |
| - | 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ă. | + | |
| - | {{ :pgapi:teme:2024:bokeh_pipeline.png?600 |Schema de principiu a celor două pass-uri de procesare}} | + | ===== Filtru de netezire separabil ===== |
| - | ===== Calculul cantității de blur ===== | + | Înainte de a aplica hașurarea, este necesară netezirea imaginii folosind un filtru medie similar cu cel din [[pgapi:laboratoare:08|]] numai că filtrul folosit va fi de dimensiuni 25x25. |
| - | 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: | + | Aplicarea filtrului folosind algoritmul ad-hoc presupune pentru fiecare pixel efectuarea a 625 eșantionări în textură. |
| + | |||
| + | Un algoritm mai optim este separarea filtrului în două filtre de dimensiuni 25x1 respectiv 1x25 [[https://en.m.wikipedia.org/wiki/Separable_filter|folosind ideea de aici]]. Netezirea se va realiza în doi pași. | ||
| + | |||
| + | Începem cu imaginea originală: | ||
| + | {{ :pgapi:teme:2024:earth.png?600 |}} | ||
| + | |||
| + | Primul pas este efectuarea unei neteziri pe orizontală. Fiecare pixel va fi egal cu media aritmetică a pixelului și a celor 24 de vecini pe aceeași linie cu pixelul. | ||
| + | |||
| + | Rezultatul este acesta: | ||
| + | {{ :pgapi:teme:2024:earth_blur_horz.png?600 |}} | ||
| + | |||
| + | Al doilea pas este efectuarea pe acest rezultat a unei neteziri pe verticală. Fiecare pixel va fi egal cu media aritmetică a pixelului și a celor 24 de vecini pe aceeași coloană cu pixelul. | ||
| + | |||
| + | Rezultatul este acesta: | ||
| + | {{ :pgapi:teme:2024:earth_blur_vert.png?600 |}} | ||
| + | |||
| + | Această metodă reduce numărul total de eșantionări a texturii pentru fiecare pixel de la 625 la 50. | ||
| + | |||
| + | ===== Filtru de hașurare ====== | ||
| + | |||
| + | ==== Model de hașurare ===== | ||
| + | |||
| + | Pentru filtrul de hașurare, primul pas este creearea unui model de hașurare, format din linii subțiri, paralele. | ||
| + | |||
| + | Din ecuația liniei avem: | ||
| $$ | $$ | ||
| - | dist = \left\| (x, y) - mousePos \right\| | + | a \cdot x + b \cdot y + c = 0 |
| $$ | $$ | ||
| - | Se definește un parametru ''focusRadius'': | + | unde $\{x, y\} \in [0, 1]$ reprezintă coordonata unui pixel în spațiul texturii. |
| - | * Pentru $dist < focusRadius$: pixelul este considerat în focus $\Rightarrow blurAmount = 0$. | + | |
| - | * Pentru $dist \ge focusRadius$: ''blurAmount'' crește odată cu distanța. | + | Pentru a obține linii paralele, este suficient să schimbăm parametrul $c$ . |
| - | Un model simplu este: | ||
| $$ | $$ | ||
| - | normalizedDist = \frac{dist - focusRadius}{focusRadius \cdot 2.0} | + | a\cdot x + b\cdot y + c_1 = 0 \\ |
| + | a\cdot x + b\cdot y + c_2 = 0 | ||
| $$ | $$ | ||
| + | |||
| + | |||
| + | |||
| + | Pentru a obține o fâșie (o linie de o anumită grosime), putem rearanja ecuația în: | ||
| + | |||
| + | |||
| $$ | $$ | ||
| - | blurAmount = clamp(normalizedDist, 0.0, 1.0) | + | a\cdot x + b\cdot y \in[-c_1,-c_2] |
| $$ | $$ | ||
| - | Raza efectivă a blurului este: | + | |
| + | |||
| + | |||
| + | |||
| + | Pentru a obține fâșii paralele ce se repetă la infinit, putem aplica în stânga ecuației o funcție periodică precum sinus sau cosinus: | ||
| + | |||
| $$ | $$ | ||
| - | dynamicBlurRadius = int(MAX\_BLUR\_RADIUS \cdot blurAmount) | + | sin(a\cdot x + b\cdot y) \in[-c_1,-c_2] |
| $$ | $$ | ||
| - | unde ''MAX_BLUR_RADIUS'' este o constantă (ex: 40). | ||
| - | ===== Filtru de netezire separabil (blur gaussian) ===== | ||
| - | Pentru blur se folosește un filtru gaussian **separabil**: | ||
| - | * într-un pass se aplică doar pe orizontală (axa X); | ||
| - | * în celălalt pass se aplică doar pe verticală (axa Y). | ||
| - | Aceasta reduce complexitatea de la $O(N^2)$ la $O(2N)$ pentru un kernel de dimensiune $N$. | + | Pentru că funcția sinus produce valori între -1 și 1, putem simplifica ecuația prin utilizarea unei singure inegalități: |
| + | |||
| - | Exemplu de kernel gaussian 1D: | ||
| $$ | $$ | ||
| - | G(x) = \frac{exp\left(-0.5 \cdot \frac{x^2}{\sigma^2}\right)}{\sqrt{2\pi} \cdot \sigma} | + | sin(a\cdot x + b\cdot y) > c |
| $$ | $$ | ||
| - | Raza blurului și $\sigma$ se pot raporta la ''blurAmount'': | ||
| - | * $\sigma = k \cdot MAX\_BLUR\_RADIUS \cdot blurAmount$ | ||
| - | * $dynamicBlurRadius \approx MAX\_BLUR\_RADIUS \cdot blurAmount$ | ||
| - | În implementare se poate folosi: | ||
| - | * un singur gaussian; | ||
| - | * sau o combinație (mixtură) de mai multe gaussiene cu $\sigma$ diferite și ponderi diferite, pentru un efect de bokeh mai interesant (ex: 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; | + | unde modificarea parametrului $c$ va duce la schimbarea grosimii liniilor, iar modificarea parametrilor $a$ și $b$ va duce la schimbarea frecvenței și a direcției acestora. |
| - | * zonele apropiate de focus rămân clare; | + | |
| - | * zonele îndepărtate sunt estompate din ce în ce mai mult. | + | |
| - | <note tip> | + | Mai multe rezultate pentru aplicarea modelului de hașurare descris mai sus cu diferite valori ale lui $a$ , $b$ și $c$ pot fi vizualizate în imaginea de mai jos. |
| - | 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). | + | |
| - | </note> | + | |
| - | ===== Interacțiune cu utilizatorul ===== | + | {{ :pgapi:teme:2024:sketch2.png?600 |}} |
| - | * 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: | + | |
| - | * afișarea imaginii originale; | + | |
| - | * afișarea imaginii blurate. | + | |
| - | Pentru a vizualiza mai ușor zona de focus, se desenează cercuri concentrice în jurul mouse-ului, în shaderul de afișare: | + | ==== Aplicare model de hașurare ==== |
| - | * 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. | + | |
| - | {{ :pgapi:teme:2024:bokeh_focus_rings.png?600 |Exemplu de reprezentare a zonei de focus cu cercuri concentrice}} | + | Pentru a realiza procesul de hașurare doar pentru anumite zone din imagine și astfel să urmărim detaliile prezente în ea, trebuie să utilizăm modelul de hașurare doar pentru pixelii care respectă anumite criterii. Cel mai simplu criteriu este să transformăm culoarea pixelului din modelul RGB în nuanță de gri, precum în [[pgapi:laboratoare:08]], să considerăm faptul că această nuanță de gri este intensitatea culorii din pixel și să utilizăm modelul de hașurare doar în situația în care pixelul are intensitatea mai mică decât un prag. |
| - | ===== Prezentare rezultat ===== | + | În rezultatul final, trebuie utilizate 3 filtre de hașurare, toate cu direcții și praguri de intensitate diferite. Alegerea acestor valori rămâne la latitudinea voastră. |
| - | Aplicația trebuie să permită vizualizarea rezultatelor în mai multe moduri, folosind tastele de pe tastatură: | + | Pentru o diversificare a rezultatelor, trebuie să introduceți în cel puțin unul din cele 3 filtre de hașurare utilizarea unor linii albe pe fundal negru și în cel puțin un alt filtru de hașurare linii negre pe fundal alb. Fundalul negru se consideră doar pentru pixelii care respectă pragul de intensitate. |
| - | * Tasta **0** – Vizualizare imagine originală; | + | ===== Prezentare rezultat ====== |
| - | * 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: | + | Pentru a se prezenta mai ușor rezultatul obținut, aplicația realizată de către voi trebuie să permită vizualizarea individuală arezultatelor pentru toți pașii intermediari ai metodei. Se vor folosi tastele de la tastatură după cum urmează: |
| - | * Tasta **+** – creșterea razei de focus (''focusRadius''); | + | * Tasta **0** - Vizualizare imagine originală; |
| - | * Tasta **-** – scăderea razei de focus (''focusRadius''); | + | * Tasta **1** - Vizualizare rezultat filtru Sobel + binarizare; |
| - | * Click stânga – comutare între imaginea originală și imaginea blurată (sau declanșarea procesării blurului). | + | * Tasta **2** - Vizualizare rezultat filtru de netezire orizontal; |
| + | * Tasta **3** - Vizualizare rezultat filtru de netezire final - orizontal și vertical. În continuare se consideră că acesta este și rezultatul filtrului de netezire; | ||
| + | * Tasta **4** - Vizualizare rezultat filtru de netezire + aplicare filtru de hașurare 1; | ||
| + | * Tasta **5** - Vizualizare rezultat filtru de netezire + aplicare filtru de hașurare 2; | ||
| + | * Tasta **6** - Vizualizare rezultat filtru de netezire + aplicare filtru de hașurare 3; | ||
| + | * Tasta **7** - Vizualizare rezultat filtru de netezire + aplicare toate cele 3 filtre de hașurare; | ||
| + | * Tasta **8** - Vizualizare rezultat final al metodei. | ||
| - | Implicit, aplicația va porni în modul interactiv complet (tasta **4**). | + | Implicit, aplicația se va deschide cu vizualizarea rezultatului final. |
| - | + | ||
| - | ===== Implementare și restricții ===== | + | |
| <note important> | <note important> | ||
| - | * Tema trebuie implementată în **C/C++** pentru partea de aplicație și **GLSL** pentru shadere. | + | În rezolvarea temei sunt următoarele restricții: |
| - | * **NU** este permisă utilizarea de biblioteci de procesare de imagine pentru implementarea efectului de blur. Efectul trebuie implementat în shaderele voastre (GLSL). | + | * 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. |
| - | * Se pot folosi biblioteci pentru: | + | * **NU** este permisă utilizarea niciunei biblioteci pentru realizarea metodelor de procesare și analiză de imagini în rezolvarea temei. Se pot utiliza biblioteci pentru alte aspecte ale rezolvării, precum încărcarea și salvarea fișierelor de tip imagine. |
| - | * încărcarea imaginilor (texturi); | + | * **NU** este permisă utilizarea unui alt limbaj de programare în afara celor menționate. |
| - | * 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. | + | |
| </note> | </note> | ||
| - | ===== Notare (200p) ===== | + | ===== Notare (200) ===== |
| - | + | * +25p - Filtru Sobel + binarizare | |
| - | * +40p – Implementare blur gaussian separabil (orizontal + vertical). | + | * +50p - Filtru de netezire separabil cu mască de convoluție de dimensiune cel puțin 25x25 |
| - | * +40p – Calcul dinamic al cantității de blur în funcție de distanța față de punctul de focus. | + | * Această cerinta se punctează doar în situația în care filtrul de netezire este implement în 2 pași. |
| - | * +40p – Integrare completă a celor două pass-uri (''FirstCompute'' + ''SecondCompute'') și afișarea corectă a rezultatului final. | + | * +75p - Filtru de hașurare |
| - | * +30p – Interfață interactivă: | + | * +25p - Aplicare 3 filtre de hașurare cu parametri diferiți |
| - | * mutarea punctului de focus cu mouse-ul; | + | * +25p - Vizualizarea individuală a rezultatelor pentru pașii intermediari ai metodei |
| - | * modificarea razei de focus din tastatură; | + | * +5p - Vizualizare rezultat filtru Sobel + binarizare; |
| - | * comutare între imagine originală / imagine blurată. | + | * +5p - Vizualizare rezultat filtru de netezire; |
| - | * +25p – Vizualizarea zonei de focus prin cercuri concentrice (sau alt overlay clar). | + | * +10p - Vizualizare rezultate filtru de netezire + aplicare filtru de hașurare cu parametri diferiți; |
| - | * +25p – Organizarea codului și claritatea implementării (structură fișiere, comentarii, tratarea corectă a rezoluției imaginii și a aspect ratio-ului). | + | * +5p - Vizualizare rezultat filtru de netezire + filtru de hașurare. |
| ===== Bonusuri posibile ===== | ===== Bonusuri posibile ===== | ||
| - | * +10–20p – Utilizarea unei combinații de mai multe gaussiene pentru kernel (mixtură de gaussiene) pentru un efect de bokeh mai realist. | + | * Implementarea pe unitatea de procesare grafica a pașilor prezentați în cerință |
| - | * +10–20p – Optimizări suplimentare inspirate din tehnici de tip ''Circular Separable Convolution Depth of Field'': | + | * Implementarea paralelă pe unitatea centrală de procesare a pașilor prezentați în cerință |
| - | * kernel-uri circulare; | + | * Implementarea filtrului de netezire Gaussian în 2 pași |
| - | * optimizări de sampling; | + | |
| - | * păstrarea unor detalii speciale în zonele foarte blurate. | + | |
| - | * +10p – Interfață îmbunătățită (ex: afișarea numerică a ''focusRadius'', moduri de vizualizare suplimentare). | + | |
| ===== Indicații suplimentare ===== | ===== Indicații suplimentare ===== | ||
| - | Este indicat să folosiți framework-ul laboratorului și Visual Studio. | + | Este indicat să folosiți framework-ul ș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 implementarea temei, în folderul **src/lab_m2** puteți crea un nou folder, de exemplu Tema2, cu fișierele Tema2.cpp și Tema2.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, apăsati click dreapta pe filtrul lab_m2 și selectați Add→New Filter. Dupa ce creați un nou filtru, de exemplu Tema1, dați click dreapta și selectați Add→Existing Item. Astfel adăugați toate fișierele din folderul nou creat. În fișierul lab_list.h trebuie adaugată și calea către header-ul temei. De exemplu: #include “lab_m2/Tema2/Tema2.h” |
| - | Pentru a vedea fișierele nou create în Visual Studio în **Solution Explorer**: | + | ===== Arhivarea proiectului ===== |
| - | * 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 ===== | + | |
| <note> | <note> | ||
| - | * În mod normal arhiva trebuie să conțină toate resursele necesare compilării și rulării. | + | * Î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: | + | * î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** | + | * 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) | + | * și ștergeți folderul __**/build/.vs**__ (dacă nu îl vedeți, **este posibil să fie ascuns**) |
| - | * SAU ștergeți complet folderul **/build**. | + | * 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. | + | * în cazul în care arhiva tot depășește limita de 50MB (nu ar trebui), puteți să ștergeți și folderul __**/deps**__ sau __**/assets**__ întrucat se pot adăuga la testare. Nu este recomandat să faceți acest lucru întrucat îngreunează mult testarea în cazul în care versiunea curentă a bibliotecilor/resurselor diferă de versiunea utilizată la momentul scrierii temei. |
| </note> | </note> | ||
| - | |||