webgl学习(一)——camer的lookAt

webgl学习(一)——camer的lookAt

webgl学习(一)——camer的lookAt

 
3 人赞同了该文章

首先我们需要知道相机的期望位置,将它叫做cameraPosition, 然后需要知道看向或对准的目标位置,将它叫做target。 如果将target减去cameraPosition就会得到相机的朝向, 将它叫做zAxis。由于我们知道相机看向的是 -Z 方向, 所以可以用另一种方式相减cameraPosition - target, 将结果单位化后直接赋给矩阵的z区域。

矩阵的这个区域代表的是 Z 轴。在这个例子中相机的 Z-axis 进行了单位化, 单位化也就是一个做一个类似 1.0 的矢量

z 轴

这些信息还不够,只给了一个单位圆上点,如何来确定物体的姿态呢? 这就需要填充矩阵的其他区域,尤其是 X 轴和 Y 轴。通常情况下我们知道它们互相垂直, 如果再知道哪里是上方,在该例中是(0,1,0),就可以使用“叉乘”去计算矩阵的 X 轴和 Y 轴。

我不知道叉乘的数学意义是什么,但我知道将两个单位向量叉乘后可以得到一个和它们都垂直的向量。 换句话说,如果你有一个向量指向东南方,一个向量指向上方, 叉乘后会得到一个指向西南方或东北方的矢量,因为这两个矢量都和东南方和上方垂直。 相乘的顺序不同的到结果相反。

在任何情况下我们可以通过叉乘zAxis 和up 得到相机的xAxis。

up 叉乘 zAxis = xAxis

现在我们有了 xAxis , 可以叉乘 zAxis 和 xAxis 的到相机的 yAxis

zAxis 叉乘 xAxis = yAxis

现在将三个轴插入矩阵中,会给我们提供一个从 cameraPosition 指向 target 的转换,只需要再加上 position

简化理解:假设x,y,z轴为默认值, 这个矩阵就变成了平移矩阵

这是计算叉乘的代码

function cross(a, b) {
  return [a[1] * b[2] - a[2] * b[1],
          a[2] * b[0] - a[0] * b[2],
          a[0] * b[1] - a[1] * b[0]];
}

这是向量相减的代码

function subtractVectors(a, b) {
  return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
}

这是单位化向量的代码

function normalize(v) {
  var length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  // 确定不会除以 0
  if (length > 0.00001) {
    return [v[0] / length, v[1] / length, v[2] / length];
  } else {
    return [0, 0, 0];
  }
}

这是计算“朝向”矩阵的代码

var m4 = {
  lookAt: function(cameraPosition, target, up) {
    var zAxis = normalize(
        subtractVectors(cameraPosition, target));
    var xAxis = normalize(cross(up, zAxis));
    var yAxis = normalize(cross(zAxis, xAxis));
 
    return [
       xAxis[0], xAxis[1], xAxis[2], 0,
       yAxis[0], yAxis[1], yAxis[2], 0,
       zAxis[0], zAxis[1], zAxis[2], 0,
       cameraPosition[0],
       cameraPosition[1],
       cameraPosition[2],
       1,
    ];
  }

 

有啥用:

根据fov、aspect、near、far构建了一个默认为相机位置在原点, 且看向z轴负方向的视锥;

但相机位置肯定是随意变换的,lookAt就是变化依据:

// 默认位置的相机视锥
var projectionMatrix = m4.perspective(fieldOfViewRadians, aspect, zNear, zFar);

// 任意位置的矩阵
var cameraMatrix = m4.lookAt(cameraPosition, fPosition, up);

// 得到最终的视锥构建
var viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);

应用到着色器中:

gl_Position = viewProjectionMatrix * a_position; // 即可计算出顶点在当前视视锥下的坐标位置点

 

发布于 2024-04-29 15:40・IP 属地重庆

posted on 2024-10-20 16:49  漫思  阅读(10)  评论(0编辑  收藏  举报

导航