webgl中相机运动通过变换视图矩阵实现,本质是反向变换世界坐标系;常用lookat函数构建,支持平移、轨道旋转和fps旋转;手动构造时view = 平移逆×旋转逆,需注意矩阵顺序与正交基;须与投影矩阵联用,且避免万向节死锁。

WebGL 本身不提供相机概念,所谓“相机旋转和平移”其实是通过变换 视图矩阵(View Matrix) 来模拟的。核心思路是:把整个世界反向旋转/平移,让观察者(即“相机”)看起来在动——这比真正在场景中移动相机更高效、更符合 OpenGL/WebGL 的坐标变换逻辑。
用 lookAt 构建基础视图矩阵(最常用)
多数 WebGL 应用(尤其 Three.js 风格)会用 lookAt(eye, target, up) 函数生成视图矩阵。它描述的是:从 eye 点出发,看向 target 点,头顶朝向 up 向量。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
-
平移相机:直接修改
eye和target的坐标(保持相对偏移不变),比如 eye += [dx, dy, dz],target += [dx, dy, dz]; -
绕原点旋转(如轨道相机):固定
target(常为 [0,0,0]),用极角/方位角更新eye坐标:eye.x = radius * sin(azimuth) * cos(elevation)eye.y = radius * sin(elevation)eye.z = radius * cos(azimuth) * cos(elevation) - 绕自身坐标系旋转(如 FPS 相机):需维护 yaw/pitch 角度,并用旋转矩阵依次左乘 eye 和 up 向量(注意:target 通常设为 eye + forward,forward 由 yaw/pitch 推出)。
手动构造视图矩阵(理解本质)
视图矩阵 = 平移逆矩阵 × 旋转逆矩阵。假设相机位置为 t = [tx, ty, tz],旋转由正交基 [r, u, f](右/上/前)构成(列向量形式),则:
View = [ r.x r.y r.z 0 ] [ 1 0 0 -tx ]
[ u.x u.y u.z 0 ] [ 0 1 0 -ty ]
[ f.x f.y f.z 0 ] [ 0 0 1 -tz ]
[ 0 0 0 1 ] [ 0 0 0 1 ]
- 平移部分:-t 是把相机移到原点;
- 旋转部分:[r u f] 是将相机局部轴对齐世界轴,它的逆就是其转置(因正交),所以直接用 r/u/f 作为前三行;
- 修改 r/u/f 即实现旋转;修改 t 即实现平移。
实际操作建议(避免常见坑)
- 不要每帧重算完整 lookAt —— 若仅平移,可只更新 eye/target;若仅 yaw,可用旋转变换 eye 和 up,再重算 forward 得新 target;
- pitch 角限制在 (-π/2, π/2) 内,防止万向节死锁(up 向量与 forward 平行);
- 使用列主序矩阵时(WebGL 默认),确保矩阵数据按列填充(如 glMatrix 的 mat4.lookAt 返回的就是列主序);
- 调试技巧:把 view 矩阵求逆,得到 cameraToWorld,从中提取 eye = inverse[12..14],forward = -inverse[8..10],验证是否符合预期。
配合投影矩阵一起使用
视图矩阵必须和投影矩阵(perspective 或 ortho)相乘后传给着色器:uniform mat4 u_matrix = u_projection * u_view * u_model;
其中 model 是物体自身变换,view 是相机变换,projection 是镜头特性。顺序不能错(右乘习惯下:顶点 × model × view × projection)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










