Skip to content

Mi23154 - #6

Open
pobratime wants to merge 55 commits into
mainfrom
mi23154
Open

Mi23154#6
pobratime wants to merge 55 commits into
mainfrom
mi23154

Conversation

@pobratime

Copy link
Copy Markdown
Owner
Screenshot_20260804_154818

pobratime added 29 commits July 28, 2026 02:15
…ring model loading), Model changes yet to be made, RayTracing pipeline destroyed, BvhTree needs to be fixed
…es from files, after that we pass them to ThreadPool
- Updated .gitignore to exclude .zed files
- Commented out rendering calls in MainController and Scene to disable rendering temporarily
- Renamed and modified methods in RayTracingPipeline for better clarity and functionality
- Added position, rotation, and scale methods to RayTracingModel
- Changed BlasTree node structure for improved clarity
- Introduced TlasTree class for handling top-level acceleration structures
Comment thread app/resources/shaders/ray.glsl
Comment thread app/resources/shaders/ray.glsl Outdated
@pobratime

Copy link
Copy Markdown
Owner Author

@spaske00 Imam par pitanja vezanih za osvetlenje. Samo odgovorite na komentar da bi mi stiglo obavestenje kad budete mogli da odgovorite da Vas ne bi remetio.

@spaske00

spaske00 commented Aug 7, 2026

Copy link
Copy Markdown

slobodno pisite, ja cu videti i odgovoriti prvom prilikom

@pobratime

Copy link
Copy Markdown
Owner Author

@spaske00 Mislim da Vam nesto oko mejla nijie u redu, pokusao sam vise puta danas da Vam posaljem pitanja ali svaki mejl se vrati, drugi mejlovi prolaze.

@pobratime

pobratime commented Aug 7, 2026

Copy link
Copy Markdown
Owner Author

Malo veca nedoumica oko izvora svetla.

Naime plan i ideja je bila da imam neki model na sceni koji je lepo osvetljen, u smislu da svetli samo tamo gde je potrebno, ne ceo. Za to mi je potreban nekakav nacin da prepoznam da li je udaren primitiv izvor svetla ili ne. Ovo nije velika problematika treba samo dodati neki flag u GPUPrimitive. Medjutim ta informacija za scenu sama po sebi nije dovoljna jer kada udarimo u neki primitiv koji nije izvor svetla treba proveriti da li je ON osvetljen (treba proveriti i refleksivnost naravno i ispaliti shadow ray ali nije to tema). Znaci da mi lokalna informacija o tome da li je primitiv osvetljen, na nivou primitiva nije dovoljna i da prosto moram imati neku struktru / niz koji cuva informacije o izvorima svetla.

Ovo sam mislio da resim tako sto pokupim trouglove koji su susedni na nivou jednog modela i imaju emissive svojstvo, napravim AABB oko njih i izracunam centroid tog AABB. Kada se nesto sto nije Emissive na sceni (u_Textures[emissive_idx].rgb == (0.0.0)) ispaljuje se zrak ka centroidu AABB-a izvora svetla i ako pogodi AABB i nista izmedju model je osvetljen i pucamo nakon toga shadow ray. Ako mislite da postoji bolji pristup, recite pokusacu da implementiram.

Mislim da je ovaj pristup okej za scenu i da je neku ovakvu strukturu okej slati i kao niz i da nema potrebe da pravim posebno stablo za LightSources, jer ne planiram da bude vise od par izvora svetla.

Izvlacenje informacije o tome da li je primitiv emisivan ili ne mi je problem.

a) Jedan nacin na koji bi to mogao da odradim jeste da svaki put kad se model ucitava sacuvam emisivnu teksturu pogledam vrednost na koordinatama da li je >0 i tako filtriram primitve sa i bez izvora svetla, i kasnije odradim gore opisano. Ova ideja mi se uopste ne svidja ali ne vidim drugi nacin osim sledeceg.

b) Naime mogu uraditi to i tako sto pri ucitavanju modela, model koji se sastojoi od sub-modela i ima u nazivu "emissive" pokupim i obradim. Ovo je dosta laksi pristup ali zahteva da model koji ucitavam prethodno ucitam u blender i izmenim ime sub-modela koji je emisivan u npr. emissive-bulb, i to kasnije prepoznam preko imena mesha. Medjutim ovo se oslanja na to da model koji uvozim pre toga ima .blend format i da mogu promeniti deo koji mi je potreban. Ovo nije problem za potrebe moje scene, sve modele koje ucitavam su svakako prethodno .blend samo ih eksportujem, no kako je ovo deo engine mozda nije najlepsa praksa pa je bolje da vidim sa Vama.spdlog::info("Mesh name-> {}", mesh->mName.C_Str());
image

Primetio sam da se engine takodje ne ponasa najlepse kada model ima sub-modele. Nigde se ne dohvata node->mTransformation.

Nadam se da je pristup b) okej jer bi mi a) oduzeo mnogo vremena i jako je robusan.

Sto se tice tekstura, prosirio sam engine da podrzave jos neke tipove koji su mi potrebni, te lagano u shaderu za refleksije i emisivnost proveravamo samo vrednost u teksturi, i odlucujemo pucamo li novi zrak ili ne i sta radimo.

Teksture nazalost moram slati preko dva niza velicine 16. Bindless teksture ne postoje na asahi linuxu, a texture array zahteva da sve budu istog formata i velicine, sto je previse posla da se uredjuje svaki fajl zasebno. Mozda postoji neki drugi nacin koji preporucujete?

Takodje grupa A, FBO klasu sam napravio i odradicu bloom.
Grupa B sa druge strane su rasterske tehnike, pa sam mislio u dogovoru sa vama da na primer umesto SSAO odradim RTAO i proucim ga, ili ako dopustate mozda da bude odradjen PBR lightning, jer kad vec radim ray tracing ajde da probam da ucinim scenu sto realisticnijom.

@spaske00

@spaske00

spaske00 commented Aug 8, 2026

Copy link
Copy Markdown

Dodacu samo neka zapazanja, Vi slobodno odaberite pristupizmedju A ili B koji Vam se cini najbolji, oba su prihvatljiva.

Takodje, dole izneto su samo predlozi i sta mi se cini da bi bilo optimalno u ovom konkretnom slucaju.
Ne morate striktno, ili cak uopste, ispratiti predloge za maksimum bodova, procenite sta je najbolje.

Takodje, iz iznetih zapazanje ce te uociti da se svaki pristup moze dodatno otpakovati i imati nepokrivenih slucajeva i boljih resenja. Molim Vas, obratite paznju da cilj ovog konkretnog projekta nije da napravio klon Unreal Engine-a koji u svakoj mogucoj situaciji hendla sve moguce slucajeve, vec samo da na konkretnom zadatku provezbate sebe u implementaciji i razumevanju grafike. Shodno tome, ako zelite da implementirate sve ovo, nemam nista protiv, samo napred, ja cu Vam pomoci u svemu; samo imajte na umu i da u nekom trenutku treba ograniciti skup funkcionalnosti i podrzanih slucajeva kako bi se projekat kompletirao. :)

Ako sam nesto propustio da odgovorim, slobodno pisite.

Pristup A

Nema potrebe da se proverava emisivna tekstura po trouglu prilikom učitavanja.
Bolja reprezentacija je da se emisivnost izvodi iz materijala:

struct GPUPrimitive {
...
uint32_t materialIndex;
bool emissive;
};

ili, još bolje, da se informacije ne bi duplirale:

struct GPUMaterial {
...
int emissiveTextureIndex;
glm::vec3 emissiveFactor;
};

Zatim:

bool isEmissive(GPUMaterial material)
{
return material.emissiveTextureIndex >= 0 &&
dot(texture(u_Textures[material.emissiveTextureIndex], uv).rgb,
vec3(1.0)) > 0.0;
}

E sad, tekstura moze da varira unutar jednog trougla. Zbog toga primitiva ne moze uvek jednostavno da se klasifikuje kao emisivna/neemisivna na osnovu svog materijala. Trougao moze imati emisivnu teksturu sa samo malim emisivnim regionom, ali to vec prevazilazi opseg projekta. Slobodno mozete staviti da je svojstvo materijala.

struct GPUMaterial
{
int albedoTexture;
int normalTexture;
int roughnessTexture;
int metallicTexture;
int emissiveTexture;

glm::vec3 emissiveFactor;
};

Dakle, primitiva koja koristi materijal sa pozitivnom emisijom je emisivna.

Pristup B

Nije bas najsrecnije resenje sa inzinjerske strane, ali moze da radi uz male modifikacije.

Korišćenje Blender konvencije imenovanja kao što je:
Lamp
Lamp_emissive
Bulb_emissive

je sasvim ok kao konvencija asset pipeline-a za Vas projekat.

Međutim, ja bih tu konvenciju prilikom učitavanja pretvorio u eksplicitne podatke engine-a:

if (mesh->mName.C_Str() contains "_emissive")
{
    material.emissive = true;
}

Nakon učitavanja, renderer više ne bi trebalo da zavisi od konvencije.

Još bolje, ako vec imate pristup Blender assetima, slobodno nakacite emisioni materijal u Blenderu omoguciti asimpu da ga ucita da bi se koristila semantika materijala, a ne konvencija.

Izvor svetla

Nije potrebna posebna struktura za ubrzavanje ako postoji samo nekoliko izvora svetla.

Na primer:

struct GPULightSource
{
    AABB bounds;
    glm::vec3 centroid;
};

i:

std::vector<GPULightSource> lightSources;

mogu da se pošalju kao SSBO.

Samo bih vodio racuna prilikom koriscenja centroid AABB-a kao stvarnu poziciju izvora svetla.

Centroid može biti prilično udaljen od stvarne emisivne površine, naročito kod tankog ili konkavnog izvora svetla.

Na primer, kod pravougaonog izvora, centroid AABB ce biti ispravan, ali za neki nepravilni oblik nece.
Ukoliko nemate taj slucaj, onda ignorisite, ali samo nesto o cemu treba voditi racuna :)

Ako bas zelite do kraja da ga ispeglate, onda bi sacuvao ovako nesto

struct GPULightSource
{
    AABB bounds;
    glm::vec3 position; // reprezentativna tačka
};

gde je position centroid emisivnih trouglova, a ne centroid AABB-a.

Opet, bilo bi poželjno da se uzorkuje tačka na površini izvora svetla, umesto da se uvek cilja jedna reprezentativna tačka. Ali za ovaj projekat reprezentativna tačka je sasvim dovoljna.

Ako postoji samo nekoliko izvora svetla, algoritam može biti znatno jednostavniji:

hit = tracePrimaryRay()

if hit.isEmissive:
    return hit.emission

radiance = 0

for each light in lightSources:
    lightPoint = sampleLight(light)

    shadowRay = createRay(hit.position, lightPoint)

    if isVisible(shadowRay, lightPoint):
        radiance += calculateDirectLighting(hit, lightPoint)

return radiance

Takodje

Ako pogodi AABB i između nema ničega, model je osvetljen

je malo problematična. AABB samo govori da zrak ulazi u okvirnu zapreminu objekta, ali ne i da zaista dolazi do emisivne geometrije.

Na kraju je ipak potrebna provera vidljivosti prema stvarnoj geometriji izvora svetla.

Pogodak primitive

kada pogodimo primitivu koja nije izvor svetla, treba proveriti da li je osvetljena

Ja bih ovo drugačije formulisao u rendereru.
Osvetljenost je svojstvo trenutnog pogotka zraka, a ne generalno svojstvo primitiva.

Isti trougao može biti:

  • osvetljen iz jedne tačke,
  • u senci iz druge tačke,
  • osvetljen od strane jednog izvora svetla,
  • u senci u odnosu na drugi izvor svetla.

Zbog toga je:

primitive.isIlluminated

generalno pogrešna apstrakcija.

Umesto toga, zgodnije bi bilo Pogodak ima:

  • primitive/material
  • position
  • normal

a zatim shader/path tracer izračunava:

radiance_at_hit =
    emission
    + direct_lighting
    + reflected_radiance

Submodeli

Engine trenutno ignorise podpodele, slobodno dodajte funkcionalnost ako Vam je potrebna :)

Teksture u GLSL-u

Slobodno mozete:

sampler2D textures[16];
sampler2D emissiveTextures[16];

Samo napravite eksplicitno indeksiranje

struct GPUMaterial
{
    int albedoTexture;
    int normalTexture;
    int roughnessTexture;
    int metallicTexture;
    int emissiveTexture;
};

RTAO vs PBR

Odabrao bih RTAO za ovaj projekat.

@pobratime

Copy link
Copy Markdown
Owner Author

@spaske00
Pre svega hvala na detaljnom odgovoru.

Sto se tice komentara sa kojim ste zapoceli odgovor, u potpunosti ste u pravu, nije tema projekta napraviti klon Unreal Engine-a. Svestan sam toga no elem to vuce ono sto sam jos u prvom mejl pisao, cista nezasitost onim sto napravim. Imao sam 2 forka pre ovoga koja sam u potpunosti obrisao. Jedan je radio ray marching, te sam mogao da prikazem matematicke figure => ne svidja mi se ovo ocu modele, nakon toga napravim modele => fps je nizak, ocu da bude brze => implementiram blas, mogu samo jedan model => ne moze to tako ocu tlas => sad nemam teksture treba mi i to itd. itd. i tako se moze ici u nedogled. Ali potpuno ste u pravu u jednom trenutku treba reci dosta i zaokruziti stvari.

Trenutno se unutar GPUPrimitive cuvaju dva glm::vec4 sa indeksima ka teksturama, Vas pristpu sa MaterialID je mnogo elegantiniji. Medjutim, i dalje ne vidim kako doci do toga koji deo modela je emisivan, kako bi mogo imati podatak o lokaciji izvora svetla u prvu ruku, odatle i moja logika za citanje sirovih podataka teksture, i sam razlog o razmisljaju pristupa B. Naime mozda se opet negde lose izrzim bolje kroz primer, ako imamo model dart vejdera koji ima emisivan lajt sejber, nema smisla da lokacija izvora svetla bude sam centar modela dart vejdera, treba da lokacija izvora svetla bude sam lajt sejber i osvetli dart vejdera, ne obrnutno. Nikada problem nije bio gledanje da li je emisivan primitiv, to je najlogicnije raditi u sejderu, necemo da hardkodujemo stvari, vec kako prepoznati i izracunati deo modela koji je izvor svetla. Verovatno sam se ja jako lose izrazio te ste zato i ispisali podsekciju o pogodku primitive, nisam mislio da ista hardkodujem, izgled scene zavisi od trenutnog stanja scene, ne od podataka koje imam sa C++ strane, tekstura i slicnih stvari. Problem citav jeste racunanje lokacije izvora svetla. Tj. kako da u strukturi
struct GPULightSource { AABB bounds; glm::vec3 position; // reprezentativna tačka };
dodjem do te reprezentativne tacke, ili u centroid slucaju, kako doci do centroida.

Ostali saveti su sve top, primenicu. To sto ste rekli da mogu da odradim ono da bi ispeglao do kraja, odradicu to. Kad sam vec uzeo ovoliko da zagrizem i krenuo da radim sve ovo nije okej da sad pred kraj odustanem :).

@spaske00

spaske00 commented Aug 8, 2026

Copy link
Copy Markdown

Nekako ovako bi izgledalo:

CPU / ucitavanje modela

Neki tok podataka bi bio

Model
  |
Meshes + materijali
  |
Identifikovanje emisivnih primitiva
  |
Za svaku emissivnu primitivu:
    transformisi vertekse u world space
    izracunati povrsine trouglova i centroid
    AABB
  |
GPU LightSource[]
struct GPULightSource {
    glm::vec3 position;
    AABB bounds;
};

Ovo saljemo kao SSBO.

GLSL GPU

Shader dobija:

struct GPULightSource {
    vec3 position;
    AABB bounds;
};

layout(std430, binding = ...) buffer LightSources {
    GPULightSource lights[];
};

uniform int u_LightCount;

Postojeći podaci o primitivima/materijalima odreduju materijal u tacki pogotka zraka, dalje algoritam je:

  1. ray
  2. BVH traversal
  3. presek sa trouglom
  4. GPUPrimitive
  5. MaterialID
  6. material/textures

Na mestu pogotka:

Hit hit = traceRay(ray);

if (hit.material.isEmissive)
    return evaluateEmission(hit);

ako je promasaja ide standardno ostatak algoritma.

Neka podela posla bi bila da CPU obavlja ekstrakciju izvora svetlosti, dok GLSL obavlja transport svetlosti/shading.

Opet, ovo je sve ugrubo, da Vam da skicu, nije jedini pristup i slobodno prilagodite za potrebe Vaseg projekta. Takodje, ne mora da bude idealno, i ne mora da bude savrseno efikasno.
Bice dobro prvo da radi, kasnije se moze optimizovati.

@pobratime

Copy link
Copy Markdown
Owner Author

Nekako ovako bi izgledalo:

CPU / ucitavanje modela

Neki tok podataka bi bio

Model
  |
Meshes + materijali
  |
Identifikovanje emisivnih primitiva
  |
Za svaku emissivnu primitivu:
    transformisi vertekse u world space
    izracunati povrsine trouglova i centroid
    AABB
  |
GPU LightSource[]
struct GPULightSource {
    glm::vec3 position;
    AABB bounds;
};

Ovo saljemo kao SSBO.

GLSL GPU

Shader dobija:

struct GPULightSource {
    vec3 position;
    AABB bounds;
};

layout(std430, binding = ...) buffer LightSources {
    GPULightSource lights[];
};

uniform int u_LightCount;

Postojeći podaci o primitivima/materijalima odreduju materijal u tacki pogotka zraka, dalje algoritam je:

1. ray

2. BVH traversal

3. presek sa trouglom

4. GPUPrimitive

5. MaterialID

6. material/textures

Na mestu pogotka:

Hit hit = traceRay(ray);

if (hit.material.isEmissive)
    return evaluateEmission(hit);

ako je promasaja ide standardno ostatak algoritma.

Neka podela posla bi bila da CPU obavlja ekstrakciju izvora svetlosti, dok GLSL obavlja transport svetlosti/shading.

Opet, ovo je sve ugrubo, da Vam da skicu, nije jedini pristup i slobodno prilagodite za potrebe Vaseg projekta. Takodje, ne mora da bude idealno, i ne mora da bude savrseno efikasno. Bice dobro prvo da radi, kasnije se moze optimizovati.

@spaske00 Mislim da se opet nismo razumeli, vec Vam previse vremena oduzimam. Sve sto ste opisali je nesto sto nije problem uz malo logike srediti i napraviti kako treba uraditi ovaj pipeline slanja podataka, i u pocetnom pitanju je kod mene isti stvar problem.

Model
  |
Meshes + materijali
  |
Identifikovanje emisivnih primitiva // <- Ovo ovde
  |
Za svaku emissivnu primitivu:
    transformisi vertekse u world space
    izracunati povrsine trouglova i centroid
    AABB
  |
GPU LightSource[]

Problem je identifikacije emisivnih primitiva na C++ strani. Kada model ima teksturu emisiv onda je npr 80% crna i 20% neka druga boja. Kada u sejderu pogodimo zrak to je lako procitati. Ali mi nekakav ovakav podatak moramo i sa C++ strane srediti, da bi izracunali mesto izvora svetla.

industrial_pipe_lamp_emission_1k

Nije problem slanje, kreiranje ili ucitavanje. Problem je pre kreiranja treba izdvojiti primitive koji su emisivni. Kako izdvojiti primitive koji su emisivni?

@spaske00

spaske00 commented Aug 8, 2026

Copy link
Copy Markdown

@pobratime

Mislim da se opet nismo razumeli, vec Vam previse vremena oduzimam.

Taman posla, sve pet, razjasnicemo, vrv sam i ja nesto pogresno razumeo :)

Problem je pre kreiranja treba izdvojiti primitive koji su emisivni. Kako izdvojiti primitive koji su emisivni?

Aha, na osnovu materijala, zar ne? Mozete uvesti ogranicenje da je primitiva emisivna ako ima prikljucen emisivni materijal.
Ako imate problema jer je submodel, slobodno izdvojite emisivni deo kao zaseban model, ne mora biti lampa, mozete napraviti obicnu sferu/kocku koja je cela emisivna i samo nju importaovati kao izvor svetlosti. Neka visi u vazduhu, sto da ne. Tako cete uprostiti identifikovanje emisivnih primitiva i ucitavanje modela a opet dobiti RT.
Slobodno recite ako neki deo nije najjasniji ili sam promasio pitanje 😅

@pobratime

Copy link
Copy Markdown
Owner Author

@spaske00
Verovatno se ja ne izrazavam najlepse sta pokusavam da postignem i sta nije kako treba.
Ajde da kazemo da pokusavam da ucitam lampu jer taj model imam trenuno dostupan da ne bi trazio novi.

GLSL

GPUPrimtive iz BlasTree u sebi ima dva vec4 (promenicu na materialId kao sto se predlozilii) koji u sebi cuvaju indekse ka:

enum class TextureType {
    Regular,
    Diffuse,
    Specular,
    Normal,
    Height,
    Emissive,
    Metalness,
    DiffuseRoughness,
    AmbientOcclusion
};

A sve teksture se cuvaju u

uniform sampler2D u_Textures[16];

Moguce je da mi ne trebaju sve teksture izbacicu ono sto mi ne treba, ali svakako ne smeta funkcionalnosti.
One se kasnije koriste unutar .glsl fajla na sledeci nacin

vec3 texture_primitive(GPUPrimitive tri, GPUInstance inst) {
    int diff_idx = int(tri.t_idx.x);
    int spec_idx = int(tri.t_idx.y);
    int norm_idx = int(tri.t_idx.z);
    int high_idx = int(tri.t_idx.w);

    float u = primitive_hit.uv.x;
    float v = primitive_hit.uv.y;
    float w = 1.0f - u - v;

    vec2 interpolated_uv = w * tri.uv0.xy + u * tri.uv1.xy + v * tri.uv2.xy;

    vec3 diff_color = (diff_idx != -1) ? textureLod(u_Textures[diff_idx], interpolated_uv, 0.0).rgb : vec3(1.0f);
    vec3 norm_color = (norm_idx != -1) ? textureLod(u_Textures[norm_idx], interpolated_uv, 0.0).rgb : vec3(0.5, 0.5, 1.0);
    float spec_color = (spec_idx != -1) ? textureLod(u_Textures[spec_idx], interpolated_uv, 0.0).r : 0.2f;

    return diff_color;
}

textureLod se koristi zarad kvaliteta, imao sam grube linije na modelima ovo ih je resilo. Ova funkcija je i dalje jako hardkodovana i nije gotova ali sluzi da dobijete osnovnu ideju i prikaze model na sceni, nista specijalno.
Kada se proslede ostal materijali za nas model jednostavno mozemo gledati sta radimo sa zrakom. Metalness == 0 -> mat boja nema refleksije, Metalness > 0 -> ima refleksije reflektuj zrak odradi miks, Emissive > 0 -> izvor svetlosti samo ga oboj itd. itd. itd. da ne navodim sve slucajeve znate bolje od mene sta se sve desava.
Unutar sejdera nemamo problem sa slanjem tekstura, prepoznavanjem STA JE pogodjen primitiv i sta treba radti sa njiim.
Ako pogodimo primitiv koji nije izvor svetla treba iz njega ispaliti zrak zrak_vec = world_hit_cord - light_src_cord i ispitati sta se desava sa njim. Implementacija ovoga moze se odraditi na vise nacina, moze se lepo optimizovati, path tracing, raditi neki jednostavan algoritam i sl. No elem da bi ispalili zrak koji ima vektor zrak_vec = world_hit_cord - light_src_cord, mi jelde moramo znati light_src_cord. Sve u svemu, mi moramo poslati nekakav SSBO koji u sebi ima strukturu koja ima podatke o povrsini dela koji je emisivan (ili AABB ili bilo koji nacin koji odaberemo svejedno je kontekst je isti), lokaciju ovoga, tj light_src_cord, i int koji nam govori unutar kog modela je ovaj light source, u ondnosu na GPUInstance.
GLSL deo sve kul. :)

Obrada podataka C++

Okej znaci ajde da napravimo neku klasu, strukturu uz par f-ja, bilo kakav pristup da oformimo nesto ovako. Za ovo su nam potrebni sirovi podaci pri ucitavanju. Nikakav problem imamo pristup njima. Uzmemo podatke, umemo da ih obradimo. Primitivi se pokupe, izracuna se centroid svakog, globalni centroid, poveze se sa GPUInstance da bi imao pristup zbog

    struct GPUInstance {
        glm::mat4 world_to_local; // ZBOG OVOGA
        glm::mat4 local_to_world; // ZBOG OVOGA
        uint32_t blas_root_index;
        uint32_t material_index;// TODO change later <- apsolutni visak treba da se pretvori u pad
        uint32_t pad0;
        uint32_t pad1;
    };

world_to_local local_to_world, jer iako je emitvan deo poseban i saljemo nesto zaesbno za njega, on je i dalje deo istog modela i za njega vaze ista pravila kao sto vaze i za ostatak modela, ne zelimo da se moddel razdvoji. A i treba nam da bi mogli da prolazimo kroz tlas i proverimo da li je hitId modela koji je hitovan i id modela kojeg je izvor svetla deo isti. Znaci umemo da naravimo ovo.
Obrada podataka i povezivanje, sve kul. :)

Ucitavanje i izdvajanje podataka C++

Znaci mi nekako moramo umeti da prepoznamo koji delovi modela su emisivni. Ovo moramo raditi pri ucitavanju, jer tada imamo pristup "raw" podacima koji nam trebaju. Ajde da se vratimo na pocetnu pp. da ucitavamo lampu, da se sastoji iz sijalice, tela i glave. Sijalica, telo, glava i dalje dele isi .gltf fajl, dele iste teksture (u smisli da je u istom .jpg fajlu za npr. difuzunivnu teksturu cela lampa, nije odvojeno kao sto je slucaj sa nekim drugim modelima, ali je i dalje lampa sastavljena od sub-modela sub-mesheva).
Kako probrati sijalicu:

OPCIJA 1:

void AssimpSceneProcessor::process_node(const aiNode *node) {
    for (uint32_t i = 0; i < node->mNumMeshes; ++i) {
        auto mesh = m_scene->mMeshes[node->mMeshes[i]];
        process_mesh(mesh);
    }
    for (uint32_t i = 0; i < node->mNumChildren; ++i) {
        process_node(node->mChildren[i]);
    }
}

Imamo ovu funkciju. Sijalica je poseban deo modela lampe, Okej ajde da odradimo nesto sa, mesh->mName. Ovo se oslanja kao sto sam u prethodnim komentarima reko na jako grubu pretpostavku da su u blenderu lepo imenovane stvari i da ih mi mozemo menjati. Ali ovo resenje daje jako lep rezultat, imamo logicku strukturu koja je lepo formirana, izracunamo sve sto nam treba tako sto posaljemo u process_mesh flag da je ovo emisivno, appendujemo u nekakv niz gde cuvamo podatke emisivnih delova koje treba obraditi.

OPCIJA 2:

// FIXED sub-mesh loading
void AssimpSceneProcessor::process_mesh(aiMesh *mesh) {
    std::vector<Vertex> vertices;
    vertices.reserve(mesh->mNumVertices);
    for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
        vertices.push_back(extract_vertex(mesh, i));
    }
    const std::vector<uint32_t> indices = extract_indices(mesh);

    const auto material = m_scene->mMaterials[mesh->mMaterialIndex];
    std::vector<Texture *> textures = process_materials(material);

    if (m_loading_model_rt) {
        // ovo promeniti koristiti materialId kao sto je marko preporucio a unutar materialId staviti indekse ovih stvar
        glm::vec4 tex_indices_a{-1.0f};
        glm::vec4 tex_indices_b{-1.0f};
        for (const auto &tex: textures) {
            if (!tex) continue;
            switch (tex->type()) {
                case TextureType::Diffuse: tex_indices_a.x = static_cast<float>(tex->index()); break;
                case TextureType::Specular: tex_indices_a.y = static_cast<float>(tex->index()); break;
                case TextureType::Normal: tex_indices_a.z = static_cast<float>(tex->index()); break;
                case TextureType::Height: tex_indices_a.w = static_cast<float>(tex->index()); break;
                case TextureType::Emissive: tex_indices_b.x = static_cast<float>(tex->index()); break;
                case TextureType::Metalness: tex_indices_b.y = static_cast<float>(tex->index()); break;
                case TextureType::DiffuseRoughness: tex_indices_b.z = static_cast<float>(tex->index()); break;
                case TextureType::AmbientOcclusion: tex_indices_b.w = static_cast<float>(tex->index()); break;
                default: break;
            }
        }
        const size_t num_triangles = indices.size() / 3;
        for (size_t i = 0; i < num_triangles; ++i) {
            m_rwg.texture_indexes.push_back(tex_indices_a);
            m_rwg.texture_indexes.push_back(tex_indices_b);
        }
        const auto base_index = static_cast<uint32_t>(m_rwg.vertices.size());
        for (const uint32_t idx: indices) {
            m_rwg.indices.push_back(base_index + idx);
        }
        m_rwg.vertices.insert(m_rwg.vertices.end(), vertices.begin(), vertices.end());
    } else {
        m_meshes.emplace_back(Mesh(vertices, indices, std::move(textures)));
    }
}

(Ovde treba promeniti ovo sa dva vec4 bas je ruzno zanemarite.) Okej ajde da uzmemo da pristupimo tokom samog ucitavanja mesha sirovim podacima teksture, tako sto cemo za zasebne piksele proveravati da li su emisini ili ne, da li je vrednost vreca od 0 ili 0.

Nadam se da sam se sada lepo izrazio. Pitanje je kako unutar modela koji u sebi ima deo koje je izvor svetla izvuci samo primitive koji su izvor svetla. Nije problem njihovo cuvanje, obrada i slanje, vec kako ih pronaci. Nadam se da sam Vam sad lepse opisao.

@pobratime

Copy link
Copy Markdown
Owner Author

Preimenovacu nazive meshova i podmodela u blenderu, smislio sam ideju kako bi moglo da funkcionise 2. pristup ali previse izmena zahteva i trebala bi mi zasebna klasa za procesuiranje ovih stvari. Nije najlepsa praksa kao sto smo rekli da engine zavisi od naziva modela ali valjda mozemo reci da je "okej" za potrebe projekta.

@pobratime

Copy link
Copy Markdown
Owner Author

@spaske00 Trebalo bi da je projekat zaokruzen manje vise, to je ta struktura. Dodato je jos par modela i neke izmene su napravljene. Ako zelite da pulujete projekat da pogledate da li sve izgleda okej, mogu vam proslediti link do modela ili ih samo skloniti iz .gitignore. Ako imate neke zamerke, skrenite mi paznju da bi ih ispravio sto pre. Kod mene na laptopu se projekat ne pokrece najlepse, dosta secka i ima 5-15 fpsa, na kompjuteru je dosta stabilnije, da znate samo unapred ako budete hteli da pokrecete.

@spaske00

Copy link
Copy Markdown

@pobratime dodajte molim Vas i modele da bih mogao kod mene pokrenuti

@pobratime

Copy link
Copy Markdown
Owner Author

@spaske00 Odradjeno. Mozete pogledati.

@spaske00

Copy link
Copy Markdown

Top, sve radi!

Projekat je fenomenalan, stvarno ste se potrudili! Sve cestitke od mene za trud i rad!

Nadam se da Vam je bilo zanimljivo. Na sutrasnjem poslu u industriji iteracija na nekom zadatku
koji dobijete se ne razlikuje u mnogome od ovoga sto ste sada prosli.

Dakle:

  1. U oblasti kojom se bavite (ovom slucaju je bila grafika), dodjete na projekat koji je uveliko u razvoju (matf-rg-project-2024)
  2. Dobijete zadatak da projekat nadogradite (ray tracing, senke)
  3. Vi onda izucavajuci zadatak ucite kako radi i kako da uklopite implementaciju u vec postojeci projekat
  4. Negde zapnete, nesto ne radi, nesto radi...pitate starije kolege, oni Vas upute ali ne resavaju problem umesto Vas
  5. Vi onda ponovo trazite, implementirate, dobijate komentare na rad, ispravljate i tako dok se ne iskonvergira ka nekome resenju

Jedino sto bi mozda PR-ovi bili manji, ali sve u svemu ovo je opsta slika.

Eto, to je sutra manje vise ono sto Vas ceka na poslu :)

Samo prijavite projekat preko stranice, odbranu cemo zakazati pred ispitni rok.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants