专栏首页王肖的UTOpenGL中投影变换矩阵的反向推导

OpenGL中投影变换矩阵的反向推导

在OpenGL中有两个重要的投影变换:正交投影(Orthographic Projection)和透视投影(Perspective Projection),二者各有对应的变换矩阵。初学者比较难理解这两个矩阵是怎么来的。本文从数学角度来反向推导两个投影矩阵。

推导的思路

正交投影和透视投影的作用都是把用户坐标映射到OpenGL的可视区域。如果我们能根据二者的变换矩阵来推出最终经过映射的坐标范围恰好是OpenGL的可视区域,也就是反向推导出了这两个投影矩阵。

OpenGL的可视区域的坐标范围是一个边长为2的立方体。每个维度上的大小是2,范围是[-1,+1]。经过各种变换之后的坐标超出[-1,+1]范围的部分将不会显示到屏幕上。

正交投影

变换效果

正交投影在OpenGL中的作用是调整屏幕宽高比,并将实际定义的坐标转换成[-1,+1]范围内的对应的坐标。

矩阵定义

下图是正交投影矩阵。

参数解释如下:

只考虑x轴和y轴,则:

在定义物体的坐标的时候,坐标范围为: \left\{\begin{matrix}x\in [left,right] \\ y\in [top,bottom] \end{matrix}\right.

通过上面那个矩阵,就可以转换成[-1,+1]范围内的对应的坐标。下面对此进行证明。

数学推导

① 假设物体上的一个坐标为(x,y,z,1),其中,x的范围为[left, right],y的范围为[top, bottom],z的范围为[near, far]

则,矩阵*向量

即,x1=\frac{2x-left-right}{right-left} ,y1=\frac{2y-top-bottom}{bottom-left} ,z1=\frac{2z-near-far}{far-near} ,w1=1

② 考虑到perspective divide的存在,此时w=1,所以:

② 先证明x轴确实落在了[-1, +1]的范围。

很明显,x1是关于x的一元一次线性函数。x1=f(x)=\frac{2*x-left-right}{right-left}

所以x=right的时候,f(x)最大,x=left的时候,f(x)最小。

代入方程,得到:f(x)=\left\{\begin{matrix}f(x)=-1, x=left \\ f(x)=1, x=right \end{matrix}\right.

③ 所以x1=f(x) \in [-1, +1]

同理,y1和z1的范围也是[-1, +1]。

证明结束。

小结

正交变换是将物体的坐标转换成OpenGL的坐标。

变换前的范围为:\left\{\begin{matrix}x \in [left,right] \\y \in [bottom,top] \\z \in [near,far] \end{matrix}\right.

变换后的范围为: \left\{\begin{matrix}x \in [-1,1] \\y \in [-1,1] \\z \in [-1,1] \end{matrix}\right.

透视投影

变换效果

在用2D屏幕展现3D场景时,会有一种近大远小的感觉。OpenGL也是利用这一原理实现在2D屏幕上的3D效果。透视投影会形成一个视椎体,在视椎体内的坐标都是可以绘制到屏幕上的,也就是说,在视椎体上的坐标范围都会被调整到[-1, +1]的区间。

矩阵定义

参数解释如下:

透视矩阵有些特殊,并未说明x和y的范围,下面通过推导得出这个范围。

数学推导

① 假设物体上的一个坐标为(x,y,z,1)

则,矩阵*向量的结果为:

即,

② 考虑perspective divide的存在,得到:

③ 求:当结果落在了[-1, +1]的范围的时候,x的范围是多少?

很明显,x2是关于x的一元一次线性函数。

x2=f(x)=\frac{-ax}{aspect*z}

下面推算当x2的范围为[-1, +1]的时候,x的范围

x=\left\{\begin{matrix}\frac{aspect*z}{a},f(x)=-1 \\ -\frac{aspect*z}{a},f(x)=1 \end{matrix}\right.

所以,x的范围为[\frac{aspect*z}{a},-\frac{aspect*z}{a}]

这里注意,按照习惯,z一般都是负数,所以上面的区间范围是没问题的,下同。

④ 求:当结果落在了[-1, +1]的范围的时候,y的范围是多少?

因为,y2=f(y)=-\frac{ay}{z}

分别求y1为1和-1时,y的值。

y=\left\{\begin{matrix}\frac{z}{a},f(y)=-1 \\ -\frac{z}{a},f(y)=1 \end{matrix}\right.

所以,y的范围为[\frac{z}{a},-\frac{z}{a}]

⑤ 求:当结果落在了[-1, +1]的范围的时候,z的范围是多少?

因为,

-1<=f(z)<=1

则有,

解方程得,-1<=f(z)<=1

所以,n<=z<=f

即变换前的坐标一定要在平截椎体的Z轴范围内才能最终展示到屏幕上。

证明结束。

小结

透视变换是将物体的坐标转换成OpenGL的坐标。

变换前的范围为:

变换后的范围为:

附上透视椎体的图解:

总结

矩阵变换在OpenGL坐标变换中起到了非常重要的作用。在二维图像显示时一般使用正交变换,在三维图像显示时就要用到透视变换。理解这两个变换对应的矩阵的作用对我们理解这两个变换很重要。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android版本名称及API版本对应表

    wxdut.com
  • 《实现模式》读书总结

    这是一本关于如何写好代码的书,是一本关于“如何编写别人能懂的代码”的书。

    wxdut.com
  • 《OpenGL ES 2.0 for Android》读书笔记

    OpenGL其实只能绘制三角形,确定三个顶点,然后就可以绘制一个三角形,多个三角形拼在一起就可以组成各式各样的图形,把图片资源贴到这些各式各样的图形上就可以实现...

    wxdut.com
  • 关于多云的最大误解

    https://www.cloudops.com/blog/the-biggest-myths-of-multi-cloud/

    CNCF
  • 初识nginx——配置解析篇

    一、nginx的介绍     nginx是由俄罗斯人开发的一款高性能的http和反向代理服务器,也可以用来作为邮件代理。相比较于其他的服务器,具有占用内存少,稳...

    magicsoar
  • 基于JDK8中Optional写出可读性高的代码

    JDK8中引入了函数式编程,大大提高了我们编写代码的可读性,其中Optional则是为了避免NPE而生,下面我们就来看看它是如何提高代码可读性的。

    加多
  • MySQL显示ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)解决方法

    葆宁
  • 8TBLRMs存储模块

    该存储模块容量为8TB,适用于军用飞机,符合军用飞机可靠性设计准则,采用领存自主可控主控芯片SSD,通过SAS接口对外提供块级文件存、取服务,具备...

    国产的人的国产路
  • 高斯消元法(Gauss Elimination)【超详解&模板】

    高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵。 高斯消元法的原理是: 若用初等行变换将增广矩阵 化为 ...

    Angel_Kitty
  • Vue Cli 3 搭建一个可按需引入组件的组件库架子

    babel-plugin-component 就是 Element UI 用来实现组件按需加载的一个 babel 插件。我们把它用到我们的组件库上,就不需要重新...

    stys35

扫码关注云+社区

领取腾讯云代金券