首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >OpenGL矩阵变换的数学推导

OpenGL矩阵变换的数学推导

作者头像
天天P图攻城狮
发布于 2023-04-10 03:40:16
发布于 2023-04-10 03:40:16
1.4K0
举报
文章被收录于专栏:天天P图攻城狮天天P图攻城狮

说起OpenGL的矩阵变换,我是之前在我们的项目天天P图、布丁相机中开发3D效果时才比较深入地研究了其中的原理,一直想写这篇文章,由于很忙(lǎn),拖了很久,再不写我自己也要忘了。 一开始时,也只是知道怎么去用这些矩阵,却不知道这些矩阵是怎么得来的,当出现一些莫名其妙的问题时,如果不了解其中的原理,就不知道如何解决,于是想彻底搞懂其中的原理,还好自己对数学挺有兴趣,于是从头到尾把推导过程研究了一遍,总算掌握了其中的奥秘,不得不佩服OpengGL的设计者,其中的数学变换过程令人陶醉,下面我们一起来看看。 这些矩阵当中最重要的就是模型矩阵(Model Matrix)、视图矩阵(View Matrix)、投影矩阵(Projection Matrix),本文也只分析这3个矩阵的数学推导过程。这三个矩阵的计算OpenGL的API都为我们封装好了,我们在实际开发时,只需要给API传对应的参数就能得到这些矩阵,下面带大家来看看究竟是怎样计算得到的。

什么是OpenGL的矩阵变换

我们先来看一张经典图:

这张图相信很多同学在学习OpenGL的过程中都看到过,它比较直观地展示了OpenGL矩阵变换的过程,下面我详解一下其中的含义:

  • 首先OpenGL有个世界坐标系,我们渲染的物体就是在世界坐标系中,我们的模型需要放到世界坐标系中,那么当我们还没放的时候,模型就和世界坐标系没有联系,它就还处于自己的坐标系中,我们叫做模型坐标系、局部空间、局部坐标系,也就是图中的LOCAL SPACE。
  • 当我们把模型放到世界坐标系中,模型就在世界坐标系里有了坐标,也就是原来在LOCAL SPACE中的那些坐标值,变成了世界坐标系中的坐标值,帮助我们完成这个变换的就是模型矩阵,对应图中的MODEL MATRIX,于是这样我们就把模型放到了图中的世界坐标系WORLD SPACE中
  • 放到世界坐标系后,是不是就确定了我们渲染出来看到的样子?还没有,大家可以想像一下,我把一个东西放在世界坐标系的某个地方,我可以从近处看观察它,也可以从远处观察它,还可以从上下左右观察它,甚至还可以倒着观察它,因些还需要确定我们观察它的状态。OpenGL里帮我们虚拟出了一个Camera(特别注意,这里的Camera不是指我们硬件的Camera),从API的层面上看,我们只需要设置Camera的位置、朝向的点坐标、以及Camera的上方向向量就能将观察状态定下来,而这些设置最终会转换成OpenGL中的视图矩阵,对应图中的VIEW MATRIX
  • 经过View Matrix的变换后,我们观察它的结果就确定了,图中是从距离它一定的距离、上往下观察它,这时候的点坐标就来到了视图坐标系下,对应图中的VIEW SPACE
  • 这时候,我们能看到什么东西,基本已经确定了,不过还有一步投影变换,这是什么东西?大家想像一下,我们看到同一个东西,是不是通常都是近大远小?那么如何实现近大远小?就要靠投影变换,OpenGL提供正交投影和透视投影,正交投影没有近大远小的效果,不管在什么距离上看,都一样大,透视投影则有近大远小的效果,也是符合我们实际生活的一种效果,透视投影应用得比较多,可看下面这张经典图:

        完成投影变换就需要靠投影矩阵,即图中的PROJECTION MATRIX

  • 我们看可以从图中看到经过投影变换后就到了裁剪坐标系CLIP SPACE,什么?裁剪坐标系?我们不是投影吗?裁剪了什么东西?实际上,我们的投影操作也顺带做了裁剪,所谓裁剪就是说把那些我们视野内看不到的东西去掉,什么是视野?就是我们在生成投影矩阵时会设置近平面、远平面、视角,这些东西会构成一个可见的空间,对应上图中的虚线和近平面、远平面包围起来的空间
  • 下一步就是上屏(如果是离屏渲染就是到一个frame buffer上),这些坐标毕竟只是OpenGL坐标系下的坐标,那么最终以什么样的大小呈现在屏幕上呢?就要通过视口变换映射到屏幕上

以上就是一个完整的矩阵变换过程,里面最重要的就是MVP三个矩阵,M即模型矩阵(Model Matrix),V即视图矩阵(View Matrix),P即投影矩阵(Projection Matrix),本文将针对这三个矩阵的来由详解其中的数学推导,其中投影矩阵只讲解透视投影矩阵,因此它比较常用且其推导过程比正交投影矩阵复杂得多。

模型矩阵(Model Matrix)推导

相信大家在数学中都学过平移、缩放、旋转三种基本变换,将模型放到世界坐标系中就是利用这三种变换的组合来实现的,我们来看一下平移、缩放、旋转三种变换对应的矩阵:

  • 平移变换
  • 缩放变换
  • 旋转变换

        1)绕x轴旋转

         2)绕y轴旋转

          3)绕z轴旋转

大家可以看到旋转变换有三个矩阵?为什么不写成一个,注意绕轴旋转的先后顺序不同,最终的结果可能是不一样的,因此有三个独立的矩阵,根据实际情况组合。

模型矩阵相对来说简单一些,相信大家还能回忆起来之前学数学时的知识,就是通过将平移、缩放、旋转三种矩阵的组合实现将模型以某种姿态、某种大小放到世界坐标系的某个地方。

视图矩阵(View Matrix)推导

前面提到过,视图矩阵对应Camera的位置、朝向的点坐标、以及Camera的上方向向量,我们先来看一张图:

下面我们来看看怎样通过Camera的位置、朝向的点坐标、以及Camera的上方向向量得到对应的View Matrix,首先给Camera定一个坐标系:

NUV这三个向量是怎么来的呢?我们将Camera的坐标记为eye,朝向的点坐标记为lookat,上方向向量记为up,那么:

N向量: eye - lookat

U向量:up X N并归一化

V向量:N X U并归一化

我们要把Camera以某种姿态放在世界坐标系中的某个地方,这个放的过程就是对应Camera的旋转和平移,这里表示为TR,其中T表示平稳变换矩阵,R表示旋转变换矩阵。

我们虽然设置的是Camera,但最终动的是点坐标,因为Camera压根就不存在,是一个假想的东西。假设我们不动摄像机,动坐标点,那么对坐标点的变换就应该是对相机变换的逆变换T^-1R^-1(就是对TR整体求逆矩阵),注意,这里的T^-1R^-1看起来貌不惊人,实际上就是我们要求的View Matrix。

根据前面的知识,我们能很容易得到T^-1:

这个直观上也好理解,比如本来是平移Tx,逆过来就是平移-Tx,依此类推。 再回顾一下我们的目标T^-1R^-1,现在还差R^-1,现在再次回到我们假想的Camera,前面说要对它做TR,当做完R后,Camera会旋转至某个姿态:

XYZ和UVN都可以看成是一组基,根据线性代数公式可将一个点在XYZ基下的坐标转成在UVN基下的坐标,R就相当于是把基XYZ变换成UVN的变换矩阵,其中:

假设:

则有:

于是:

由于R是正交矩阵,有性质:R^-1=R^TR^T代表R的转置),为什么R是正交矩阵?Tips:方阵A正交的充要条件是A的行(列) 向量组是单位正交向量组。 于是:

现在我们T^-1R^-1都有了,T^-1R^-1也就是最终的View Matrix可以很容易地计算出来了,因为OpenGL中坐标是4维的,所以这里将矩阵写成4*4的:

投影矩阵(Projection Matrix)推导

下面是投影矩阵的推导,是最为复杂的一个矩阵,前面提到,投影矩阵是由视野决定的,而视野又是由近平面、远平面和视角决定的,我们把视野在坐标系中画出来,请看下图:

简单起见,我们不妨把Camera摆在原点,让它朝z轴负方向来讨论问题。 h表示近平面高度 w表示近平面宽度 n表示Camera到近平面的距离 f表示Camera到远平面的距离 P代表视野中的一个点 那么接下来要求的投影矩阵,就是能将P点正确地投影到近平面上,设P(x0, y0, z0),我们从y轴正向往负向看,即看xoz平面,看到的画面是这样的:

假设投影后的x坐标为x1 ,由三角形相似原理则易得:

同理有:

设l和r分别为近平面左、右边框的x坐标,则有l=-w/2,r=w/2,投影归一化后坐标范围为-1~1,最左边是-1,最右边是1,l和r归一化至-1~1是线性变换,于是列一个kx+b类型的方程组并解得k和b:

xn表示点P的x坐标投影归一化后的值,代入kx+b得:

同理可得点P的y坐标投影归一化后的值yn:

下面我们来构造带有未知数的投影矩阵然后求解它们,设待投影点为(x0,y0,z0,1),我们先来构造投影矩阵的第一第二行:

这里强调一个细节,投影矩阵仅帮我们完成投影变换,不会归一化,上面的x2、y2、z2指的是投影后归一化前的值,还记得前面计算的xnyn吗?我们用一个括号把其中一个部分括了起来,外面乘了一个因子(-1/z0),后面会说这个因子是什么东西,现在只需要知道,x2、y2实际上就是前面括号里那堆东西,所以上面投影矩阵的第一行和第二行就自然能轻松地构造出来。

接下来就构造第三第四行,我们先看第四行,第四行计算的结果是投影后的第四维坐标,也就是w,前面提到了归一化,而OpenGL的归一化操作就是通过将坐标除以其对应的w值来完成的,再回头看我们前面计算的xnyn,它们是归一化后的值。 还记得括号外面乘了一个因子(-1/z0)吗?乘(-1/z0)可以看成是除以-z0,因此希望w就是-z0,于是构造第四行让w的计算结果为-z0

接下来就是最复杂的第三行,如何去构造第三行?第三行有4个值,现在都不知道是什么,我们需要构造4个未知数吗?对于解方程来说,在能解决问题的情况下,未知数能少就尽量少,不然只会徒增烦恼。 这里其实不需要4个未知数,为什么呢?那就要理解z2这个值是什么东西,它就是投影之后未归一化的深度值,而深度和x0、y0没有关系,这个如何理解?就是说我把一个东西放在左,上边,还是右边,不影响它的深度,要改变深度需要前后移动。 既然z2x0、y0没有关系,那么x0、y0不管是什么值,都不会影响z2的值,因此用0去乘x0、y0,即第三行的第一第二个元素是0。 再看第三行的第三第四个元素,我们假设第三个元素是0,会发生是什么?那么z2就等于B,而B最后求出来放到矩阵中肯定是一个定值,这就意味着z2也是定值,于是z2就无法表示不同的点的不同深度,这不是我们想要的结果,因此第三个元素不能是0,是一个待求的未知数。同理,我们假设第四个元素是0会发生什么?这样投影矩阵第四列全是0,根据线性代数的知识,这个矩阵行列式等0,它必定不可逆,而我们希望投影矩阵是可逆的,这样我们可以对坐标做一些逆变换来实现一些特殊的功能,因此第四个元素也不能是0,于是设它为一个未知数。 这样,我们就构造出了一个包含未知数A和B的投影矩阵:

下面就是求解A和B: 我们将z0-f-n代进去,-f就是远平面,-n就是近平面,求归一化后的坐标,-f最远,深度最深,归一化后是1,反之,-n代进去后是-1,注意,深度是值越大越深,于是有:

可解得:

于是投影矩阵为:

总结

至此,我们就完成了模型矩阵(Model Matrix)、视图矩阵(View Matrix)和投影矩阵(Projection Matrix)的数学推导,可以看到里面的变换还是很精彩的,原来神秘的矩阵变换过程已经清晰可见,希望能对大家有帮助!谢谢!

作者简介:kenney, 天天P图Android工程师


文章后记 天天P图是由腾讯公司开发的业内领先的图像处理,相机美拍的APP。欢迎扫码或搜索关注我们的微信公众号:“天天P图攻城狮”,那上面将陆续公开分享我们的技术实践,期待一起交流学习!

加入我们 天天P图技术团队长期招聘: (1) 深度学习(图像处理)研发工程师(上海) 工作职责

  • 开展图像/视频的深度学习相关领域研究和开发工作;
  • 负责图像/视频深度学习算法方案的设计与实现;
  • 支持社交平台部产品前沿深度学习相关研究。

工作要求

  • 计算机等相关专业硕士及以上学历,计算机视觉等方向优先;
  • 掌握主流计算机视觉和机器学习/深度学习等相关知识,有相关的研究经历或开发经验;
  • 具有较强的编程能力,熟悉C/C++、python;
  • 人脸识别,背景分割,体态跟踪等技术方向上有研究经历者优先,熟悉主流和前沿的技术方案优先;
  • 宽泛的技术视野,创造性思维,富有想象力;
  • 思维活跃,能快速学习新知识,对技术研发富有激情。

(2) AND / iOS 开发工程师  (3) 图像处理算法工程师 期待对我们感兴趣或者有推荐的技术牛人加入我们(base 上海)!联系方式:ttpic_dev@qq.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 天天P图攻城狮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
OpenGL矩阵变换的数学推导
说起OpenGL的矩阵变换,我是之前在我们的项目天天P图、布丁相机中开发3D效果时才比较深入地研究了其中的原理,当时一开始时,也只是知道怎么去用这些矩阵,却不知道这些矩阵是怎么得来的,当出现一些莫名其妙的问题时,如果不了解其中的原理,就不知道如何解决,于是想彻底搞懂其中的原理,还好自己对数学挺有兴趣,于是从头到尾把推导过程研究了一遍,总算掌握了其中的奥秘,不得不佩服OpengGL的设计者,其中的数学变换过程令人陶醉,下面我们一起来看看。 这些矩阵当中最重要的就是模型矩阵(Model Matrix)、视图矩阵(View Matrix)、投影矩阵(Projection Matrix),本文也只分析这3个矩阵的数学推导过程。这三个矩阵的计算OpenGL的API都为我们封装好了,我们在实际开发时,只需要给API传对应的参数就能得到这些矩阵,下面带大家来看看究竟是怎样计算得到的。
腾讯Bugly
2019/01/30
6.7K2
OpenGL矩阵变换的数学推导
​OpenGL 学习系列---坐标系统
在前面绘制基本图形中,遇到了很明显的问题,圆形不像圆形,正多边形不像正多边形?就像下面图形一样:
音视频开发进阶
2019/07/25
1.5K0
WebGL简易教程(五):图形变换(模型、视图、投影变换)
通过之前的教程,对WebGL中可编程渲染管线的流程有了一定的认识。但是只有前面的知识还不足以绘制真正的三维场景,可以发现之前我们绘制的点、三角形的坐标都是[-1,1]之间,Z值的坐标都是采用的默认0值,而一般的三维场景都是很复杂的三维坐标。为了在二维视图中绘制复杂的三维场景,需要进行相应的的图形变换;这一篇教程,就是详细讲解WebGL的图形变换的过程,这个过程同样也适合OpenGL/OpenGL ES,甚至其他3D图形接口。
charlee44
2019/10/08
3.1K0
WebGL简易教程(五):图形变换(模型、视图、投影变换)
图形学入门(一):坐标变换
将一个物体显示到屏幕上,这个事情似乎非常简单,以至于我们基本上认为它已经天经地义到直接告诉计算机我们要显示什么物体它就会自动显示出来,毕竟我们拍照的时候就是举起相机按下快门就会出现一张图片了。但事实上,相机是基于物理感光元件实现了从三维世界到二维图片的投影,在计算机的程序世界中一切都需要被计算出来,也就是说,我们只有一堆图形的描述信息,我们需要自己将这些图形在二维的平面上绘制的方式告诉操作系统,操作系统才能最终在屏幕上绘制出我们想要的图形。
zhiruili
2021/08/10
2K0
图形学入门(一):坐标变换
OpenGL ES-3D图形变换知识
最近一段时间很忙,没什么时间再去研究OpenGL,有朋友问我OpenGL ES图形变换的相关问题,这里抽出时间整理一下相关资料,便于大家学习3D图形运动的知识。 (ps:有朋友以为我去腾讯云+社区写博客去了,这里说明一下,没有换平台写博客,只是加入了腾讯的云+社区分享计划,这里写的文章会自动同步到腾讯云+社区,有腾讯云+社区的朋友也可关注我) 一.坐标系统 OpenGL希望在所有顶点着色器运行后,所有我们可见的顶点都变为标准化设备坐标(Normalized Device Coordinate, NDC)。
清墨
2018/07/04
1K0
OpenGL-投影和摄像机
本文介绍了从相机内外参数的标定、立体匹配、多视几何、投影映射、体渲染等多个方面,系统地讲解了移动设备GPU上基于光线的3D渲染从输入到输出的整个过程。同时,通过实例介绍了在移动端GPU上实现这些算法的具体实现方式和优化策略,包括Vulkan、Metal、OpenGL ES、WebGL等多种平台上的实现。本文旨在帮助读者了解3D渲染技术的基本原理,以及在移动端GPU上实现这些算法的具体实现方式和优化策略,包括Vulkan、Metal、OpenGL ES、WebGL等多种平台上的实现。
MelonTeam
2018/01/08
3.4K0
OpenGL-投影和摄像机
理解单目相机3D几何特性
激光雷达技术、以及立体视觉通常用于3D定位和场景理解研究中,那么单个摄像头是否也可以用于3D定位和场景理解中吗?所以我们首先必须了解相机如何将3D场景转换为2D图像的基本知识,当我们认为相机坐标系中的物体场景是相机原点位置(0,0,0)以及在相机的坐标系的X、Y、Z轴时,摄像机将3D物体场景转换成由下面的图描述的方式的2D图像。
点云PCL博主
2022/04/06
1.9K0
理解单目相机3D几何特性
投影矩阵和内外参到底是啥关系?
投影矩阵能够实现3D点到2D坐标,结合和内参K和外参T,可以表达为P=K[R|t] 我们知道K是3*3的矩阵,我们在内参的基础上增加一列将其变成3*4矩阵。在ROS中我们将投影矩阵定义为内参加上一个baseline的位移。所以投影矩阵的左边3*3的矩阵是相机内参,所以如果是双目的左相机的投影矩阵,他的投影矩阵的最后一列的tx,ty就是0。
点云PCL博主
2024/11/25
4390
投影矩阵和内外参到底是啥关系?
OpenGL(五)-- OpenGL中矩阵的变换OpenGL(五)-- OpenGL中矩阵的变换
通过模型矩阵,观察者矩阵(View Matrix),投影矩阵(Projection Matrix)三步矩阵变换后最终确定该展示怎样的图像。要注意的是矩阵的计算时从右往左的所以: result = 投影矩阵 * 观察者矩阵 * 模型矩阵。
用户8893176
2021/08/09
2.7K0
OpenGL(五)-- OpenGL中矩阵的变换OpenGL(五)-- OpenGL中矩阵的变换
[OpenGL]OpenGL坐标系及坐标转换
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ouyangshima/article/details/25135009
用户1148525
2019/06/11
4.5K0
透视投影变换矩阵推导_矩阵的投影
http://www.codeguru.com/cpp/misc/misc/math/article.php/c10123__1/Deriving-Projection-Matrices.htm,由于本人能力有限,有译的不明白的地方大家可以参考原文,谢谢^-^!
全栈程序员站长
2022/11/10
1.8K0
透视投影变换矩阵推导_矩阵的投影
终端图像处理系列 - OpenGL ES 2.0 - 3D基础(矩阵投影)
Overview 移动设备的屏幕是二维平面,要想把一个三维场景渲染在手机二维屏幕上,需要利用OpenGL中的矩阵投射,将三维空间中的点映射到二维平面上。三维矩阵的相关知识是学习OpenGL最重要的课程之一。 线性代数 学习OpenGL三维投射知识之前,我们得事先了解下一些基础的线性代数知识,如向量运算,矩阵运算。 向量运算 向量: 指一个同时具有大小和方向的几何对象,因常常以箭头符号表示以区别于其它量而得名。 向量加减 向量的加(减)法定义是分量的相加(减),即将一个向量中的每一个分量加上(减去)另一个向量
天天P图攻城狮
2018/02/02
2.7K0
终端图像处理系列 - OpenGL ES 2.0 - 3D基础(矩阵投影)
图形学习之视图
本篇介绍下视图变换,包括从世界坐标到显示器中的一系列变换。通过本篇可以了解到我们看到的一幅图像是如何渲染到显示器上的。
一只小虾米
2022/10/25
3860
图形学习之视图
基于消失点的相机自标定(1)
标题:Camera calibration using two or three vanishing points
点云PCL博主
2020/12/17
4.3K0
基于消失点的相机自标定(1)
模型矩阵、视图矩阵、投影矩阵
模型视图投影矩阵的作用,就是将顶点从局部坐标系转化到规范立方体(Canonical View Volnme)中。总而言之,模型视图投影矩阵=投影矩阵×视图矩阵×模型矩阵,模型矩阵将顶点从局部坐标系转化到世界坐标系中,视图矩阵将顶点从世界坐标系转化到视图坐标系下,而投影矩阵将顶点从视图坐标系转化到规范立方体中。
全栈程序员站长
2022/08/27
2.6K0
OpenGL中投影变换矩阵的反向推导
在OpenGL中有两个重要的投影变换:正交投影(Orthographic Projection)和透视投影(Perspective Projection),二者各有对应的变换矩阵。初学者比较难理解这两个矩阵是怎么来的。本文从数学角度来反向推导两个投影矩阵。 推导的思路 正交投影和透视投影的作用都是把用户坐标映射到OpenGL的可视区域。如果我们能根据二者的变换矩阵来推出最终经过映射的坐标范围恰好是OpenGL的可视区域,也就是反向推导出了这两个投影矩阵。 OpenGL的可视区域的坐标范围是一个边长为2
wxdut.com
2018/05/09
2.6K0
实验6 OpenGL模型视图变换
  (1)阅读教材有关三维图形变换原理,运行示范实验代码,掌握OPENGL程序三维图形变换的方法;   (2)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换。   (3)请分别调整观察变换矩阵、模型变换矩阵和投影变换矩阵的参数,观察变换结果;   (4)掌握三维观察流程、观察坐标系的确定、世界坐标系与观察坐标系之间的转换、平行投影和透视投影的特点,观察空间与规范化观察空间的概念。理解OpenGL图形库下视点函数、正交投影函数、透视投影函数。理解三维图形显示与观察代码实例。
步行者08
2020/10/27
2.3K0
实验6  OpenGL模型视图变换
3D图形学线代基础
如标题所言都是些很基础但是异常重要的数学知识,如果不能彻底掌握它们,在 3D 的世界中你将寸步难行。
NewbieYoung
2020/10/26
2.3K0
3D图形学线代基础
66. 三维重建——相机几何模型和投影矩阵
在文章29. 小孔相机中,我介绍了小孔相机的成像模型。如果你看了这篇文章,你应该至少有了一个重要印象,即相机是一个将三维物体投影为二维图像的设备。
HawkWang
2022/01/19
3K0
66. 三维重建——相机几何模型和投影矩阵
OpenGL坐标转换推导(十一)
之前我们已经提到在OpenGL中,所有物体都是在一个3D空间里的,但是屏幕都是2D像素数组,所以OpenGL会把3D坐标转变为适应屏幕的2D像素,最终投射到2D的屏幕上去。所以对于每一个顶点坐标都会依次进行model、view、projection三种变换。这三种变换实现代码如下:
PengJie
2021/01/10
2.7K0
相关推荐
OpenGL矩阵变换的数学推导
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档