S03E06:光线反射

1,117 阅读1分钟

说明

在 3D 中,求光线的反射向量是一个非常常见的操作,那么一般计算过程是什么?

几何

如下图,光线向量为 AB,反射面的法向量为 BC,这里 BC 长度为 1,已经进行了归一化。 那么,我们对光线进行分解,计算出光线在法线方向上的投影长,可以用点乘来计算。向量 BD = dot(AB, BC) * BC

因为向量是可以平移的,这里我们对 AB 进行移动,即方便相加,也在几何上构成四边形,更容易理解。下图中,BB1 = AB,而 B1D2 = 2 * BD。可知,BD2 就是要求的反射向量,而 BD2 = AB + 2 * BD。

这里我们着重说一下,法线 BC 为什么要是归一化的单位向量:如果 BC 不是单位向量的话,直接点乘是无法得到 BD 长度的,最后的结果要除以 BC 的长度。在 3D 计算中,光线有很多条,而法线一般是较为固定的,也就是说一个小三角形上的法线都是一致的,或者提前计算好的法线贴图规定每个点的法线。提前将法线进行归一化处理好处多多,可以减少很多计算量。

代码

在系统 simd 框架下有个simd.geometry,里面自带了计算光线反射的函数。同时,在说明中也强调了法线是单位向量。如有需要可直接调用。

//Returns the reflection direction of an incident vector and a unit normal vector.
func simd_reflect(_ __x: simd_float3, _ __n: simd_float3) -> simd_float3