基于中心差分法从高度图计算法线:系数2*与-4的来源疑问
拆解高度图法线计算中的中心差分系数逻辑
嘿,这个问题问得特别到位——很多人都是直接抄公式用,但很少深究背后的数学原理,我来一步步给你理清楚:
先明确基础逻辑:高度图→梯度→法线
高度图的每个像素对应空间中的点坐标是 (x, y, h(x,y)),其中 h(x,y) 是该点的高度值。我们要找的法线,本质是垂直于该点所在平面的向量,而这个平面的倾斜程度由高度的变化率(也就是梯度)决定:
- 梯度
∇h = (∂h/∂x, ∂h/∂y),表示x、y方向上的高度变化速率 - 法线与梯度垂直,我们可以通过两个切线向量的叉乘得到法线:
x方向切线向量是(1, 0, ∂h/∂x)(x走1单位,y不动,高度变化∂h/∂x)
y方向切线向量是(0, 1, ∂h/∂y)(y走1单位,x不动,高度变化∂h/∂y)
叉乘结果就是法线:(-∂h/∂x, -∂h/∂y, 1)(右手坐标系下的结果,方向指向上方)
中心差分怎么算偏导数?
中心差分是计算离散数据偏导数的常用方法,比前向/后向差分精度更高。对于高度图来说,我们默认相邻像素的步长(Δx、Δy)都是1:
- x方向偏导:取当前点右侧像素高度R和左侧像素高度L,差值除以2(因为L到R的距离是2个单位步长),即
∂h/∂x = (R - L)/2 - y方向偏导:取当前点下方像素高度B和上方像素高度T,同理得
∂h/∂y = (B - T)/2
这里的除以2就是你看到的中心差分“除以2”的逻辑——它是用两点间的总距离来计算平均变化率,误差更小。
公式里的2*和-4是怎么来的?
把上面的偏导代入法线公式,得到:
法线 = ( -(R-L)/2, -(B-T)/2, 1 )
这个向量是正确的,但里面有分数,不方便计算。我们可以给整个向量乘以一个非零常数(因为归一化时会除以向量模长,常数会被约掉,不影响最终方向):
- 乘以
-4的话,就得到:
这就是你看到的公式!这里的法线 = ( 2*(R-L), 2*(B-T), -4 )-4一方面消去了分数,另一方面反转了法线的方向(z分量从1变成-4)——这通常是为了适配某些渲染系统的坐标系要求(比如部分系统中z轴指向屏幕外,法线需要指向场景内部)。
关键结论
不管是原始的 (-(R-L)/2, -(B-T)/2, 1) 还是你看到的 (2*(R-L), 2*(B-T), -4),本质是成比例的向量,归一化后得到的法线方向完全一致。系数只是为了计算方便和适配坐标系,核心逻辑还是中心差分算梯度、叉乘得法线。
内容的提问来源于stack exchange,提问作者gdf31
相关产品推荐
相关产品推荐

