#sec-1
Computer Graphics · Chapter 5 · 01

虚拟相机与观察变换

从模型坐标到相机坐标:谁在移动?我们从哪里看?

医学模型虚拟相机相机标架View MatrixlookAt
第5章 · 观察 | 40分钟独立教学单元 | WebGL2 / Reveal.js
#sec-2-1
Bridge-in · MED × CG

医工问题:模型不动,为什么视图改变?

同一个已重建的骨骼与植入物三维模型,能否在不改变模型数据的情况下,从正面、侧面和斜上方观察?

同一三维医学模型的不同观察视角
#sec-2-2
Prediction

如果相机向右移动,模型看起来向哪边移动?

保持相机观察方向不变,世界里的立方体和器械都固定不动。

相机沿世界X正方向平移1个单位,物体在相机坐标中的X值如何变化?
A. 增大1B. 减小1C. 保持不变
答案:B 世界相对于相机向相反方向移动。
先独立作答,再用“相机静止、世界反向移动”的等效视角进行解释。
#sec-2-3
Connection · Chapter 4 → 5

第四章移动模型;第五章移动观察者

Model Matrix · M

改变对象在世界中的位置、方向或大小,回答“对象放在哪里”。

View Matrix · V

将世界中的点表达为相机坐标,回答“相机怎样观察”。

模型坐标→M→世界坐标→V→相机坐标
统一思想:对象和相机虽然角色不同,但GPU处理的仍是顶点坐标与矩阵。
#sec-3-1
Camera Parameters

三个输入参数:Eye、At、Up

一个位置、一个目标点、一条参考向上方向——让程序知道相机在哪里、看向哪里、怎样保持正立。

Eye · 视点

相机位置,几何类型是点。

At · 观察目标

决定视线方向,几何类型是点。

Up · 参考向上

确定相机滚转参考,几何类型是向量。

lookAt三参数与相机标架
#sec-3-2
Camera Frame

从世界的方向,得到相机自己的方向

视线方向

f = normalize(at − eye)
指向目标,朝向相机局部负Z方向。

相机后向

n = normalize(eye − at)
指向相机后方,对应局部正Z轴。

n = normalize(eye − at)本课程使用右手相机标架,相机默认朝局部 −Z 方向看。
预测:只改变At、不改变Eye,会改变相机位置还是朝向?
#sec-3-3
Construct Camera Basis

借助叉积建立三个正交轴

1后向 n:normalize(eye − at)。
2右向 u:normalize(up × n)。
3真正上向 v:n × u。
Camera Frame = {Eye, u, v, n}得到相机在世界坐标中的一个正交标架。
需要的前置知识:第四章叉积、单位向量、参考标架。不在这里重讲向量运算定义。
#sec-3-4
Common Pitfalls

Up不一定就是相机最终的Y轴

正常情况

参考Up并不要求与视线严格垂直;程序会构造真正的上向轴v。

退化情况

如果Up和视线平行或近乎平行,叉积长度为零或过小,无法稳定地构造相机标架。

当eye=(0,0,5)、at=(0,0,0)时,下面哪个Up会导致退化?
A. (0,1,0)B. (0,0,1)C. (1,0,0)
答案:B 它与观察方向共线。
#sec-3-5
Coordinate Frames

同一个几何点,在不同标架下有不同坐标

对象标架
Object
→世界标架
World
→相机标架
Camera

第四章关注

如何从对象坐标得到世界坐标:p_world = M · p_model。

这一课关注

如何从世界坐标得到相机坐标:p_eye = V · p_world。

关键:点没有改变,改变的是点相对于不同标架的坐标表示。
#sec-4-1
Inverse Transform

观察矩阵:为什么需要相机位姿的逆变换?

相机位姿说明“相机在世界中的位置”,但渲染需要“世界中的点相对于相机在哪里”。

V = C−1C:相机标架 → 世界标架;V:世界标架 → 相机标架。
相机移动与世界反向变换
#sec-4-2
Worked Example

只有平移时,逆变换特别直观

相机位于(0,0,5),观察方向为负Z;世界中的点P=(1,0,0)。

相机在Z=5→世界沿Z负方向平移5→P的相机坐标(1,0,−5)
V = T(0, 0, −5)平移矩阵的逆,就是采用反方向位移。
思考:把相机向远处移动,不等于简单“把物体缩小”;是否变小还取决于投影类型。
#sec-4-3
Orientation

相机旋转时,也要改变坐标轴的表达

相机自身绕某个轴旋转,物体没有旋转,却会在相机画面中改变方位。

相机位姿 C

由旋转R和平移T构成,用来描述相机在哪里、朝向哪里。

观察矩阵 V

需要逆向使用旋转和平移,使相机成为新标架的原点与基准轴。

V = RT · T(−eye)假设R是相机到世界的正交旋转,列向量约定。
联系第四章:矩阵乘法顺序不可交换;先移动世界,再转到相机方向。
#sec-4-4
Transformation Chain

相机不是“贴在世界里的一张图片”

pmodel→M→pworld→V→peye
peye = V · M · pmodel
到这里仍然是三维坐标。二维投影要在第二课时引入P。
#sec-4-5
Quick Check

观察方向和视点的位置,谁改变了?

保持Eye不变,修改At,一般会直接改变什么?
A. 相机的位置B. 相机的观察方向C. 模型自身顶点坐标
答案:B 目标点变化会改变视线方向;模型数据没有被改写。
补充:Eye和At同时作相同平移,可使相机整体移动而保持观察方向不变。
#sec-5-1
Interactive Demo

D05-01 · 相机与观察矩阵显微镜

D05-01 · 教学实验台 WebGL2 + Canvas 2D + 原生三维数学

虚拟相机与观察矩阵显微镜

改变相机参数,模型几何数据保持不可变。实时探究 Eye、At、Up 如何构造相机标架,以及观察矩阵为何是位姿矩阵的逆。

🔹 三重视角联动:世界旁观概览、4×4 矩阵数值与 WebGL2 透视渲染同步更新
🔹 顶点不可变性:模型顶点 Buffer 永久保持不变,仅更新 View Matrix
🔹 异常几何捕捉:实时拦截 Eye 与 At 重合及 Up 与视线共线错误
课堂观察任务 4 min

带着问题观察与验证

  1. 预测与平移:体验“Prediction → Operation → Observation → Explanation”流程,验证相机沿 +X 平移时点 P 的相机坐标为何减少 1。
  2. 保持 Eye 改变 At:验证相机原地转向时,视线方向变化与旋转矩阵更新,确认相机位置未变。
  3. 非法 Up 探究:设置 Up 与视线同向,观察正交标架为何无法建立及几何原因。
  4. 顶点 Buffer 监视:观察操作全过程,Vertex Buffer 状态指示灯是否全程绿灯保持未改变。
💡 重点理解:改变相机与移动世界具有互逆的相对运动关系(\(V = C_{\text{pose}}^{-1}\))。
请先口头预测,再操作滑块;Demo中应显示坐标和矩阵的中间状态,而不仅是最终图像。
#sec-5-2
Demo Experiment

三次操作,只改变一个条件

1保持朝向不变,改变Eye:观察相对坐标变化。
2保持Eye不变,改变At:观察相机朝向改变。
3保持Eye和At不变,改变Up:观察相机滚转。
记录:哪些操作会导致观察矩阵改变?哪些操作会改变对象的原始顶点Buffer?
#sec-5-3
Observation → Explanation

实验现象说明了什么?

坐标表示改变

世界中相同的顶点,在相机坐标中的分量会随着观察矩阵改变。

模型几何保持

改变Eye、At、Up时不需要重新生成模型顶点,只需改变观察状态并重新渲染。

Scene Geometry(固定) + View Matrix(变化) → New View
连接第三章的事件输入、动画循环与第四章的uniform矩阵传递。
#sec-6-1
Code Walkthrough

在JavaScript中调用lookAt

const viewMatrix = mat4.create();
const eye = [3, 2, 6];
const at  = [0, 0, 0];
const up  = [0, 1, 0];

mat4.lookAt(viewMatrix, eye, at, up);
与教材中的lookAt(eye, at, up)记号对应。注意gl-matrix的接口需要输出矩阵参数。

这段代码创建的是世界坐标到相机坐标的观察矩阵,不是相机对象的模型矩阵。

#sec-6-2
Shader Connection

第四章的Model Matrix,接上View Matrix

vec4 worldPosition = uModelMatrix * aPosition;
vec4 cameraPosition = uViewMatrix * worldPosition;
// 下一课:gl_Position = uProjectionMatrix * cameraPosition;
Vertex Buffer→Model→World→View→Camera
今天先理解相机坐标的形成,不把cameraPosition误认为已经完成投影的gl_Position。
#sec-6-3
AI Collaboration · Bug Hunt

AI给出的相机解释是否正确?

AI CLAIM

“lookAt返回相机在世界中的位姿矩阵,因此可直接作为相机的Model Matrix使用。”

1确定lookAt输出矩阵的映射方向。
2写出相机位姿C与观察矩阵V的关系。
3用相机位于(0,0,5)的数值例子核验。
结论:通常V=C⁻¹;说“相机放在Z=5”不等于把V平移到Z=5。
#sec-6-4
Performance Connection

相机变化时,需要修改什么数据?

通常不变

模型顶点数组、拓扑和Vertex Buffer。

会更新

View Matrix及对应的uniform;然后重新绘制。

仅移动虚拟相机时,下列哪项通常必须更新?
A. 全部几何顶点坐标B. 观察矩阵uniformC. 每个顶点的索引顺序
答案:B 可以使用原有顶点Buffer和新的观察矩阵。
#sec-7-1
Connection to Next Lesson

观察变换解决了什么,还没解决什么?

三维对象→模型变换 M→世界场景→观察变换 V→相机坐标
下一课的问题:已经得到相机坐标,怎样决定正交/透视、裁剪范围并得到屏幕上的二维图像?
#sec-7-2
Summary

本课时小结:相机如何进入绘制流水线

1Eye / At / Up 定义观察位置、视线及参考向上方向。
2lookAt 构造从世界到相机的观察矩阵。
3V=C⁻¹ 体现参考标架转换的逆变换思想。
4p_eye=V·M·p_model 是下一课投影的输入。
#sec-7-3
Exit Ticket

Exit Ticket · 一句话解释逆变换

相机朝向不变、沿世界X轴正方向平移时,世界中的固定物体在相机坐标中沿哪个方向变化?为什么?
先写出预测,再用“世界相对于相机”的语言解释。
期望答案:物体相对坐标沿X负方向变化,因为观察变换使用相机位姿的逆变换。

课堂结束:请学生指出Model Matrix与View Matrix各自回答什么问题。