详解OpenGL中的各种变换(投影变换,模型变换,视图变换)(二)——投影变换
2015-09-05 23:41
423 查看
下面介绍投影变换矩阵。这个相比较上一遍的就比较难了。主要分为透视投影矩阵和正交投影矩阵,本文主要介绍透视投影矩阵,正交比较简单,就给出矩阵形式。
(1)透视投影变换矩阵
我们先来说一下透视投影需要哪些参数。如图1所示,深色部分表示最终显示的区域。照相机的z轴是穿过视锥体正中心的,显示区域离相机最近的平面我们称为Znear,最远的平面我们称为Zfar。其中Znear就是最终的投影窗口。所以我们要把Znear的宽映射到坐标[-1,1],把Znear的高映射到坐标[-1,1],把Znear到Zfar的深度距离映射到坐标[-1,1]。因为最后的OpenGL绘制的区域其实就是一个从(-1,-1,-1)到(1,1,1)的一个立方体。而且这样映射还有个好处,就是绘制的时候靠近Znear的对象要比靠近Zfar的对象大。
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905082628811-1294843623.png)
图1
根据这些参数我们可以得到投影变换矩阵。首先,对于这个矩阵,我们先来看x轴和y轴。我们结合上图,根据相似三角形可以得到:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905152449498-660005860.png)
图2
我们化简一下可以得到Yproj=Znear*x/z和Xproj=Znear*y/z。之后我们将齐次坐标的w分量设为z,就可以得到Yproj=Znear*x和Xproj=Znear*y。再将坐标映射到[-1,1],除以投影窗口的长宽即可。我们得到部分透视投影矩阵:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905153815295-123778551.png)
图3
我们再来看z轴。其实z轴映射也非常简单。我们假设f(z)=A*z+B,当齐次坐标的w分量为z时,那么实际上z轴的坐标为A+B/z。我们根据映射关系得到下面两个式子:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905154631248-181460439.png)
图4
再根据这两个式子,求出A和B的值(具体求解就忽略了,得到的结果就是下面矩阵第三行的两个值)。最终得到完整的透视投影变换矩阵:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905154954154-1565632689.png)
图5
我们还可以用另一种方式来表达透视投影。这种方式一共有四个变量。
透视的角度fovy。如图6所示,fovy表示的是照相机所看到的范围。
投影窗口的宽高比aspect。如图6所示,aspect就是Znear平面的宽高比。
显示区域离相机最近的距离near和离相机最远的距离far。这两个量与前面都是一样的。
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905084128904-1130580001.png)
图6
这个表达下的透视投影矩阵如下(计算过程跟上面一种基本一致):
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905155306967-1983054591.png)
图7
(2)正交投影变换矩阵
正交投影就比较简单了。如图8所示,显示区域就是一立方体。因为没有近大远小的特性,齐次坐标的w分量不需要变化,设为1.0就可以了。另外,我们也需要把x轴,y轴,z轴分别映射到坐标[-1,1]。计算过程也和透视投影变化矩阵类似。
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905155840701-573727735.png)
图8
下面是正交投影变换矩阵:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905160948732-1039928572.png)
图9
(1)透视投影变换矩阵
我们先来说一下透视投影需要哪些参数。如图1所示,深色部分表示最终显示的区域。照相机的z轴是穿过视锥体正中心的,显示区域离相机最近的平面我们称为Znear,最远的平面我们称为Zfar。其中Znear就是最终的投影窗口。所以我们要把Znear的宽映射到坐标[-1,1],把Znear的高映射到坐标[-1,1],把Znear到Zfar的深度距离映射到坐标[-1,1]。因为最后的OpenGL绘制的区域其实就是一个从(-1,-1,-1)到(1,1,1)的一个立方体。而且这样映射还有个好处,就是绘制的时候靠近Znear的对象要比靠近Zfar的对象大。
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905082628811-1294843623.png)
图1
根据这些参数我们可以得到投影变换矩阵。首先,对于这个矩阵,我们先来看x轴和y轴。我们结合上图,根据相似三角形可以得到:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905152449498-660005860.png)
图2
我们化简一下可以得到Yproj=Znear*x/z和Xproj=Znear*y/z。之后我们将齐次坐标的w分量设为z,就可以得到Yproj=Znear*x和Xproj=Znear*y。再将坐标映射到[-1,1],除以投影窗口的长宽即可。我们得到部分透视投影矩阵:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905153815295-123778551.png)
图3
我们再来看z轴。其实z轴映射也非常简单。我们假设f(z)=A*z+B,当齐次坐标的w分量为z时,那么实际上z轴的坐标为A+B/z。我们根据映射关系得到下面两个式子:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905154631248-181460439.png)
图4
再根据这两个式子,求出A和B的值(具体求解就忽略了,得到的结果就是下面矩阵第三行的两个值)。最终得到完整的透视投影变换矩阵:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905154954154-1565632689.png)
图5
我们还可以用另一种方式来表达透视投影。这种方式一共有四个变量。
透视的角度fovy。如图6所示,fovy表示的是照相机所看到的范围。
投影窗口的宽高比aspect。如图6所示,aspect就是Znear平面的宽高比。
显示区域离相机最近的距离near和离相机最远的距离far。这两个量与前面都是一样的。
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905084128904-1130580001.png)
图6
这个表达下的透视投影矩阵如下(计算过程跟上面一种基本一致):
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905155306967-1983054591.png)
图7
(2)正交投影变换矩阵
正交投影就比较简单了。如图8所示,显示区域就是一立方体。因为没有近大远小的特性,齐次坐标的w分量不需要变化,设为1.0就可以了。另外,我们也需要把x轴,y轴,z轴分别映射到坐标[-1,1]。计算过程也和透视投影变化矩阵类似。
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905155840701-573727735.png)
图8
下面是正交投影变换矩阵:
![](http://images2015.cnblogs.com/blog/791740/201509/791740-20150905160948732-1039928572.png)
图9
相关文章推荐
- USBKey使用openssl链接
- Linux下编程获取本地IP地址的常见方法
- 【Linux 学习】数据流重导向
- Linux内存管理之mmap详解
- 架构师速成-架构体系 - for5million - 博客园
- angular attrs.$observe和$scope.$watch的区别
- centos单用户 救援 运行级别 yum,单用户模式,救援模式,inittab :启动级别 e2fsck wetty mingetty 物理终端 /dev/console 虚拟终端 /dev/tty(0,6) 模拟终端 /dev/pts/# grub-md5-crypt 给grub加密码 initrd 第二节课
- Linux内存管理
- linux bash基础
- Linux 内核的排队自旋锁
- win7使用eclipse连接hadoop集群,运行mapreduce报错之:org.apache.hadoop.security.AccessControlException
- docker 入门准备step1
- Codis 高可用负载均衡群集的搭建与使用
- 磁盘分区格式化,挂载,交换分区的挂载
- Linux内核switch_to宏实现进程切换的原理
- CentOS Linux服务器安全设置
- Linux shell基本运算需要注意空格
- 使用PowerShell简化我的工作
- Linux下安装虚拟机jre-8u60-linux-x64.tar.gz
- Linux下安装SVN服务(CentOS7下)