Zakładmy, że wektor normalny →N, padający →i jak i załamany →t są znormalizowane.
Ponieważ wektory →i i →t są znormalizowane to:
|→i2|=sinα|→i1|=cosα|→t2|=sinβ|→t1|=cosβ
Z rzutów wektorów →i i →t na →N:→i→N=−cosα→t→N=−cosβ
Znając długości wektorów |→i1| i |→t1| i ich zwrot możemy zapisać:→i1=−→Ncosα→t1=−→Ncosβ
Z prawa Snelliusa:n1sinα=n2sinβ
n1|→i2|=n2|→t2|
Ponieważ wektory →i2 i →t2 mają zgodny zwrot i kierunek:n1|→i2|=n2|→t2|
n1→i2=n2→t2
n1(→i−→i1)=n2→t2
n1(→i+→Ncosα)=n2→t2
→t2=n1n2(→i+→Ncosα)
Teraz wyznaczmy →t1:n1(→i−→i1)=n2→t2
n1(→i+→Ncosα)=n2→t2
→t2=n1n2(→i+→Ncosα)
→t1=−→Ncosβ=−→N|→t1|=−→N√1−|→t2|2=−→N√1−sin2β=−→N√1−n1n22sin2α=−→N√1−n1n22(1−cos2α)
Mając →t1 i →t2:→t=→t1+→t2=n1n2(→i+→Ncosα)−→N√1−n1n22(1−cos2α)=n1n2→i+→N(n1n2cosα−√1−n1n22(1−cos2α))
Otrzymany wektor →t jest znormalizowany. Promień padający po w kierunku normalnej nie zostanie załamany.
Jeśli n1<n2 wraz ze zwiększaniem kąta α kąt β będzie się zwiekszał, ale wolniej. Jak α będzie dążył do 90∘ to β będzie dążył do arcsinn1n2, kąta mniejszego od 90∘. Jeśli n2<n1 wraz ze zwiększaniem kąta α kąt β będzie się zwiększał, ale szybciej. Kąt β zmienia się zgodnie z arcsin(n1n2sinα). Dla pewnego granicznego kąta α wartość z której liczymy arcsin będzie większa niż jeden. Nastąpi to dla kąta granicznego arcsinn2n1. Po przekroczeniu tego kąta promień załamany zanika i następuje całkowite wewnętrzne odbicie.
W naszym równaniu na wektor promienia załamanego zjawisko całkowitego wewnętrznego odbicia następuje jeśli:
1−n1n22(1−cos2α)<0
W odniesieniu do raytracing'u należy jeszcze uwzględnić jak zmienia się energia promienia odbitego i załamanego. Po pierwsze zakładamy, że istnieje współczynnik pochłaniania energii promienia odbitego i załamanego. Samo podział energii (a także polaryzacji) dla dielektryków definiuje równanie Fresnel'a. Sam promień przechodząc przez medium powinien tracić energię (Prawo Beer'a albo współczynniki pochłaniania liniowego i wykładniczego).
W niektórych mediach współczynnik załamania może się zmieniać w sposób nieliniowy w danym materiale i tak też będzie poruszać się promień światła w materiale.
Przykład implementacji w C#:
public Ray RefractedRay { get { Debug.Assert(Exists); if (m_refracted_ray == null) { double n = RefractionIndiceN1 / RefractionIndiceN2; double cos_alpha = -SourceRay.Dir * ShadeNormal; double cos_beta_2 = 1 - n * n * (1 - cos_alpha * cos_alpha); if (cos_beta_2 > 0) { Scene.Statistics.RaysRefracted++; Scene.Statistics.RaysCreated++; m_refracted_ray = new Ray() { Dir = n * SourceRay.Dir + (n * cos_alpha - Math.Sqrt(cos_beta_2)) * ShadeNormal, SourceIntersection = this, Start = Pos, Depth = SourceRay.Depth + 1, }; } else { Scene.Statistics.TotalInternalReflections++; } } return m_refracted_ray; } }
Brak komentarzy:
Prześlij komentarz