图形学相关数学(反射,折射公式)

这篇博客详细介绍了图形学中的反射和折射公式。通过数学推导和代码示例,解释了反射向量AC如何根据光方向向量AB和法向量N计算,并提供了C++实现。同时,文章还探讨了折射公式,根据折射定律和光学原理,推导出了折射向量T的计算方法,同样附带了相应的C++代码。
部署运行你感兴趣的模型镜像

反射公式

反射是经常用到的一个公式,之前在Phong光照的时候推导过一次,这次再整理一下。反射过程如图所示:

首先需要保证光方向向量AB,法向量N均为单位向量,反射向量AC,光入射方向AD = -AB

θ为入射角,由反射公式我们知道,AC与AB沿y轴对称,AD与AC沿x轴对称

EB = N * |AB|cosθ = N * dot(N,AB)

DC = 2 * EB = -2 * N * dot(N, AB)

AC = AD + DC = -AB + 2 * N * dot(N,AB)

C++代码如下:

	static Vector3 Reflect(const Vector3& vec, const Vector3& normal)
	{
		return -vec + normal * 2.0f * Vector3::Dot(vec, normal);
	}

这里面使用的是vec是指向光源方向的Vec(似乎在shader里面使用这种表示方法更多一些),如果vec指的是由光源方向指向入射点的位置(光线追踪使用得更多一些),则反射公式表示为:

	static Vector3 Reflect(const Vector3& vec, const Vector3& normal)
	{
		return vec - normal * 2.0f * Vector3::Dot(vec, normal);
	}

 

折射公式

最近在玩光线追踪,遇到了一个折射光线的代码,看了半天没太理解,后来拿出笔推算了一遍,才算是理解了原来折射公式还是比较复杂的。下面记录一下推导的过程,先来一张图:

其中入射光线L,折射光线T,入射角θ,折射角θ',法线方向N,入射向量分解为L1,L2,折射向量分解为T1,T2。

首先需要的知识点是折射定律(似乎是中学时学过的):

(1)折射光线位于入射光线和界面法线所决定的平面内;

(2)折射线和入射线分别在法线的两侧;

(3)入射角i的正弦折射角i′的正弦的比值,对折射率一定的两种媒质来说是一个常数。

假设上方介质为1,下方介质为2,则n1 * sinθ1 = n2 * sinθ2,n21 = n2 / n1,表示介质2相对于介质1的折射率。

换成上图公式则为,sinθ' / sinθ  =  n1 / n2 = η。

cosθ = dot(N, -V) = -dot(N,V)。

cosθ' ^2 = 1 - sinθ' ^ 2 = 1 - η * η * sinθ ^2 = 1 - η * η * (1 - cosθ ^ 2)

cosθ' = sqrt(1 - η * η * (1 - dot(N,V) ^ 2))

上图中,将入射光线和出射光线分别拆分成垂直于x轴和垂直于y轴的两条方向上的光线。

T = T1 + T2,L = L1 + L2,T和L以及N均为单位向量|T| = |L|

L = L1 + L2,L = -Ncosθ + L2  => L2 = L + Ncosθ

|T2| = |T|sinθ',|L2| = |L|sinθ,二者相除,且由于|T| = |L|,得到 T2 = L2 * sinθ’ / sinθ = (L + Ncosθ)η

T1与N反方向,故T1 = -N * |T1| = -N * |T|cosθ',由于|T|为单位向量,即 T1 = -N * cosθ'

T = T1 + T2 => T = -N cosθ' + (L + Ncosθ)η

T = -N * sqrt(1 - η * η * (1 - dot(N,V) ^ 2)) + (L - N * dot(N,V)) η

C++代码如下:

	//refractRatio = sinθ' / sinθ 
	static bool Refract(const Vector3& vec, const Vector3& normal, float refractRatio, Vector3& refractDir)
	{
		Vector3 inVec = vec;
		inVec.Normalize();
		float dt = Vector3::Dot(inVec, normal); //cosθ
		float s2 = 1.0 - dt * dt; // sinθ ^ 2
		float st2 = refractRatio * refractRatio * s2;// sinθ’ ^ 2 = refractRato ^ 2 * sinθ ^ 2
		float cost2 = 1 - st2;
		if (cost2 > 0)
		{
			refractDir = (inVec - normal * dt) * refractRatio - normal * sqrt(cost2);
			return true;
		}
		return false;
	}

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值