9
Kolegij Računalna grafika, 2018/19, Student: Vedran Ivanušid, 0036477033 Dokumentacija za 1. Laboratorijsku vježbu: Pradenje putanje Učitavanje tijela Učitani model čuva se u objektu tipa DrawableObject, a objekt se učitava funkcijom loadOBJ koja je deklarirana u obj_loader.h, a definira se u utils.cpp. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class DrawableObject{ public: DrawableObject(std::vector<glm::vec3> vert, std::vector<Face> fc); void draw(); void rotate(glm::mat3 rot); void translate(glm::vec3 v); glm::vec3 center; private: std::vector<glm::vec3> vertices; std::vector<glm::vec3> vertices_original; std::vector<Face> faces; }; 1.1 Aproksimacijska uniformna B-splajn krivulja - Učitava se u metodi ucitajBspline(spline_path); Metoda ucitajBspline obrađuje segment po segment krivulje (segment se sastoji od četiri točke), a i-ti segment krivulje parametar t se računa kao k/100, gdje je k cijeli broj [0-100]. Za i-ti segment i j-tu točku segmenta računa se pozicija, prva i druga derivacija. Opdenito, ako segment aproksimacijske B-splajn krivulje ima k točaka, a postoji N segmenata, onda imamo N*k točaka krivulje koje se u programu čuvaju u globalno definiranom vektoru splineB. Takđer, prilikom učitavanja, odmah računamo i prve i druge derivacije u točki. One se čuvaju u vektorima tanB, dtanB. Metode koje računaju poziciju, prvu i drugu derivaciju redom: pozicija, tangenta, derivacija2 1.4 Rotacija objekta Za rotaciju objekta koriste se četiri parametra: os rotacije(3 parametra) i kut rotacije. 3 parametra x,y,z osi rotacije dobijemo kao vektorski umnožak početne osi rotacije( u smjeru z -osi 0,0,1) i željene osi rotacije koja se dobije kao vektor tangente u trenutnoj točki.

Kolegij Računalna grafika, 2018/19 Student: Vedran

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Kolegij Računalna grafika, 2018/19 Student: Vedran

Kolegij Računalna grafika, 2018/19, Student: Vedran Ivanušid, 0036477033

Dokumentacija za 1. Laboratorijsku vježbu: Pradenje putanje

Učitavanje tijela

Učitani model čuva se u objektu tipa DrawableObject, a objekt se učitava funkcijom loadOBJ koja je

deklarirana u obj_loader.h, a definira se u utils.cpp.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

class DrawableObject{

public:

DrawableObject(std::vector<glm::vec3> vert, std::vector<Face> fc);

void draw();

void rotate(glm::mat3 rot);

void translate(glm::vec3 v);

glm::vec3 center;

private:

std::vector<glm::vec3> vertices;

std::vector<glm::vec3> vertices_original;

std::vector<Face> faces;

};

1.1 Aproksimacijska uniformna B-splajn krivulja

- Učitava se u metodi ucitajBspline(spline_path);

Metoda ucitajBspline obrađuje segment po segment krivulje (segment se sastoji od četiri točke),

a i-ti segment krivulje parametar t se računa kao k/100, gdje je k cijeli broj [0-100].

Za i-ti segment i j-tu točku segmenta računa se pozicija, prva i druga derivacija. Opdenito, ako

segment aproksimacijske B-splajn krivulje ima k točaka, a postoji N segmenata, onda imamo N*k

točaka krivulje koje se u programu čuvaju u globalno definiranom vektoru splineB. Takđer,

prilikom učitavanja, odmah računamo i prve i druge derivacije u točki. One se čuvaju u vektorima

tanB, dtanB.

Metode koje računaju poziciju, prvu i drugu derivaciju redom: pozicija, tangenta, derivacija2

1.4 Rotacija objekta

Za rotaciju objekta koriste se četiri parametra: os rotacije(3 parametra) i kut rotacije.

3 parametra x,y,z osi rotacije dobijemo kao vektorski umnožak početne osi rotacije( u smjeru z-osi

0,0,1) i željene osi rotacije koja se dobije kao vektor tangente u trenutnoj točki.

Page 2: Kolegij Računalna grafika, 2018/19 Student: Vedran

Kosinus kuta rotacije dobijemo iz skalarnog umnoška početnog vektora rotacije s i konačnog vektora

rotacije, e, koji još podijelimo s njihovim normama.

cos𝜑 =𝑠𝑒

𝑠 |𝑒|

Dodatno, potrebno je pretvoriti kut rotacije iz radijana u stupnjeve.

glm::vec3 os = glm::cross(s, e); float se = glm::dot(s, e); float aps_s = sqrt(pow(s.x, 2) + pow(s.y, 2) + pow(s.z, 2)); float aps_e = sqrt(pow(e.x, 2) + pow(e.y, 2) + pow(e.z, 2)); float fi_rad = acos(se / (aps_s * aps_e)); float fi_stup = (fi_rad / (2 * N_PI)) * 360.0f;

Pomak objekta na krivulji radi se tako da se za svaku točku bSpline-a, ovdje k-tu točku:

1. Objekt pomakne u ishodište glTranslatef(splineB[k].x, splineB[k].y, splineB[k].z);

2. Objekt se rotira u pozitivnoj smjeru sa glRotatef(fi_stup, os.x, os.y, os.z)

oko osi rotacije

3. Objekt se vrati nazad na poziciju glTranslatef(-obj_to_draw->center.x, -

obj_to_draw->center.y, -obj_to_draw->center.z)

4. Objekt se iscrta sa obj_to_draw->draw()

Slika: Wireframe avion polijede po B-spline krivulji. Iscrtane su koordinatne osi. Na slici desno vide se

tangente u nekoliko točaka na krivulji.

Namještanje putanje do objekta i spline-a:

- Direktorij s modelima: /models

- Direktorij s putanjama: /splines

char* model_path = "../Zadatak1/models/aircraft747.obj"; char* spline_path = "../Zadatak1/splines/bspline_runway.txt";

Page 3: Kolegij Računalna grafika, 2018/19 Student: Vedran

Dokumentacija za 2. Laboratorijsku vježbu

2.1 Definicija čestice / Particle.h

Čestica je definirana kao c++ struct sa atributima početna pozicija, brzina, akceleracija, trenutna

pozicija, brzina, akceleracija, sila, boja, veličina, starost, životni vijek i zastavica koja označava da li je

čestica živa, tj. kažemo da je čestica živa ako (p_age < p_lifeSpan).

Metoda update čestice ažurira njenu poziciju i brzinu. Nakon svakog poziva particle::update za neku

česticu, starost te čestice se povedava za neki fiksni prethodno zadani vremenski interval (fTimeStep).

void Particle::update(float fTimeStep) { p_age += fTimeStep; p_velocity += p_acceleration; p_position = p_init_position + p_init_velocity * p_age + 0.5f * p_init_acc* glm::pow(p_age, 2); return; }

ParticleSystem

Sustav čestica( ParticleSystem.h i ParticleSystem.cpp). Ova klasa ima pokazivač na primjerak klasa

ParticleEmitter i ParticleBuffer, gdje je ParticleBuffer definira tip podatka kao vektor unique

pokazivača na objekte tipa Particle (std::vector<std::unique_ptr<Particle>>). Ova definicija

može se pronadi u Particle.h.

Ukoliko želimo npr. koristiti sferni emiter, sve što je potrebno je naslijediti klasu ParticleEmitter i

definirati novi emiter. Prilikom inicijalizacije sustava čestice predati pokazivač na takav sferni emiter.

Klasa particle system obavlja i druge 'kudanske poslove' kao što su stvaranje čestica, inicijalizacija

čestica: u metodi ParticleSystem::InitializeParticles() se zove metoda

ParticleEmitter::EmitParticle(Particle& particle) koja prima referencu na česticu i modificira inicijalno

njenu poziciju,brzinu; ParticleSystem ažurira sve čestice nakon nekog vremenskog intervala u metodi

ParticleSystem::Update(float fTimeStep).

Detaljnjiji opis glavnih metoda slijedi.

ParticleSystem::Initialize()

- Zove metodu CreateParticles, koja stvara potreban broj čestica (alocira memoriju) i stvara

pokazivače na stvorene objekte tipa Particle.

- Zove InitializeParticles() -> svakoj čestici daje se početni položaj, brzina, akceleracija kroz

metodu EmitParticle() odgovoarajudeg emitera.

- Stvara VAO, VBO, EBO buffer objekte koji de se koristiti. Pozivom metode BindBuffers() vežu

se bufferi ovog ParticleSystema na odgovarajude targete.

- Puni GL_ARRAY_BUFFER i GL_ELEMENT_ARRAY_BUFFER spremnike, za prvi se postavlja

GL_DYNAMIC_DRAW kao flag, jer se podaci često mjenjaju

- Postavlja pokazivače za VBO (linija 116-140)

Page 4: Kolegij Računalna grafika, 2018/19 Student: Vedran

ParticleSystem::makeVertexBuffer()

- u ovoj metodi pripremaju se podaci koji de se spremati u GL_ARRAY_BUFFER

- računa se orijentacija Billboard čestica (tako da su uvijek prema promatraču)

- Za svaku česticu: računa se os rotacije kao vektorski produkt početne orijentacije s (uvijek u

smjeru –z osi ) i vektora između kamere i trenutne pozicije čestice - e. Potom se računa

kosinus kuta rotacije iz skalarnog produkta vektora (s, e). Konačno, za svaku česticu računa se

matrica rotacije, za izračunati kut, oko dobivene osi rotacije.

- Računaju se pozicije 4 točke poligona na koji de se primjeniti tekstura iz: pozicije čestice,

matrice rotacije R, relativnog položaja točke s obzirom na centar čestice, npr. donji lijevi rub

poligona ,x=-0.5f, y=-0.05f: glm::vec3 tmp1 = p->p_position + glm::vec3(R * ((-X - Y)));

- Na ovaj način stvorit de se ukupno N * 4 * 8 = N * 32 atributa za N čestica (3 za poziciju, 3 za

boju, 2 za koordinatu teksture) i sve se množi s 4 jer imamo 4 rubne točke poligona.

- Ova metoda modificira član objekta VertexBuffer, svaki put kad želimo raditi promjene

čestica. Treba napomenuti da se memorijski prostor nikad više ne mjenja tokom života

jednog sustava čestica (Kad se čestica rodi, iskoristi se memorijski element neke umrle

čestice).

Slika: dijagram klasa i struktura

Page 5: Kolegij Računalna grafika, 2018/19 Student: Vedran

Slika: Efekt vatrometa s dva sustava emitera čestica.

Page 6: Kolegij Računalna grafika, 2018/19 Student: Vedran

Dokumentacija za 3. Samostalnu vježbu

Naziv: Demonstracija uporabe shadera za rotaciju i uzorkovanje tekstura

Ciljevi:

Demonstrirati na koji način se koriste VBO(Vertex buffer object), VAO(vertex array object),

EBO(element buffer object)

Učitvanje teksture

Pisanje vertex i fragment shadera, te njihova svrha i uporaba

Kompajliranje shadera iz source koda

Kako dohvatiti atribute na shaderu

Potrebne biblioteke:

Biblioteka za učitavanje OpenGL ekstenzija: glew

Biblioteka za I/O, inicijaliziranje OpenGL konteksta: freeglut

Stb – niz utility biblioteka za C/C++, korišten za učitavanje teksture: stb_image.h

https://github.com/nothings/stb

Pokretanje vježbe

Ako ved nije uključeno u root folderu projekta treba uključiti GLConfig_relative.props u kojem su

podešene staze do svih potrebnih biblioteka s obzirom na glavni direktorij gdje se nalazi Visual Studio

solution (RG2018.sln). Sve potrebne biblioteke su uključene u direktorije projekta, nije potrebno

raditi dodatna podešavanja.

VBO (Vertex buffer object)

- OpenGL objekti, izvori (spremnici, bufferi) Vertex podataka, jedan vertex buffer object može

definirati više vertex atributa (pozicija, boja, normale, 2D teksturne kordinate)

- U našem primjeru definirali smo u jednom bufferu slijedno 3 vrijednosti za poziciju, 3 za boju

(rgb), te 2 za teksturu: PPP BBB TT.

glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer: Omoguduje vezanje spremnika na „target“. Ovo označava nakanu da želim koristiti

spremnik VBO za spremanje podataka vertex atributa. Bududi pozivi funkcija koriste vertex atribute

gledaju koji je buffer trenutno vezan na GL_ARRAY_BUFFER.

Page 7: Kolegij Računalna grafika, 2018/19 Student: Vedran

VAO(Vertex Array Object)

- Prednosti: ne moramo svaki put prije iscrtavanja raditi isti posao, VAO se „veže“ na kontekst i

pamti stanje konteksta. Pozivi nekih od navedenih funkcija modificiraju stanje VAO-a:

- glBindBuffer, glEnableVertexAttribArray, glVertexAttribPointer

- npr. pozivom glVertexAttribPointer VAO pamti koji buffer je bio vezan na GL_ARRAY_BUFFER

za taj atribut i pamti definirani pointer. Bududi pozivi na glBindBuffer se ne pamter, jer VAO

pamti samo buffer koji je bio vezan u trenutku poziva glVertexAttribPointer funkcije.

- Generiranje VAO objekta: glGenVertexArrays(1, &VAO);

- Prije crtanja koristimo: glBindVertexArray(VAO);

EBO(Element Buffer Object)

- Omoguduje 'recikliranje' vertexa zadavanjem indeksa vertexa koji treba iscrtati.

- Način inicijalizacije je identičan kao za VBO:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,GL_STATIC_DRAW);

- Poziv funkcije glDrawElements koristi GL_ELEMENT_ARRAY_BUFFER – indeksirano crtanje glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

- Prvi parametar je primitiv kojeg želimo crtati, drugi parametar je broj

elemenata(ne broj primitiva), odnosno crtamo 12 trokuta, koji se svaki sastoji

od 3 vertexa danih indeksima u GL_ELEMENT_ARRAY_BUFFER.

Shaderi

- VertexShader i FragmentShader dio su OpenGL grafičkog cijevovoda. OpenGL zahtjeva od

nas da definiramo barem VertexShader i FragmentShader (ne postoje podrazumijevani).

U kodu VertexShader je definiran u datoteci VertexShaders.h, a fragment shader u

FragmentShaders.h

Page 8: Kolegij Računalna grafika, 2018/19 Student: Vedran

Vertex Shader

- GLSL jezik

- Koriste se za modificiranje svojstava vertexa: pozicija, boja, koordinate teksture

- Definicija „atributa“ na shaderu: layout(location = i) in ...

#version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aColor; layout(location = 2) in vec2 aTexCoord; out vec3 ourColor; out vec2 TexCoord; uniform mat4 u_proj; uniform mat4 u_view; uniform mat4 u_model; void main() { gl_Position = u_proj * u_view * u_model * vec4(aPos, 1.0); ourColor = aColor; TexCoord = aTexCoord; }

FragmentShader

- Obrađuje fragment generiran rasterizacijskim korakom i generira novi (modificirani)

fragment

- Novi fragment sadrži depth value, stencil value, podatke o boji

Korišteni fragment shader:

#version 330 core out vec4 FragColor; in vec3 ourColor; in vec2 TexCoord; uniform sampler2D ourTexture; void main() { FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 0.5); };

- Ukoliko imamo jednu izlaznu varijablu ne moramo specificirati lokaciju, postavlja se na

lokaciju 0, mogli smo pisati layout(location=0) out vec4 FragColor

Prije korištenja Vertex i Fragment shader moramo kompilirati:

fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); checkShaderCompileStatus(fragmentShader);

Nakon što to napravimo za oba shadera, potrebno je dodati oba shadera u naš shader program, te dodatno linkati

program. Linkanjem se stvaraju izvršni programi koji de se izvršavati u vertex, odnosno fragment procesoru.

ourShader = glCreateProgram(); glAttachShader(ourShader, vertexShader); glAttachShader(ourShader, fragmentShader);

Page 9: Kolegij Računalna grafika, 2018/19 Student: Vedran

glLinkProgram(ourShader);

Ako sad želimo koristiti naš shader program:

glUseProgram(ourShader);

Ako želimo slati podatke na shader:

Dohvatimo lokaciju varijable – glGetUniformLocation(program, ime) vrada cjeli broj koji određuje

lokaciju varijable sa danim imenom unutar specificiranog programa. Npr. projekcijska matrica:

GLint proj_loc = glGetUniformLocation(ourShader, "u_proj");