为什么要算这个?
在3D游戏中,我们需要处理大量光影和物理碰撞。这需要频繁计算“法线向量”(指明物体表面的朝向)。
为了让计算方便,我们需要把向量的长度变成 1,这个过程叫归一化 (Normalization)。
归一化的数学公式是:每个坐标除以向量的长度。而向量长度是用勾股定理算的,包含开平方。所以,底层计算频繁需要求解:
y = 1 / √(x)
在当时,计算机做除法和开平方非常非常慢。这段代码通过一系列数学和计算机底层的“欺骗”手段,巧妙绕过了传统的慢速计算,速度快了数倍!
归一化:将任意长度的箭头缩放为长度1
代码逐行拆解与数学原理
点击左侧代码的任意一行,查看右侧对应的硬核科普解析。
inv_sqrt.c
float InvSqrt(float x) {
1
float xhalf = 0.5f * x;
2
int i = *(int*)&x;
3
i = 0x5f375a86 - (i >> 1);
4
x = *(float*)&i;
5
x = x * (1.5f - xhalf * x * x);
return x;
}
}
算法实测与误差分析图表
自己动手试一试。算法的神奇之处在于:它第一步猜得就非常准,再用牛顿法微调一次,误差直接降到 0.17% 以下!在图形学中,这个精度完全够用了。
标准数学算出的真实值
0.500000
第一步:位移魔法的初猜值
0.490000
误差: ~2%
第二步:牛顿迭代微调后
0.499990
误差: < 0.2%
图表显示了对于不同的X值,魔法初始值与最终值的准确度