1. 问题的引出
这个问题的引出又是因为《3D游戏编程大师技巧》这书里面有的问题没讲明白,有的东西又不对。
首先宽高比这个名词的出现是因为我们的PC屏幕不是正方形的,屏幕宽度 : 屏幕高度 就是宽高比。但是我们上次搭建的相机系统的视平面是正方形的,那么当很多物体投影到视平面上后,必然最后完成的是一幅正方形的画,而屏幕是长方形的,这时只有两种办法:
1) 把照片压扁,这样画上的所有物体都被压扁了。
2) 把照片上下多余的两条分别裁下来,只保留屏幕大小的画,这样物体不会走样变形,但是这幅画有一部分看不到了。
哪种是正确的?
以人眼为例,我们的眼睛不可能因为眼睛的外框不是正方形就把东西压扁吧,所以我们要做的是不要多余的上下两条边,而不是把物体压扁。
2. 两种方式
我们可以想到有两种方法来做这件事:
1) 如Hello3DWorld这样,在已经变换到了屏幕系的图像上动手脚,把图像的多余上下边舍弃。
2) 我们将yz平面的FOV不设置为与xz平面的FOV相同,而是使视平面的宽高比和屏幕的宽高比相同。这样,上下裁剪面的方程就会有所变化,直接会将原本会出现在多余的两边的东西裁掉,也就是在3D空间裁剪做完之后,再投影到视平面上的结果已经不是正方形了,而是和屏幕的比例相同,也就是在实质上对纵向的视野进行了操作。这样的好处是在物体剔除时可以剔除更多的物体,也不需要再进行2D图像裁剪了。所以我们应该使用这种方法。
如果修改了上下裁剪面方程,从透视投影到屏幕变换的新的过程将会是这样:
得到的已经是最后的屏幕坐标了。
3. 修改生成上下裁剪面的代码
还记得如何生成上下裁剪面吗?上一篇文章讲的很细了,这里不再重复了。现在所作出的改变就是取那特殊的两点的坐标发生了变化。比如上裁剪面,以前是(-1,1) (1,1),现在变成了(-1, 1/ar) (1, 1/ar)。
把新的坐标代进求叉乘,求新的上裁剪面法向量,得:<0, d, -1/ar>
下裁剪面法向量:<0, -d, -1/ar>
这是新的创建相机的函数代码:
4. 透视投影矩阵的推导
透视投影的原理我们已经非常清楚了,上篇文章介绍了:
x' = x * d / z
y' = y * d / z
推导矩阵的原理苍井空老师也介绍过了。但这次比较特殊,因为我们无法通过变换矩阵让坐标值除以z,只有借助4D齐次坐标了。
我们要这么做:
1) 把x和y放大d
2) 把齐次坐标w的值设置为z,这样因为w != 1,所以整理齐次坐标时,x就变成了x*d/w = x*d/z,y同理。
所以矩阵应该如下:
[ d 0 0 0 ]
[ 0 d 0 0 ]
[ 0 0 1 1 ]
[ 0 0 0 0 ]
如果你也发现这个结果和《3D大师》里面说的完全不一样的话,说明你有认真去推导了,因为在那本书里讲的投影矩阵推导根本狗屁不通。
然后在执行完矩阵变换后,需要把所有的顶点坐标的x,y除以w,这可以非常重要的一步哦。
下面是使用的方式,这个物体投影变换函数可以选择是手动来算还是用矩阵来算:
5. 屏幕变换矩阵的推导
上面那个大图很好的说明了屏幕变换应该怎么做:
1) 放大screen_width / 2。
2) X平移screen_width / 2。
3) Y平移screen_height / 2。
这个矩阵我们完全可以直接写出来了,不就是个缩放和平移的综合嘛:
cam->ScreenWidth / 2, 0, 0, 0,
0,cam->ScreenWidth / 2, 0, 0,
0, 0, 1, 0,
cam->ScreenWidth / 2, cam->ScreenHeight / 2, 0, 1
这个矩阵很直观吧,该缩放的缩放,该平移的平移。
使用的代码如下:
6. 总结
屏幕的宽和高不一致影响的事情有两件,一:相机的宽视野和纵视野不一致。二:变换到屏幕坐标系时需要平移的位移不相同。
7. 代码下载
因为有了灵活的相机系统,有了方便的透视和视口变换矩阵,这次稍微改了一改DEMO,可以使用方向键来调整UVN相机的世界坐标。上下调整Z坐标,左右调整X坐标,注意不要让相机离物体太近,否则会超出相机造成出错,因为我们还没有写裁剪的代码不是吗。
截图:
完整项目源代码下载:>>点击进入下载页<<
分享到:
相关推荐
透视投影是3D固定流水线的重要组成部分,是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume)中,待裁剪完毕后进行透视除法的行为。在算法中它是通过透视矩阵乘法和透视除法两步完成的。 ...
针对视场范围大、变形严重的鱼眼图像,提出了一种基于球面透视投影模型的鱼眼图像匹配算法。在仅估计鱼眼图像焦距和主点的情况下,该方法先将鱼眼图像上的特征点投影到球面透视图像上,通过估计球面透视图像之间的...
透视投影矩阵的推导过程。如果您想征服图形学中的这匹野马的话,这个文件可能是您所需要的
【OpenGL】正交投影和透视投影矩阵(二) —— 结合OpenGL代码验证
透视投影是3D固定流水线的重要组成部分,是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume)中,待裁剪完毕后进行透视除法的行为。在算法中它是通过透视矩阵乘法和透视除法两步完成的。
(1) 在屏幕中心建立三维坐标系Oxyz,x轴水平向右,y轴铅直向上,z轴 垂直于屏幕指向观察者 (2) 建立以三维坐标系Oxyz的原点为体心,边长为a的正立方体线框模型 (3) 使用旋转变换矩阵计算立方体线框模型围绕三维坐标...
D3D透视投影矩阵推导 所谓透视投影矩阵就是为了让画面呈现近大远小的效果
文章目录前言前置知识视见体和标准设备坐标系透视投影原理目的/结果透视投影矩阵的推导1. 计算视锥体的点投影到近平面的x、y坐标2. 规范化近投影面的x、y坐标3. 透视除法消除非线性变换4. 计算视锥体的点投影后的...
绕 X 轴旋转α的旋转矩阵:绕 Y 轴旋转β的旋转矩阵:绕 Z 轴旋转γ的旋转矩阵:透视投影矩阵:一般 OpenGL 使用的透视投影矩阵如果读者有学过 Open
(3)使用旋转变换矩阵计算立方体线框模型围绕三维坐标系原点变换前后 的顶点坐标。 (4)使用双缓冲技术在屏幕上绘制三维立方体线框模型的二维正交投影图。 使用键盘方向键旋转立方体线框模型。 (5)使用...
opengl 基本操作 模型变换 键盘控制 透视投影矩阵
计算机图形学:(5-3)三维视图-投影矩阵.ppt
透视变换(Perspective Transformation)的本质是将图像投影到一个新的视平面,其通用变换公式为: (u,v)为原始图像像素坐标,(x=x’/w’,y=y’/w’)为变换之后的图像像素坐标。透视变换矩阵图解如下: ...
它还可以用于描述3D空间中2D形状的透视投影。 容器 覆盖 组合 核心动画允许通过transform属性将CATransform3D应用于CALayer : let layer = UIView (). layer layer. transform = CATransform3D ( m11 : sX, ...
摄像机模型模拟程序 对模拟的参数进行仿真运算: 仿真的三维物点有12个点,对其进行摄像机模型模拟后产生图像像素点坐标; 这些坐标值保存在the result.txt文档中。...求解转换矩阵函数 求解图像像素点坐标函数
1.编写一段代码,绘制一个球体,然后平移(利用hold on把变换前后的球体放在同一个figure中) 2. 编写一段代码,绘制一个柱体,然后绕x轴旋转60° 3. 用sphere生成多面体,然后对其进行错切...5. 透视投影和平行投影
函数作用: 创建一个表示对称投影视图矩阵,并把它与当前矩阵相乘。Fovy是yz平面上视野的角度,它的值必须为[0.0,180.0]。aspect是宽高比。near far 是视点与近裁剪面和远裁剪面的距离,这个必须为正的。
对轴测投影和透视投影变换矩阵进行了研究, 推出了三维图形变换的统一矩阵。
D3D编程中的投影矩阵原理讲解,正交投影,透视投影等
理解摄像机透视投影模型中的每一个参数的意思,然后在matlab中仿真三维物点根据摄像机的透视投影模型计算出像点,并作出其图像。 模拟摄像机角度并得到旋转矩阵和平移矩阵