Podstawy oświetlenia.

Oto przed nami zupełnie nowa, otwierająca przed nami nowe horyzony część tego kursu. Zajmiemy się w tej i następnych lekcjach czymś, do czego jesteśmy przyzwyczajeni w rzeczywistym świecie, a nie widzieliśmy jeszcze w naszych programach. Nową tą rzeczą będzie oświetlenie. W tej lekcji zajmiemy się omówieniem poszczególnych modeli, a w następnej implementacją.

Toteż – czym jest oświetlenie? Na chłopski rozum – jest to „ilość” światła, jaka pada na dany piksel z danego kierunku. Logiczne i proste, ale jak to obliczyć? Tutaj mamy do dyspozycji parę sposobów. Ale najpierw zajmiemy się podziałem oświetlenia.

Oświetlenie Diffuse – roproszone – to najprostszy rodzaj oświetlenia do zaimplementowania. Powstawanie tego efektu w rzeczywistości tłumaczy poniższy obrazek:

image

Istnieje parę metod aproksymacji oświetlenia diffuse w grafice komputerowej. Najpowszechniejszą jest metoda Lamberta – i to właśnie jej będziemy używać. Otóż mądry ten szwajcar wymyślił, iż współczynnik oświetlenia diffuse równy jest kosinusowi kąta między wektorem kierunku światła, a wektorem normalnym oświetlanej powierzchni. Stąd prosty wzór na obliczenie:

diffuseLight = dot(normalize(surfaceNormal), normalize(lightDirection));

Jeśli zadbamy, żeby długości wektorów były równe 1 (normalizacja), iloczyn skalarny da nam w wyniku kosinus kąta między tymi dwoma wektorami – a więc to, o co nam chodzi! Efekt tego działania jest mniej-więcej taki:

image

Drugim rodzajem oświetlenia o jakim powiemy, jest oświetlenie Specular, czyli rozbłysk. Polskie tłumaczenie jest zgoła dosyć nieudolne, ale obrazuje o czym mowa. Mianowicie, światło padając na powierzchnię pod odpowiednim kątem utworzy błyszczące miejsce. Pokazuje to grafika niżej.

image

Oświetlenie specular możemy obliczyć dwoma sposobami.

image

Zgodnie z poprawniejszym fizycznie modelem Phonga, na podstawie formuły

pow(dot(normalize(reflectedLightDir), normalize(pixelToCamDir)), specPower);

lightDir to kierunek padania światła, N to normalna powierzchni, reflectedLightDir to pomocniczy wektor – padanie światła odbite od powierzchni. Współczynnik specular to podniesiony do potęgi specPower kosinus pomocniczego wektora odbitego i kierunku od piksela do kamery – kąta β.

Dobra, tutaj mała dygresja. Wspomniałem o czymś takim jak wektor normalny powierzchni (normalna). Pod tą szumną nazwą kryje się ni mniej ni więcej niż jednostkowy wektor skierowany prostopadle do powierzchni. Nie należy mylić jednak normalnej z wektorem znormalizowanym – czyli o długości 1.

Model Phonga daje w wyniku taki oto obrazek:

image

Na starszych komputerach, jednak, często stosowano optymalizację – prostszy algorytm Blinna.

image

Dokładna implementacja wymaga parę instrukcji shadera mniej, co wyjaśnimy sobie w następnej lekcji. Tymczasem, obejrzmy jakie efekty daje podejście oparte o model Blinna:

image

Wyróżniamy jeszcze inne składniki oświetlenia, jak Emmisive i Ambient, ale w standardowym podejściu są one realizowane przez stały wektor, więc nie ma sensu zajmować się nimi. Istnieją co prawda metody innego realizowania oświetlenia Ambient (tzw. Ambient Occlusion), jednak są one skomplikowane i na razie wykraczają poza ramy tego kursu.

Jako, iż ta krótka lekcja była jedynie podstawą teoretyczną pod następne, nie jest do niej dołączony kod źródłowy. Nie oznacza to jednak, że jest ona gorsza lub mniej ważna od pozostałych; wręcz przeciwnie – gdyż od dzisiaj, już zawsze wykorzystywać będziemy podstawy których się nauczyliśmy.

Na koniec copyright notice: niektóre obrazki (konkretniej – jedyne dwa ładne, niebędące zrzutami) są zapożyczone z książki Cg Tutorial.


komentarze 4 to “Podstawy oświetlenia.”

  1. Bardzo fajnie że ten kurs dalej powstaje, czekam na następne lekcje.

  2. Charibo kiedy następne lekcje? ;>

  3. W swoich programach oparłeś pętlę while na zmiennej BOOL Run ,ale po kliknięciu na X okna procedura okna(domyślna) już nie przetwarza komunikatów(okna nie ma) ,ale pętla while dalej chodzi ,mimo że reakcja na klawisz ESC dalej istnieje ,może dobrze było byc dodac do ciała while takie coś jeśli nie posiadasz własnej procedury okna:
    if(!IsWindow(hWnd))
    Run = false ;

    • A, tak, wiem o tym. Ale dociekliwy czytelnik sobie tę linijkę dopisze. Ja ją z resztą też dopiszę do szablonu kodu tutoriala, w następnych częściach już będzie. :)

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

 
%d blogerów lubi to: