如何从WebGL视图/透视矩阵还原mat4.lookAt的center参数?
首先得明确一个关键事实:mat4.lookAt生成的视图矩阵并不保留eye到center的距离信息——它只根据eye和center的相对方向来确定相机朝向,不管你把center放在eye前方1米还是100米,得到的视图矩阵都是完全一样的。所以如果你只拥有视图矩阵和已知的eye,你只能确定center所在的射线(从eye出发沿视线方向的射线),但无法得到精确的center点,除非你还记得当初设置lookAt时eye到center的距离。
不过别担心,我们还是能得到最核心的视线方向,再结合距离就能还原center,具体步骤如下:
步骤1:从视图矩阵中提取视线方向
glMatrix的mat4是列主序存储的,视图矩阵的第三列(数组索引8-10)对应相机空间的z轴方向,而这个方向正好是normalize(eye - center)——也就是视线方向的反方向。我们只需要取反并归一化,就能得到从eye指向center的单位向量:
import { vec3 } from 'gl-matrix'; // 假设你已经有了视图矩阵viewMat和已知的eye向量(vec3类型) const zAxis = vec3.fromValues(viewMat[8], viewMat[9], viewMat[10]); const lookDir = vec3.create(); // 取反得到视线方向(从eye指向center) vec3.negate(lookDir, zAxis); // 归一化确保是单位向量 vec3.normalize(lookDir, lookDir);
步骤2:还原精确的center点(需要距离信息)
如果你记得当初设置lookAt时,eye到center的直线距离(比如你可以计算当初的vec3.distance(eye, center)并保存下来),就可以用这个距离来计算精确的center:
// 假设保存的距离为distanceToCenter const center = vec3.create(); // center = eye + 视线方向 * 距离 vec3.scaleAndAdd(center, eye, lookDir, distanceToCenter);
为什么无法仅用视图矩阵还原距离?
因为mat4.lookAt内部会对视线方向做归一化处理,丢弃了原始的长度信息。举个例子:如果你用eye = [0,0,5],center = [0,0,0],和用center = [0,0,3]生成的视图矩阵是完全相同的——两者的相机朝向一致,只是center到eye的距离不同,但视图矩阵只关心朝向,不关心距离。
额外提示:如果结合透视投影矩阵?
即使加上透视投影矩阵,也无法还原这个距离,因为投影矩阵同样会丢弃深度的绝对信息,只保留相对的深度关系(用于裁剪和深度测试)。只有当你有某个点的深度缓冲区值,并且知道该点在世界空间中的位置时,才能反推距离,但这已经超出了仅从矩阵还原的范畴。
内容的提问来源于stack exchange,提问作者pronngo

