Czyli poprawna symulacja wielokrotnego odbicia i załamania wymagałaby pamiętania informacji o polaryzacji. Na razie pomijamy tą fizyczną właściwość światła. Zakładamy, że każdy promień padający przypomina polaryzacją światło naturalną czyli jest niespolaryzowany.
Równanie Fresnela opisuje tylko odbicie i załamanie od powierzchni dielektryków. Dielektryk może być dla danej częstotliwości światła nieprzeźroczysty. Czyli do pełnej symulacji potrzebowalibyśmy informację o widmie fali i o tym jak na każdą ze składowych widma reaguje materiał. W naszym uproszczonym przypadku posługujemy się tylko opisem jak światło zostanie załamane i odbite dla składowych RGB.
W przypadku powierzchni metalicznych światło odbija się od nich całkowicie. Równanie to nie ma zastosowania. Co nie znaczy, że światło nie może zmienić swojej polaryzacji.
W przypadku powierzchni dielektrycznych nieprzeźroczystych promień załamany jest pochłaniany, z reguły nie następuje to od razu. Cienka warstwa materiału zwykle uważanego za nieprzeźroczysty może być przeźroczysta. Pochłanianiu z reguły towarzyszy rozpraszanie.
Światło to fala elektromagnetyczna, którą możemy sobie wyobrazić jako rozchodzące się w przestrzeni, prostopadłe w płaszczyznach, oscylacje pola magnetycznego i elektrycznego. Oscylacje pola magnetycznego i elektrycznego są zgodne z fazie. Fala elektromagnetyczna jest falą poprzeczną.
Ponieważ wektory $\vec B$ i $\vec E$ są do siebie prostopadłe przyjęło się wyróżniać wektor $\vec E$ kiedy mówimy o polaryzacji.
Równania Fresnela inaczej traktują fale prostopadłą do powierzchni (płaszczyzna wektora E i kierunku fali jest prostopadła do powierzchni), a inaczej równoległą. Dowolnie inaczej zorientowaną falę można przedstawić jako superpozycję takich właśnie wzajemnie do siebie prostopadłych fal.
Dla fali prostopadłej współczynnik odbicia wynosi:
$R_\perp=(\displaystyle\frac{n_1\cos\alpha-n_2\cos\beta}{n_1\cos\alpha+n_2\cos\beta})^2$
Dla fali równoległej współczynnik odbicia wynosi: $R_\parallel=(\displaystyle\frac{n_1\cos\beta-n_2\cos\alpha}{n_1\cos\beta+n_2\cos\alpha})^2$
Współczynniki refrakcji zaś: $T_\perp=1-R_\perp$ i $T_\parallel=1-R_\parallel$.Ponieważ w naszym przypadku zakładamy, że światło jest równomiernie wymieszane, tak więc możemy powiedzieć, że składa się one w połowie fal równoległych do powierzchni i w połowie prostopadłych, tak więc: $R=\displaystyle\frac{R_\perp+R_\parallel}{2}$.
Z wzorów tych wynika, że jeśli $n_1>n_2$, dla kątów większych od kąta granicznego zachodzi zjawisko całkowitego wewnętrznego odbicia. Poza tym jeśli $n_1<n_2$ to istnieje taki kąt dla których $R_\parallel$ zanika do zera. Odbite światło pod tym kątem jest całkowicie spolaryzowane w jednej płaszczyźnie. Jest to tzw. kąt Brewstera.
Wykresy obu współczynników w funkcji kąta:
Kod MATLAB użyty do zrobienia wykresów:
count = 1000;
angles = linspace(0, 90, count);
function [r1, r2] = fresnel_all(n1, n2)
r1 = (1:count);
r2 = (1:count);
for i=1:count
alpha = angles(i) * pi / 180;
beta = asin(sin(alpha)*n1/n2);
r1(i) = ((n1*cos(alpha) - n2*cos(beta)) / ...
(n1*cos(alpha) + n2*cos(beta)))^2;
r2(i) = ((n1*cos(beta) - n2*cos(alpha)) / ...
(n1*cos(beta) + n2*cos(alpha)))^2;
if (n1 > n2) && (alpha >= asin(n2/n1))
r1(i) = nan;
r2(i) = nan;
end
end
end
[r1, r2] = fresnel_all(1, 2);
[r3, r4] = fresnel_all(2, 1);
figure(1)
hold on;
plot(angles, r1, 'r');
plot(angles, r2, 'g');
title('n_1=1, n_2=2');
legend('perpendicular ', 'parallel');
figure(2)
hold on;
plot(angles, r3, 'r');
plot(angles, r4, 'g');
title('n_1=2, n_2=1');
legend('perpendicular ', 'parallel');
Implementacja w C#:
public static double FresnelReflectionFactor(Vector3 a_reflected_or_inverse_in, Vector3 a_normal, double a_n1, double a_n2) { double ca = a_normal * a_reflected_or_inverse_in; Debug.Assert(ca.IsAlmostRelativeGreaterOrEqualThen(0)); Debug.Assert(ca.IsAlmostRelativeLessOrEqualThen(1)); ca = DoubleExtensions.Limit(ca, 0, 1); double sa = Math.Sqrt(1 - ca * ca); double sb = sa * a_n1 / a_n2; if (sb > 1) return 1; double cb = Math.Sqrt(1 - sb * sb); double can1 = ca * a_n1; double can2 = ca * a_n2; double cbn1 = cb * a_n1; double cbn2 = cb * a_n2; double rs = Math.Pow((can1 - cbn2) / (can1 + cbn2), 2); double rt = Math.Pow((cbn1 - can2) / (cbn1 + can2), 2); double result = (rs + rt) / 2; Debug.Assert(result >= 0); Debug.Assert(result <= 1); return result; } public static double FresnelReflectionFactor(Ray a_reflected_ray, Ray a_refracted_ray, Vector3 a_normal, double a_n1, double a_n2) { if (a_refracted_ray == null) return 1; double ca = a_normal * a_reflected_ray.Dir; double cb = -(a_normal * a_refracted_ray.Dir); Debug.Assert(ca.IsAlmostRelativeGreaterOrEqualThen(0)); Debug.Assert(cb.IsAlmostRelativeGreaterOrEqualThen(0)); Debug.Assert(ca.IsAlmostRelativeLessOrEqualThen(1)); Debug.Assert(cb.IsAlmostRelativeLessOrEqualThen(1)); ca = DoubleExtensions.Limit(ca, 0, 1); cb = DoubleExtensions.Limit(ca, 0, 1); double can1 = ca * a_n1; double can2 = ca * a_n2; double cbn1 = cb * a_n1; double cbn2 = cb * a_n2; double rs = Math.Pow((can1 - cbn2) / (can1 + cbn2), 2); double rt = Math.Pow((cbn1 - can2) / (cbn1 + can2), 2); double result = (rs + rt) / 2; Debug.Assert(result >= 0); Debug.Assert(result <= 1); return result; }