Raytracig: krok po kroku cz. 6 - model Phoga I. Co/Dlaczego? Model oświetleia Phoga, którym będziemy się zajmować w tej części, został przedstawioy przez Phog Bui- Tuoga w jego rozprawie doktorskiej w roku 1973. Model te przyjmuje, że obiekt jest pokryty cieką przezroczystą warstwą, a której zachodzi odbicie lustrzae, atomiast tuż pod tą warstwą astępuję odbicie rozproszoe, które zabarwia światło a odpowiedi kolor. Mimo że model te ie jest dokłady fizyczie, bardzo dobrze przybliża wygląd obiektów takich jak błyszczące plastiki i lakierowae ściay. Materiały Phoga różią się od materiałów perfekcyjie rozpraszających tym, że więcej światła jest odbijaego w kieruku lustrzaego odbicia iż w pozostałych kierukach. Przedstawia to, umieszczay już wcześiej, rysuek: II. Model Phoga Oświetleie dzieli sie a iezależe (viewer - idepedet) i zależe (viewer - depedet) od obserwatora. Stworzoy przez as wcześiej model perfekcyjie rozpraszającego materiału jest doskoałym przykładem oświetleia iezależego od obserwatora - jeśli popatrzymy a obiekt z iego puktu (ie zmieiając oświetleia), każdy pukt tego obiektu zachowa swój poprzedi kolor. Model Phoga czyi obiekty lśiącymi pozwalając im, do pewego stopia, odbijać światło - co jest widocze jako jase rozbłyski (specular highlights) a powierzchi. Jest przykładem oświetleia zależego od obserwatora - przy przemieszczaiu kamery rozbłyski wydają się przemieszczać. Rozbłysk jest zależy od kąta pomiędzy promieiami odbitymi od źródła światła, a kierukiem do obserwatora. Najsiliejszy rozbłysk występuje w miejscu gdzie kąt te jest rówy zero (promień odbity od powierzchi leci 'prosto do oka'), ale szybko słabie wraz z jego wzrostem. specular highlight a powierzchi sfery. 1
Tak więc wiemy od czego zależy jasośc rozbłysków a powierzchi materiału, ale dalej ie wiemy w jaki sposób je symulować. Zaczijmy od tego jakich daych potrzebujemy podczas cieiowaia: Pozycja światła Pozycja puktu w który trafił promień Normala cieiowaej powierzchi Pozycja obserwatora I tyle am wystarczy. Jak widać pojawił się owy, w porówaiu do światła rozproszoego pukt - jest to pozycja obserwatora. Cieiując, zacziemy podobie jak w przypadku modelu Lamberta - obliczymy kieruek wpadającego światła i sprawdzimy jaki kąt (cosius kąta) tworzy z ormalą powierzchi. Jeśli ujemy - możemy od razu zwrócić kolor czary i ie martwić się dalej. Następie dalej ic owego - liczymy współczyik światła rozproszoego: light.color * materialcolor * diffusefactor. Ale tym razem to ie koiec. Ostati krok wygląda tak: result += materialcolor * phogfactor. Tajemiczy phogfactor jest główym bohaterem tej części. Jest, podiesioym do pewej potęgi, cosiusem kąta zawartego pomiędzy kierukiem odbitego światła a kierukiem do obserwatora: exp phog = cos α Wspomiaa potęga (ozaczoa we wzorze jako exp) jest większym od zera parametrem zwaym wykładikiem rozbłysku (specular expoet) kotrolującym jego wygląd: ta sama kula rederowaa z exp = 1, 10, 100, 1000, 10000 Kieruek do obserwatora już zamy (pozycja obserwatora - pozycja puktu trafieia) - jak obliczyć kieruek odbitego światła? Okazuje się że wystarczy odbić kieruek wpadającego światła (który zamy) od ormalej powierzchi (którą rówież zamy). 2
Tak więc zostaje pytaie - jak odbić wektor? III. Odbijaie wektora W tym podrozdziale będzie trochę matematyki a wektorach - jeśli kogoś to przeraża, moża przeskoczyć od razu a koiec gdzie jest podaa gotowa fukcja. Tak więc chcemy odbić wektor wpadającego światła (l) od ormalej () żeby otrzymać wektor światła odbitego (r). Zauważmy ajpierw że odbijae i odbity wektor leżą wszystkie a jedej płaszczyźie - wyika z tego że możemy zapisać każdy z ich za pomocą kombiacji liiowej pozostałych dwóch. Zapiszmy więc: r = al + b Gdzie a i b to pewe liczby. Do ich wyzaczeia potrzebujemy jeszcze dwóch rówań. Pierwsze rówaie możemy ułożyć zauważając że zasadiczą cechą odbicia jest to że kąt pomiędzy wektorami r i jest rówy kątowi pomiędzy l i. Wyika z tego że rówe są ich projekcje (wykoywae za pomocą dot productu) a wektor. r = l Po wykoaiu dot productu po obydwóch stroach podstawowego rówaia otrzymujemy: r = al + b l = al + b r al = b (1 a) l = b 3
Możemy rówież wykoać projekcję wektorów r i l a wektor leżący a płaszczyźie od której odbijamy (będący prostopadły do ). r = l Zowu podstawiając do obydwóch stro rówaia: r = al l l (1 + a) l a = 1 = al + al = 0 + b + b = 0 Łącząc wyprowadzoe wcześiej rówaia, otrzymujemy: r = l + 2( l) Teraz możemy to zapisać w obiecaej fukcji (ależącej do klasy Vector3): public static Vector3 Reflect(Vector3 vec, Vector3 ormal) double dot = ormal.dot(vec); retur ormal * dot * 2 - vec; Przy okazji, jeszcze jeda uwaga - będziemy za chwilę potrzebować fukcji do odwracaia zwrotu wektora (zamieiaie wszystkich jego współrzędych a liczby przeciwe) którą jakimś sposobem wcześiej pomięliśmy. Musimy więc do wektora dodać taki oto kod: public static Vector3 operator -(Vector3 vec) retur ew Vector3(-vec.X, -vec.y, -vec.z); IV. Implemetacja Wiemy wszystko czego potrzebujemy, możemy przystąpić do zamieiaia tego w kod. Najpierw stwórzmy szkielet klasy materiału, pobierający potrzebe parametry: 4
class Phog : IMaterial ColorRgb materialcolor; double diffusecoeff; double specular; double specularexpoet; public Phog(ColorRgb materialcolor, double diffuse, double specular, double specularexpoet) this.materialcolor = materialcolor; this.diffusecoeff = diffuse; this.specular = specular; this.specularexpoet = specularexpoet; public ColorRgb Radiace(PoitLight light, HitIfo hit) throw ew System.NotImplemetedExceptio(); Parametry jakie przyjmuje asz materiał to (oczywiście) kolor, współczyik rozproszeia (a wypadek gdybyśmy chcieli uczyić go miejszym iż 1 czyiąc światło rozproszoe słabszym) współczyik rozbłysku (specular - kotrolujący, zaskakująco, jasość rozbłysku) i wykładik rozbłysku (ostrość odbić światła). Materiały będą iestety przyjmowały z czasem coraz więcej parametrów, i trudo coś a to poradzić (opcja `udostępij bezparametrowy kostruktor i settery pól` ma swoje zalety, ale rówież wady - materiał bez ustawioego chociaż jedego pola to ieprawidłowy materiał, a takie błędy może być ciężko wykryć). Zacziemy podobie jak przy świetle rozproszoym: Vector3 idirectio = (light.positio - hit.hitpoit).normalized; double diffusefactor = idirectio.dot(hit.normal); if (diffusefactor < 0) retur ColorRgb.Black; ColorRgb result = light.color * materialcolor * diffusefactor * diffusecoeff; Dalej musimy wyliczyć współczyik phoga i zmodyfikować kolor w oparciu o iego: double phogfactor = PhogFactor(iDirectio, hit.normal, -hit.ray.directio); if (phogfactor!= 0) result += materialcolor * specular * phogfactor; Jak wyliczyć współczyik już wiemy, przytaczając podaą wcześiej defiicję: Współczyik Phoga jest, podiesioym do pewej potęgi, cosiusem kąta zawartego pomiędzy kierukiem odbitego światła a kierukiem do obserwatora double PhogFactor(Vector3 idirectio, Vector3 ormal, Vector3 tocameradirectio) Vector3 reflected = Vector3.Reflect(iDirectio, ormal); double cosagle = reflected.dot(tocameradirectio); if (cosagle <= 0) retur 0; retur Math.Pow(cosAgle, specularexpoet); 5
Gotowe (trzeba tylko pamiętać o zwróceiu zera jeśli cosius kąta jest miejszy od zera)! Łącząc w jedą całość, otrzymujemy taką oto fukcję radiacji: public ColorRgb Radiace(PoitLight light, HitIfo hit) Vector3 idirectio = (light.positio - hit.hitpoit).normalized; double diffusefactor = idirectio.dot(hit.normal); if (diffusefactor < 0) retur ColorRgb.Black; ColorRgb result = light.color * materialcolor * diffusefactor * diffusecoeff; double phogfactor = PhogFactor(iDirectio, hit.normal, -hit.ray.directio); if (phogfactor!= 0) result += materialcolor * specular * phogfactor; retur result; V. Wyiki Jak wygląda efekt aszej pracy? Zaczie lepiej iż poprzedio (jak a jedą, dość prosta fukcję). Na początku rozłóżmy światło a czyiki pierwsze: Nie musimy się wcale ograiczać do trzech obiektów a sceie: Ciekawie wygląda rówież obrazek pokazujący działaie światła i cieia, który właściwie powiie się zaleźć w 6
poprzediej części, ale ie wyglądałby tak przyjemie (czerwoe, zieloe i iebieskie światło): Na koiec, obowiązkowy obrazek aszych klasyczych Trzech Kul Na Płaszczyźie. Podmieńmy materiały przypisywae obiektom (dodatkowo kolory zostały zmieioe a miej bijące w oczy - mają oe też te zaletę że ie są moochromatycze co przyda się przy odbiciach): IMaterial redmat = ew Phog(Color.LightCoral, 0.8, 1, 30); IMaterial greemat = ew Phog(Color.LightGree, 0.8, 1, 30); IMaterial bluemat = ew Phog(Color.LightBlue, 0.8, 1, 30); IMaterial graymat = ew Phog(Color.Gray, 0.8, 1, 30); I w taki oto sposób otrzymujemy: 7