OpenGL - 如何计算地形高度网格中的法线?

rra*_*lvv 21 opengl grid performance terrain normals

我的方法是分别计算平行于轴X和Y的两个切向量.然后计算叉积以找到法向量.

切线向量由两条最近段上的中点交叉的线给出,如下图所示.

在此输入图像描述

我想知道是否有更直接的计算,或者在CPU周期方面更便宜.

Gig*_*igi 55

你可以通过使用"有限差分法"(或者至少我认为以这种方式调用)来实际计算它而不使用叉积.

实际上它足够快,我用它来计算顶点着色器中的法线.

  // # P.xy store the position for which we want to calculate the normals
  // # height() here is a function that return the height at a point in the terrain

  // read neightbor heights using an arbitrary small offset
  vec3 off = vec3(1.0, 1.0, 0.0);
  float hL = height(P.xy - off.xz);
  float hR = height(P.xy + off.xz);
  float hD = height(P.xy - off.zy);
  float hU = height(P.xy + off.zy);

  // deduce terrain normal
  N.x = hL - hR;
  N.y = hD - hU;
  N.z = 2.0;
  N = normalize(N);
Run Code Online (Sandbox Code Playgroud)

  • 有什么地方对此有数学解释吗? (2认同)
  • 这里有一个更昂贵但稍微更准确的版本/sf/answers/1516212141/ (2认同)
  • 好的,这是有道理的,Nz 必须是偏移量的 2 倍,所以在我的例子中,我使用 0.03 作为偏移量,给出 Nz = .06 (2认同)
  • 考虑您的表面:z = h(x, y),其中 h 是高度图。因此,z - h(x,y) = 0 这是一个方程,是以下函数在 g=0 处的轮廓: g(x,y,z) = z - f(x,y) g 点的梯度向最大增量方向。它也与轮廓平面正交。所以这是正常的。要找到离散梯度,请以 (x,y) 为中心,并取其邻居的差值。grad_x = f(x+1,y) - f(x-1,y) / 2 grad_y = f(x,y+1) - f(x,y-1) / 2 grad_z = (z+1) - (z-1) / 2 = 2/2 = 1 整个事物可以在不改变方向的情况下进行缩放,因此乘以 2。然后标准化。田田! (2认同)