圖形學基礎 | 折射光向量refract的計算

轉載自: 羊羊2035
原文:幾何向量:計算光線折射refract向量

光線折射的產生,其實是因爲光線通過不同介質所產生的“偏折”現象。

ps:一般情況下,我們認爲真空中(或者說空氣中)折射率n = 1,畢竟我們起碼要選取一個標準閥值,來推導其他介質的折射率,這裏直接規定真空(空氣)爲標準1,那麼其他介質的折射率都比真空要大,也就是>1。在這裏插入圖片描述
我們通過建立單位圓輔助計算,通過標量推導出向量的模長,然後通過向量平行和同異方向推導出向量,推出OB = OD + DB = -|cosβ|OE + |sinβ/sinθ|(AO + |cosθ|* OE),推導到這裏,我們就把OB的公式用cos sin以及入射光向量AO和介質法向量N來計算了,這時候我們就思考如何計算cosβ cosθ,讓這兩個值使用已知的n1,n2,AO,OE來替換,如下圖:

在這裏插入圖片描述
我們通過斯涅爾定律:n1 * sinθ = n2 * sinβ得到sinβ = n1/n2 * sinθ

點積的概念推出cosθ

cosβ的推導可以先試用sinβ替換,然後替換斯涅爾定律中計算的sinβ得到cosθ的表示,

這個時候我們所有的未知量就全部通過已知值(n1,n2,AO,OE)來表示了,如下圖
在這裏插入圖片描述

代碼實現:

// Snell's law
// https://blog.csdn.net/yinhun2012/article/details/79472364
Vec3f refract(const Vec3f& I, const Vec3f& N,float &refractive_index) {
	
	float cosi = -std::max(-1.0f, std::min(1.f, I*N));
	float etai = 1, etat = refractive_index;
	Vec3f n = N;
	if (cosi < 0) {
		// if the ray is inside the object, 
		// swap the indices and invert the normal to get the correct result
		cosi = -cosi;
		std::swap(etai, etat); n = -N;
	}
	float eta = etai / etat;
	float k = 1 - eta*eta*(1 - cosi*cosi);
	return k < 0 ? Vec3f(0, 0, 0) : I*eta + n*(eta * cosi - sqrtf(k));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章