grafika-uam-rybki-21-22/cw 3/zadania_3.md
2021-12-27 21:29:18 +01:00

73 lines
5.0 KiB
Markdown
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Rzutowanie perspektywiczne
Zadania **main_3_1** zaczynają się w miejscu, w którym skończyło się zadanie **main_2_1** z poprzednich zajęć. Widać w nim jedynie kwadrat, nie cały prostopadłościan. Wyświetlimy go w rzutowaniu perspektywicznym, dzięki temu otrzymamy iluzję trzech wymiarów.
#### Zadanie 1
Macierz perspektywy tworzy funkcja `createPerspectiveMatrix()`, przyjrzyj się definicji tej funkcji. Prześlij macierz perspektywy do shadera.
Wynik wygląda nie do końca tak jakbyśmy się spodziewali. Wynika to z tego, że kamera znajduje się wewnątrz prostopadłościanu. Dodaj macierz kamery do macierzy transformacji, dzięki temu będzie można przesuwać kamerę za pomocą klawiszy. Przesuń prostopadłościan tak, żeby można go było zobaczyć od zewnątrz.
#### Zadanie 1*
Zmodyfikuj macierz perspektywy. W funkcji `createPerspectiveMatrix()` znajduje się zmienna `frustumScale`, która odpowiada ona za kąt widzenia, zmodyfikuj jej wartość i zobacz jaki jest efekt. By obliczyć jej wartość możesz skorzystać ze wzoru $ S = \frac{1}{tan\left( \frac{fov}{2}* \frac{\pi}{2}\right)} $, gdzie $fov$ oznacza kąt widzenia.
#### Zadanie 1**
Wciąż jest problem z rozciąganiem się obrazu przy zmianie kształtu okna. Rozwiązaniem jest wstawienie różnej wartości **frustumScale** dla współrzędnych **X** i **Y**. by to naprawić wykorzystaj funkcję `onReshape`, która jest wywoływana przy zmianie wielkości ekranu. Najpierw oblicz w niej proporcje ekranu i przypisz do zmiennej globalnej `screenRatio`. Następnie przemnóż odpowiednią współrzędną przez `screenRatio` w funkcji `createPerspectiveMatrix()`.
## Obsługa Shaderów
W tej części zadań będziemy korzystać z innych obiektów, usuń z funkcji `init` inicjalizację prostopadłościanu i jego rysowanie z funkcji `renderScene` oraz zamień shadery na `shaders/shader_3_2.vert` i `shaders/shader_3_2.frag`.
#### Zadanie 2
Wczytaj statek i sferę za pomocą do `loadModelToContext` do odpowiednich `Core::RenderContext`. Następnie wyświetl je za pomocą funkcji `Core::DrawContext`. Rozmieść je w różnych miejscach w przestrzeni.
##### Dodaj możliwość zmiany kolorów obiektów:
Stwórz zmienną `uniform vec3 objectColor` w pliku `shader_3_2.frag` (jej definicja musi się ona znajdować nad definicją funkcji `main`), wykorzystamy ją do przesłania koloru w formacie RGB do shadera. Zmienna wbudowana `gl_FragColor` jest typu `vec4` w formacie RGBA, współrzędne przyjmują wartości od od 0 do 1. Do części RGB przypisz wartość `objectColor` a do A wartość 1.
Możemy teraz ustawić kolor rysowanego obiektu ustawiając wartość zmiennej `objectColor` przed rysowaniem obiektu. Robimy to korzystając z funkcji `glUniform3f( int location, float v0, float v1, float v2 )`, gdzie parametr `location` oznacza adres zmiennej w pamięci karty graficznej, do której chcemy wartości wysłać. Można ten adres uzyskać wywołując funkcje `glGetUniformLocation(program, "nazwa zmiennej")`.
#### Zadanie 2*
Zmodyfikuj program tak, żeby kolor statku zmieniał się w czasie.
#### Zadanie 3
Wyświetl "kolor" wektora normalnego do powierzchni w danym punkcie.
> Wektor normalny to wektor prostopadły do powierzchni w danym punkcie, pozwala on na przykład na policzenie odbicia światła.
Wektor normalny wierzcholka dostępny jest w *vertex shaderze* (plik z rozszerzeniem **.vert**). Kolor powierzchni (piksela) ustala sie jednak we *fragment shaderze* (**.frag**). Zatem należy przesłać wartość wektora normalnego z *vertex* do *fragment* shadera. Służą do tego specjalne zmienne (interpolatory).
Stwórz zmienną typu `out vec3 nazwa` w *vertex shaderze* oraz odpowiadająca mu zmienna `in vec3 nazwa` we *fragment shaderze*. Prześlij przy jej użyciu wartość wektora normalnego.
Użyj tej wartości, aby w jakiś sposób przypisać kolor pikselowi.
Aby otrzymać ładny efekt, najpierw znormalizuj wektor otrzymany przez *fragment shader*.
Następnie przeskaluj wartości (x, y, z) wektora z przedziału [-1, 1] do [0, 1] i przypisz je do kanałów R, G, B zmiennej `gl_FragColor`.
#### Zadanie 4
Stwórz funkcje `drawObject`, która ułatwi rysowanie wielu obiektów.
Na liście parametrów musza znaleźć się referencja do `Core::RenderContext` oraz macierz modelu (*model matrix*) obiektu.
Wyświetl kilka obiektów w różnych pozycjach (i obejrzyj je z każdej strony).
"Przyczep" model statku do kamery - uzależnij jego macierz modelu od pozycji i orientacji kamery tak, aby wyglądało jakbyś poruszał(a) się statkiem.
```C++
glm::mat4 shipModelMatrix =
glm::translate(cameraPos + cameraDir * 0.5f + glm::vec3(0,-0.25f,0)) *
glm::rotate(-cameraAngle + glm::radians(90.0f), glm::vec3(0,1,0)) *
glm::scale(glm::vec3(0.25f));
```
Przeanalizuj tą macierz modelu lub napisz własną.
#### Zadanie 5
Stwórz układ planetarny - jedna nieruchoma kule na środku (Słonce) i kilka orbitujących wokół niej planet.
Niech przynajmniej jedna planeta ma księżyce.