Tema 3 - Lighthouse

  • Responsabili: Andrei Lăpușteanu, Vlad-Matei Drăghici, Mihnea-Petruţ-Ilie Mitrache
  • Lansare: 18 decembrie 2023
  • Termen de predare: 14 ianuarie 2024, ora 23:59
  • Regulament: Regulament general
  • Notă: Această temă este considerată temă suplimentară
  • Orice informație ce nu a fost acoperită în acest document este la latitudinea voastră!

În cadrul temei 3 veți avea de implementat o aplicație grafică bazată pe conceptele de iluminare și texturare - în acest sens, propunem crearea unei scene virtuale ce are ca tematică principală un far (lighthouse), precum și o serie de elemente vizuale menite să sporească realismul scenei - bărcuțe, lună, insulă, etc.

Puteți studia în următorul videoclip o posibilă implementare a cerințelor.

În videoclip interacțiunea cu slider-ele se realizează folosind cursorul - această cerință nu este impusă.

Scena virtuală

Scena va fi compusă dintr-o serie de modele 3D, anume:

  • Apa: Formată dintr-un plan/quad
  • Insula: Formată dintr-o sferă (scalată pe Y în exemplul nostru)
  • Farul: Format din 3 cilindri: Bază, reflector, acoperiș
  • Luna: Formată dintr-o sferă
  • Bărcuțe: Formate din cel puțin două primitive

  • Este permisă importarea de mesh-uri create în aplicații de modelare 3D
  • Primitiva cilindru pe care am folosit-o pentru demo o puteți descărca de aici: cylinder.zip

Următoarea imagine prezintă un exemplu de construcție al acestor modele.

Nu sunt aplicate calcule de iluminare în imaginea de mai sus.

Construcția scenei

Scena virtuală trebuie configurată astfel încât să se poată vizualiza în mod ușor toate elementele de interes. Vă recomandăm o configurație similară cu cea prezentată în demo.

Comportamentul bărcuțelor

Instanțiere și construcție: În scenă vom avem un număr fix de bărcuțe, minim 4. Bărcuțele trebuie să fie modelate a.î. să se poată identifica direcția lor de deplasare. În demo, direcția este indicată de velă.

Dinamică: Fiecare bărcuță se va deplasa pe un cerc de rază aleatorie, centrat în poziția farului. Punctul de start pe cerc, definit de unghiul de parcurgere a acestuia, este arbitrar. Viteza unghiulară de deplasare și sensul de rotație se modelează de asemenea aleatoriu.

Valoarea pozitivă sau negativă a vitezei dă sensul deplasării.

În timpul deplasării, bărcuțele trebuie să fie orientate conform direcției de deplasare pe cerc.

Poziționarea camerei

Camera va fi de tip perspectivă și trebuie poziționată astfel încât să fie surprinse în același timp toate elementele de interes din scenă (apa, insula, farul, luna, bărcuțele). Nu este obligatoriu să controlați poziția/rotația camerei în timpul rulării aplicației, aceasta poate să rămână statică.

Texturare

Este obligatorie texturarea fiecărui element de geometrie prezentat în secțiunea Scena Virtuală, cu excepția mesh-ului corespunzător reflectorului din far.

Texturarea apei

Pe mesh-ul corespunzător apei va trebui aplicată o textură care se repetă. Acest lucru se poate obține prin oricare dintre următoarele 2 moduri:

  • Folosirea unui mesh (fie importat, fie creat de către voi din cod) ale cărui coordonate de texturare sunt în afara domeniului uzual al spațiului UV (0,0) → (1,1)
  • Prin scalarea coordonatelor de texturare în shader. În cazul în care mesh-ul pentru plan/quad are toate coordonatele de texturare definite în intervalul (0,0) → (1,1), deoarece acest mesh trebuie scalat în mod semnificativ pentru scena virtuală, simpla aplicare a texturii va conduce la întinderea acesteia pe întreg planul și veți obține un efect 'zoomed-in'. Așadar, va trebui să scalați coordonatele de texturare în shader pentru a repeta textura pe mesh

Nu uitați că este este necesară setarea wrapping_mode-ului texturii cu GL_REPEAT. De asemenea, vă recomandăm utilizarea unei texturi de tip “seamless” pentru acest task.

Realizarea efectului de mișcare al apei

Textura apei va trebui modificată în mod continuu pentru a crea un efect de mișcare al acesteia. Pentru a obține acest efect este nevoie de translatarea în funcție de timp a coordonatelor de texturare.

Este obligatorie implementarea acestei cerințe în shader - un efect similar se poate obține prin simpla translatare a mesh-ului în mod continuu, ceea ce este nepermis.

Vă puteți folosi de Engine::GetElapsedTime() pentru a obține timpul scurs de la pornirea aplicației.

Realizarea efectului de valuri în shader

Pentru a reda un efect de valuri, textura aplicată apei va trebui alterată în mod continuu în fragment shader. Rezultatul implementării voastre nu trebuie să replice în mod direct exemplul din demo, dar este necesar să se supună următoarelor reguli:

  • Implementare în fragment shader
  • Folosirea unor funcții trigonometrice împreună cu poziția în lume a fragmentelor pentru a modula coordonatele de texturare
  • Animație de tip continuu, așadar, necesitatea folosirii unei variabile pentru timp

Pentru a înțelege mai bine conceptul puteți studia următorul snippet de cod - acesta colorează mesh-ul de apă în funcție de poziția în spațiul lume a fragmentelor. Observați faptul că aceeste coordonate (s-a considerat numai coordonata X a acestora) sunt modulate folosind o funcție trigonometrică.

// GLSL code
// sin() outputs in range [-1;1]. Adding 1 and multiplying with 0.5 remaps result to [0;1] range (for rendering purposes).
vec2 modulated_coords = (vec2(sin(world_position.x * 10)) + 1) * 0.5; 
out_color = vec4(modulated_coords.x, modulated_coords.x, modulated_coords.x, 1);

În imaginea de mai jos puteți observa efectul obținut:

Nu sunt aplicate calcule de iluminare în imaginea de mai sus.

Atenție, această colorare este doar în scop demonstrativ! Voi va trebui să vă folosiți de acest concept nu pentru colorarea directă a mesh-ului, ci pentru alterarea coordonatelor de texturare ale apei.

În GIF-ul de mai jos puteți observa în partea stângă textura apei care suferă doar efectul de translație, iar în partea dreaptă un exemplu pentru translație + efectul de valuri.

Nu sunt aplicate calcule de iluminare în imaginea de mai sus.

Iluminare

Iluminarea scenei se va implementa folosind 3 tipuri de surse de lumină: punctiformă, direcțională și spotlight. Fiecare sursă de lumină (indiferent de tipul acesteia) o să aibă o culoare specifică și trebuie să se țină cont de această culoare pentru iluminare.

Lumina punctiformă: acest tip de sursă de lumină este cel prezentat la laborator. Este necesar să se folosească acest tip de lumină pentru:

  • Reflectorul farului (pe lângă lumina spotlight a acestuia) astfel încât să se ilumineze zonele din proximitatea farului
  • Fiecare bărcuță, astfel încât să se ilumineze aceasta și apa din jurul ei. Lumina va fi atașată de bărcuță și trebuie să aibă o culoare aleatorie

În următoarea imagine au fost activate numai luminile punctiforme:

Lumina direcțională: aceasta va ilumina toate obiectele din scenă cu aceeași intensitate. Specific luminii de tip direcțional este faptul că vectorul luminii incidente $L$ nu depinde de poziția luminii sau a fragmentului care trebuie iluminat (precum în cazul luminilor de tip point și spot). Așadar, pentru fiecare fragment, iluminarea va fi calculată folosind același vector $L$ (corespunzător direcției luminii). Astfel, pentru o sursă de lumină de tip direcțional este nevoie să se definească direcția acesteia și culoarea luminii emise. În cadrul acestei teme vom considera luna ca `sursa` acestei lumini direcționale, așadar, va trebui să setați direcția acestei lumini în mod corespunzător.

În următoarea imagine a fost activată numai lumina direcțională - observați iluminarea pe partea stângă a farului, corespunzătoare direcției cerute.

Lumina de tip spotlight: acest tip de sursă de lumină este cel prezentat la laborator. Este necesar să se folosească 2 surse de acest tip pentru far, poziționate în partea superioară a acestuia, care să se rotească în jurul farului în mod continuu. Între direcțiile celor 2 surse spotlight trebuie să fie un defazaj de 180°. De asemenea, luminile spotlight trebuie să fie colorate (detalii în secțiunea Interfața cu utilizatorul)

În următorul GIF puteți observa un exemplu de implementare pentru comportamentul acestor spotlight-uri.

Intensitatea luminlor punctiforme trebuie atenuată pe baza distanței, în schimb, intensitatea luminii direcționale nu trebuie atenuată. În mod excepțional pentru această temă puteți să nu atenuați pe baza distanței luminile de tip spot de la far - în mod normal acestea sunt atenuate - dar noi am optat pentru această variantă pentru a avea lumini spotlight cu un efect mai pronunțat.

Implementarea voastră trebuie să suporte randarea mai multor surse de lumină în același frame!

Mesh-ul reflector al farului

Mesh-ul reflector al farului nu trebuie iluminat - în schimb, acesta trebuie randat folosind numai componenta emisivă - efectul dorit este ca acest mesh să aibă aparența unei zone care emite lumină. Culoarea va fi setată corespunzător culorii luminilor implementate pe far (point și spotlight).

Mesh-ul lunii

Mesh-ul lunii trebuie texturat cu o imagine a lunii. Pentru a oferi o strălucire lunii este necesar ca randarea acesteia să includă și o componentă emisivă de culoare albă.

Interfața cu utilizatorul

Interfața cu utilizatorul constă în implementarea a 3 slider-e, ce au scopul de a controla culoarea luminilor emise de către far (point și spotlight), precum și culoarea mesh-ului reflector. Fiecare slider va controla contribuția unei componete de culoare (R, G, B), iar culoarea finală va fi calculată corespunzător acestor contribuții.

Construcție: Slider-ele pot fi construite din pătrate scalate. Este necesar ca fiecare slider să fie construit din 2 astfel de pătrate - unul pentru componenta statică a slider-ului (background-ul), celălalt pentru componenta interactivă (care se poate scala). Componenta interactivă trebuie colorată corespunzător canalului de culoare pe care o controlează.

Interacțiune: Aceasta se va realiza prin intermediul a 6 taste - pentru fiecare slider se vor folosi câte 2 taste, una pentru a crește valoarea contribuției, cealaltă pentru scăderea acesteia. Partea interactivă a slider-elor se va scala corespunzător valorii contribuției. Această interacțiune trebuie să aibă loc în fiecare frame în care tastele sunt ținute apăsate.

Pentru randarea slider-ului vă recomandăm următoarele (nu sunt cerințe impuse):

  • Folosirea unei camera cu proiecție ortografică - puteți folosi doar o singură cameră, randați întâi scena 3D folosind proiecția perspectivă, iar pentru slider-e o configurați folosind o proiecție ortografică
  • Implementarea unui shader auxiliar doar pentru randarea slider-elor

Barem

  • Scena 3D (45p)
    • Asamblare obiecte 3D (apă, insulă, far, lună, bărcuțe) (20p - 4p fiecare)
    • Texturare obiecte 3D (10p - 2p fiecare)
    • Comportament bărcuțe (15p)
      • Randare a minim 4 bărcuțe (5p)
      • Rotație bărcuțe (fiecare cu rază diferită) în jurul insulei (5p)
      • Orientarea corectă a bărcuțelor în funcție de traiectoria lor (5p)
  • Efecte shader apă (35p)
    • Repetare textură (5p)
    • Efect de mișcare al texturii apei (10p)
    • Efect de valuri (20p)
  • Iluminare (40p)
    • Lumină direcțională (10p)
    • Lumini punctiforme (15p)
      • Lumină far (5p)
      • Câte o lumină pentru fiecare bărcuță (10p)
    • Lumini de tip spot (15p)
      • Implementarea celor 2 lumini, cu originea în far (10p)
      • Rotația în mod continuu a acestora (5p)
  • Interfața cu utilizatorul (30p)
    • Randarea celor 3 slider-e (10p)
    • Interacțiunea cu slider-ele folosind tastele (10p)
    • Setarea culorii luminilor farului pe baza valorii slider-elor (10p)

Exemple de Funcționalități Bonus

  • Interacțiunea cu slider-ele folosind cursorul (exemplu în demo)
  • Introducerea unor bărcuțe “polițist” cu girofar
  • Modelarea valurilor 3D (vertex displacement)
  • Utilizarea unei traiectorii complexe pentru deplasarea bărcuțelor
  • Modelarea unor obstacole plutitoare
  • Selector de culoare sub formă circulară pe modelul HSV

Întrebări și răspunsuri

Pentru întrebări vom folosi forumurile de pe Moodle. Orice nu este menționat în temă este la latitudinea fiecărui student!

Notare

Baremul este orientativ. Fiecare asistent are o anumită libertate în evaluarea temelor (de exemplu, să dea punctaj parțial pentru implementarea incompletă a unei funcționalități sau să scadă pentru hard coding). Același lucru este valabil atât pentru funcționalitățile obligatorii, cât și pentru bonusuri.

Tema trebuie încărcată pe Moodle. Pentru a fi punctată, tema trebuie prezentată la laborator. Vor exista laboratoare speciale de prezentare a temelor (care vor fi anunțate).

Indicații suplimentare

Tema va fi implementată în OpenGL și C++. Este indicat să folosiți framework-ul și Visual Studio.

Pentru implementarea temei, în folderul src/lab_m1 puteți crea un nou folder, de exemplu Tema3, cu fișierele Tema3.cpp și Tema3.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ăsați click dreapta pe filtrul lab_m1 și selectați Add→New Filter. După ce creați un nou filtru, de exemplu Tema3, 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 adăugată și calea către header-ul temei. De exemplu: #include “lab_m1/Tema3/Tema3.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 ExplorerClean Solution
    • Ștergeți folderul /build/.vs (dacă nu îl vedeți, este posibil să fie ascuns)
  • Î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 î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.

egc/teme/2023/03.txt · Last modified: 2023/12/17 20:28 by andrei.lapusteanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0