欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

[最简单 "的摄像机透视投影矩阵推导与分析

最编程 2024-04-07 20:50:17
...

原文链接

作者:大其心宏其量扩其识

链接:www.jianshu.com/p/09fef48e7…

来源:简书

原文写得很好,但是主题格式我不太喜欢,所以我对文章的格式和重点的部分进行了 补充校正,方便自己日后阅读

正文

相机透视投影矩阵的 目标 是将 视锥体 内的顶点映射到 规范观察立方体 (NDC)内

以前总是记不住透视投影矩阵的推导,现在回过头翻看其实就可以总结为以下 4 步

  1. 相似三角形
  2. 人为构造
  3. 线性映射
  4. 解方程
  • 透视锥到标准设备坐标 image.png

相似三角形计算(xex_{e}->xpx_{p}yey_{e}->ypy_{p}

先用 相似三角形 的原理,计算出 xex_{e}yey_{e}近裁剪面 上的投影 xpx_{p}y_{p}$

  • 左:顶视图 右:侧视图 image.png

先计算 x

image.png

同理,再计算 y

image.png

人为构造第四行

因为 xpx_{p}, ypy_{p} 都与 ze-z_{e} 成反比,因为相机空间的坐标被 GL_PROJECTION 矩阵转换后还是 齐次坐标,最终得到 NDC 坐标是通过除以 裁剪坐标ww 元素来得到的,所以把 ze-z_{e} 当作裁剪坐标的 ww 元素

image.png

线性映射(得到第一、二行)

接下来根据 xpx_{p}->xnx_{n}, ypy_{p}->yny_{n}线性映射 关系:[l,r]->[-1, +1], [b,t]->[-1, +1] 得出归一后公式(一次函数)

image.png

xpx_{p}ypy_{p} 代入到公式中

image.png

方程里的每一项都除以 ze-z_{e}, 那么 括号里的 就变成了 裁剪坐标 xcx_{c}, ycy_{c}

这样,已经推导出了 第一行第二行

image.png

解方程(得到第三行的 A 与 B)

znz_{n}xnx_{n}yny_{n} 不太一样,所有点的 zez_{e} 投影到 近裁剪面 上以后都是相同的,但是我们要用 zez_{e} 来进行裁剪与深度测试, 所以我们要 反向投影Z 轴与 X,Y 轴是无关联的,可以用 Z 轴与 近裁剪面远裁剪面 相交的两个特殊点 (0,0,-n,1), (0,0,-f,1), 反推出映射关系中的 A,B

image.png

因为在相机空间中,wew_{e}1 所以简化为

image.png

在规则观察体里 -n 映射成 -1, -f 映射成 1,代入方程

image.png

解方程求出 A,B

image.png

得到最终矩阵

再把 zez_{e}znz_{n} 的关系代入

image.png

  • OpenGL Perspective Projection Matrix image.png

如果相机视锥是对称的,r=-l, t=-b,投影矩阵可以简化为

image.png

可恶的非线性

需要 注意zez_{e}znz_{n} 的关系 不是线性 的,离 近裁剪面 近的时候变化很大远的时候变化很小,这会导致深度的精度问题,所以尽可能使用 小一些 的深度值

  • Comparison of depth precision image.png

kuso!

也是因为这个 非线性 问题,导致 透视除法 被延后到了 顶点着色器和片元着色器之间,不然顶点着色器后的插值会出问题。

image.png

实际的裁剪

实际硬件上的裁剪步骤是在 裁剪空间 的齐次坐标(顶点着色器中经过 MVP 变换得到)下就完成的,而不是经过透视除法后(顶点着色器和片元着色器之间)的 NDC 空间中,即 xyz 分别和 w 进行比较[注0],而不是除了 w 后再和 [-1,1] 进行比较

image.png

注0:据说硬件上在 xy 上的裁剪还会乘上一个 guardband 系数 扩大范围 裁剪空间.png

参考

  • OpenGL Projection Matrix
  • 图形学基础 - 变换 - 投影
  • 齐次坐标系与Unity投影矩阵的推导
  • Unity 透视投影矩阵变换的可视化