D3D透视投影矩阵推导
- 格式:pdf
- 大小:246.98 KB
- 文档页数:4
深入探索透视投影变换最近更新:2013年11月22日-Twinsen编写-本人水平有限,疏忽错误在所难免,还请各位数学高手、编程高手不吝赐教-email: popyy@透视投影是3D固定流水线的重要组成部分,是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume)中,待裁剪完毕后进行透视除法的行为。
在算法中它是通过透视矩阵乘法和透视除法两步完成的。
透视投影变换是令很多刚刚进入3D图形领域的开发人员感到迷惑乃至神秘的一个图形技术。
其中的理解困难在于步骤繁琐,对一些基础知识过分依赖,一旦对它们中的任何地方感到陌生,立刻导致理解停止不前。
没错,主流的3D APIs如OpenGL、D3D的确把具体的透视投影细节封装起来,比如gluPerspective(…)就可以根据输入生成一个透视投影矩阵。
而且在大多数情况下不需要了解具体的内幕算法也可以完成任务。
但是你不觉得,如果想要成为一个职业的图形程序员或游戏开发者,就应该真正降伏透视投影这个家伙么?我们先从必需的基础知识着手,一步一步深入下去(这些知识在很多地方可以单独找到,但我从来没有在同一个地方全部找到,但是你现在找到了 )。
我们首先介绍两个必须掌握的知识。
有了它们,我们才不至于在理解透视投影变换的过程中迷失方向(这里会使用到向量几何、矩阵的部分知识,如果你对此不是很熟悉,可以参考《向量几何在游戏编程中的使用》系列文章)。
齐次坐标表示透视投影变换是在齐次坐标下进行的,而齐次坐标本身就是一个令人迷惑的概念,这里我们先把它理解清楚。
根据《向量几何在游戏编程中的使用6》中关于基的概念。
对于一个向量v以及基oabc,可以找到一组坐标(v1,v2,v3),使得v = v1 a + v2 b + v3 c (1)而对于一个点p,则可以找到一组坐标(p1,p2,p3),使得p – o = p1 a + p2 b + p3 c (2)从上面对向量和点的表达,我们可以看出为了在坐标系中表示一个点(如p),我们把点的位置看作是对这个基的原点o所进行的一个位移,即一个向量——p – o(有的书中把这样的向量叫做位置向量——起始于坐标原点的特殊向量),我们在表达这个向量的同时用等价的方式表达出了点p:p = o + p1 a + p2 b + p3 c (3)(1)(3)是坐标系下表达一个向量和点的不同表达方式。
2d到3d转换计算公式
2D到3D的转换可以通过不同的方法实现,其中最常用的方法是透视投影。
透视投影是一种将二维平面上的点映射到三维空间中的方法,可以模拟人眼观察物体时的透视效果。
在透视投影中,可以使用以下计算公式将二维坐标转换为三维坐标:
x' = x (d / z)。
y' = y (d / z)。
z' = d.
其中,(x, y)是二维平面上的点坐标,(x', y', z')是转换后的三维坐标,d是观察者与投影平面的距离,z是物体在二维平面上的深度。
这个公式的意思是,通过将二维坐标的x和y值乘以观察者与投影平面的距离与物体在二维平面上的深度的比例,可以得到转换
后的三维坐标的x'和y'值。
而z'的值则等于观察者与投影平面的距离。
需要注意的是,这个公式只能将二维坐标转换为三维坐标的近似值,因为在实际情况中,存在着很多其他因素,如相机的镜头参数、透视效果的强度等,都会影响到最终的转换结果。
除了透视投影,还有其他的方法可以进行2D到3D的转换,如立体投影、三角测量等,每种方法都有其特定的计算公式和应用场景。
具体使用哪种方法,取决于你的需求和具体情况。
总之,2D到3D的转换是一个复杂的过程,需要考虑多个因素和采用适当的方法来实现。
以上是透视投影方法的计算公式,希望对你有所帮助。
透视投影是3D固定流水线的重要组成部分,是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume)中,待裁剪完毕后进行透视除法的行为。
在算法中它是通过透视矩阵乘法和透视除法两步完成的。
透视投影变换是令很多刚刚进入3D图形领域的开发人员感到迷惑乃至神秘的一个图形技术。
其中的理解困难在于步骤繁琐,对一些基础知识过分依赖,一旦对它们中的任何地方感到陌生,立刻导致理解停止不前。
没错,主流的3D APIs如OpenGL、D3D的确把具体的透视投影细节封装起来,比如gluPerspective(…) 就可以根据输入生成一个透视投影矩阵。
而且在大多数情况下不需要了解具体的内幕算法也可以完成任务。
但是你不觉得,如果想要成为一个职业的图形程序员或游戏开发者,就应该真正降伏透视投影这个家伙么?我们先从必需的基础知识着手,一步一步深入下去(这些知识在很多地方可以单独找到,但我从来没有在同一个地方全部找到,但是你现在找到了)。
我们首先介绍两个必须掌握的知识。
有了它们,我们才不至于在理解透视投影变换的过程中迷失方向(这里会使用到向量几何、矩阵的部分知识,如果你对此不是很熟悉,可以参考可以找到一组坐标(v1,v2,v3),使得v = v1 a + v2 b + v3 c (1)而对于一个点p,则可以找到一组坐标(p1,p2,p3),使得p – o = p1 a + p2 b + p3 c (2)从上面对向量和点的表达,我们可以看出为了在坐标系中表示一个点(如p),我们把点的位置看作是对这个基的原点o所进行的一个位移,即一个向量——p – o(有的书中把这样的向量叫做位置向量——起始于坐标原点的特殊向量),我们在表达这个向量的同时用等价的方式表达出了点p:p = o + p1 a + p2 b + p3 c (3)(1)(3)是坐标系下表达一个向量和点的不同表达方式。
这里可以看出,虽然都是用代数分量的形式表达向量和点,但表达一个点比一个向量需要额外的信息。
透视投影的原理和实现透视投影的原理和实现摘要:透视投影是3D渲染的基本概念,也是3D程序设计的基础。
掌握透视投影的原理对于深⼊理解其他3D渲染管线具有重要作⽤。
本⽂详细介绍了透视投影的原理和算法实现,包括透视投影的标准模型、⼀般模型和屏幕坐标变换等,并通过VC实现了⼀个演⽰程序。
1 概述在计算机三维图像中,投影可以看作是⼀种将三维坐标变换为⼆维坐标的⽅法,常⽤到的有正交投影和透视投影。
正交投影多⽤于三维健模,透视投影则由于和⼈的视觉系统相似,多⽤于在⼆维平⾯中对三维世界的呈现。
透视投影(Perspective Projection)是为了获得接近真实三维物体的视觉效果⽽在⼆维的纸或者画布平⾯上绘图或者渲染的⼀种⽅法,也称为透视图[1]。
它具有消失感、距离感、相同⼤⼩的形体呈现出有规律的变化等⼀系列的透视特性,能逼真地反映形体的空间形象。
透视投影通常⽤于动画、视觉仿真以及其它许多具有真实性反映的⽅⾯。
2 透视投影的原理基本的透视投影模型由视点E和视平⾯P两部分构成(要求 E不在平⾯P上)。
视点可以认为是观察者的位置,也是观察三维世界的⾓度。
视平⾯就是渲染三维对象透视图的⼆维平⾯。
如图1所⽰。
对于世界中的任⼀点X,构造⼀条起点为E并经过X点的射线R,R与平⾯P的交点Xp即是X点的透视投影结果。
三维世界的物体可以看作是由点集合 { Xi} 构成的,这样依次构造起点为E,并经过点Xi的射线Ri,这些射线与视平⾯P的交点集合便是三维世界在当前视点的透视图,如图2所⽰。
图1 透视投影的基本模型图2 透视图成像原理基本透视投影模型对视点E的位置和视平⾯P的⼤⼩都没有限制,只要视点不在视平⾯上即可。
P⽆限⼤只适⽤于理论分析,实际情况总是限定P为⼀定⼤⼩的矩形平⾯,透视结果位于P之外的透视结果将被裁减。
可以想象视平⾯为透明的玻璃窗,视点为玻璃窗前的观察者,观察者透过玻璃窗看到的外部世界,便等同于外部世界在玻璃窗上的透视投影(总感觉不是很恰当,但想不出更好的⽐喻了)。
投影矩阵的推导(OpenGL D3D)OpenGL矩阵推导——模型视图变化在三维编程中,模型视图变换是从三维世界到二维屏幕中一个很重要的变换,但是这个变换往往很多人都不太理解,要么是事而非。
而这方面的文章不是太少就是讲的太浅没有真正的理解模型视图变换,本人在这个过程中曾经走过很多歪路,不过好在最终在自己的不懈努力下终于降伏了这只猛虎。
本人就以自己的理解,通过矩阵推导过程一步一步来了解模型视图变化,最后通过两个OpenGl的程序来进一步理解模型视图矩阵。
先从一个基本的模型视图—透视投影变换讲起。
透射投影是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume 以下简称CVV)中,待裁剪完毕后进行透视除法的行为。
透视投影变换是令很多刚刚进入3D图形领域的开发人员感到迷惑乃至神秘的一个图形技术。
其中的理解困难在于步骤繁琐,对一些基础知识过分依赖,一旦对它们中的任何地方感到陌生,立刻导致理解停止不前。
主流的3D APIs 都把透射投影的具体细节进行了封装,从而只需一个函数便可生成一个透射投影矩阵比如gluPerspective(),使得我们不需要了解其算法便可实现三维到二维的转化,然而实事是,一些三维图形或游戏开发人员遇到一些视图矩阵的问题往往会不知所措,比如视景体裁剪。
以下部分内容是从别处那转过来的,主要感谢Twinsen和一个叫丁欧南的高中生。
透视投影变换是在齐次坐标下进行的,而齐次坐标本身就是一个令人迷惑的概念,这里我们先把它理解清楚。
齐次坐标对于一个向量v以及基oabc,可以找到一组坐标(v1,v2,v3),使得v = v1 a + v2 b + v3 c (1)而对于一个点p,则可以找到一组坐标(p1,p2,p3),使得p–o = p1 a + p2 b + p3 c (2)从上面对向量和点的表达,我们可以看出为了在坐标系中表示一个点(如p),我们把点的位置看作是对这个基的原点o所进行的一个位移,即一个向量——p –o(有的书中把这样的向量叫做位置向量——起始于坐标原点的特殊向量),我们在表达这个向量的同时用等价的方式表达出了点p:p = o + p1 a + p2 b + p3 c (3)(1)(3)是坐标系下表达一个向量和点的不同表达方式。
投影矩阵的计算过程投影矩阵的计算过程3d模型经过世界坐标变换、相机坐标变换后,下⼀步需要投影变换。
投影变换的⽬的就是要把相机空间转换到标准视图空间,在这个空间的坐标都是正规化的,也就是坐标范围都在[-1,1]之间,之所以转换到这个空间是为了后续操作更⽅便。
下⾯的讨论都是以列向量来表⽰,这样在变换操作时,采⽤的是矩阵左乘法,如果采⽤的是⾏向量的话,那就相反,矩阵右乘法即是向量在左边乘以变换矩阵。
采⽤哪种表⽰并不影响结果,只需要把该种表⽰下得出的变换矩阵转置⼀下,就是采⽤另外⼀种表⽰模式需要的结果。
常见的投影有两种,正交投影和透视投影,正交投影相对来说更简单,所以先来看看正交投影。
最简单的正交变换矩阵1 0 0 00 1 0 00 0 0 1这个正交变换是不可逆变换,变换后x和y保留,z变成了0,在实际应⽤中,更常见的情况是限定x、y、z在⼀定的范围内的进⾏投影变换,⽐如x[l,r],y[b,t],z[n,f]。
那么要把这段空间中的点变换到-1和1之间,只要完成两个变换,⾸先把坐标轴移到中⼼,然后进⾏缩放就可以了。
采⽤列向量的话,那就是缩放矩阵乘以平移矩阵。
2/(r-l) 0 0 0 1 0 0 -(r+l)/2 2/(r-l) 0 0 -(r+l)/(r-l)0 2/(t-b) 0 0 x 0 1 0 -(b+t)/2 = 0 2/(t-b) 0 -(t+b)/(t-b)0 0 2/(f-n) 0 0 0 1 -(n+f)/2 0 0 2/(f-n) -(f+n)/(f-n)0 0 0 1 0 0 01 0 0 0 1透视投影类⽐于我们⼈眼系统,看⼀个物体,会有远⼩近⼤的效果。
在转换到相机空间后,相机是这个空间的原点,和正交投影体是⼀个长⽅体或者⽴⽅体不同,透视投影体是⼀个锥体被近平⾯截取掉头部剩下的空间。
假定仍然采⽤上⾯的坐标表⽰。
在透视投影下,空间上⾯的任何⼀点P投影到近平⾯上某点q,通过三⾓⼏何学我们可以得到q x=p x*n/p z ,y点同理。
深入探索正交投影变换之前我们在《深入探索透视投影变换》以及《深入探索透视投影变换(续)》中研究了OpenGL、D3D以及M3G的透视投影变换的原理以及生成方法。
这些方法在当前的主流图形API 中得到了普遍使用。
但关于投影应用,还有一类经常使用的投影方式需要我们深入理解——正交投影,我们在本篇文章里面研究它(这里假设读者已经看过前两篇文章,并理解了绝大多数的理论,因为正交投影比透视投影的推导关系简单得多,因此我们的推导会非常得快,如果读者有任何的不解,请参考前两篇文章或者通过email联系我)。
在具体研究之前我觉得有必要把平面投影的分类简单介绍一下,目的是为了让大家有一个总体的认识,从而更好的理解这个知识体系。
请看下图:平面投影分为平行投影和透视投影两种类型,后者我们在前两篇文章中介绍了。
平行投影则是具有矩形观察体的投影方式(透视投影则是视锥观察体),它不会根据物体离视点的远近缩放物体(透视投影则会)。
平行投影可以分成侧投影和正交投影两种类型。
这两种类型如何区分呢?我们继续看图吧:上图中,v是投影平面,n是它的法线。
p和q是平面外两点,p’和q’分别是它们在平面上的投影点。
q的投影方向向量为Q = 单位化(q’-q),而p的投影方向向量为P = 单位化(p’-p),其中Q不平行于n而P平行于n,则q的投影叫做侧投影,而p的投影叫做正交投影。
正交投影是我们今天的研究对象。
实际上上面对平面投影的分类还可以继续向下细分,比如透视投影可以分为一灭点、二灭点以及三灭点透视投影。
侧投影则可以继续分为散点侧投、斜二轴侧投等等。
而正交投影则可以分成轴侧投影以及多视点正交投影等等。
如果读者对此感兴趣,可以参考相关的图形学教程。
接下来我们研究正交投影。
分别介绍OpenGL、D3D以及M3G的。
我们的环境约定(左右手坐标系、行列向量乘法、CVV范围)仍然尊重相应API自己的设置。
OpenGL正交投影变换下图是OpenGL的右手坐标系中观察空间的情形,我们看到的是正交投影的矩形观察体,原点是相机位置,n是近裁剪平面到相机平面的距离,f是远裁剪平面到相机平面的距离。
OpenGL学习脚印:投影矩阵的推导OpenGL学习脚印: 投影矩阵的推导写在前面本节内容翻译和整理自songho的博客《OpenGL Projection Matrix》内容,以供自己和初学者熟悉投影矩阵推导过程。
通过本节,你可以了解到:•投影矩阵计算的阶段•透视投影和正交投影的矩阵推导本节的要点就在于: 阅读时,自己拿笔推导一遍。
1.概览计算机屏幕是2维的,OpenGL渲染的3D场景必须以2D形式的图像投影到屏幕上。
GL_PROJECTION 矩阵就是用来设置投影变换的。
首先,它将所有顶点从眼坐标(照相机坐标)转换到裁剪坐标系下。
然后,这些裁剪坐标通过透视除法,即除以裁剪坐标中w分量,转换到归一化设备坐标系(NDC)。
一个由视锥裁剪的三角形因此,我们要记住,裁剪(视锥剔除frustum culling)和NDC转换都集成到了GL_PROJECTION 矩阵。
接下来的部分描述了怎么样通过left, right, bottom, top, near and far 这6个界限参数来构造投影矩阵。
注意:视锥剔除是在裁剪坐标系中进行的,并且恰好在透视除法之前进行。
裁剪坐标xc, yc 和 zc 通过与wc比较来进行测试。
如果某个坐标值比Wc小或者比Wc大,那么这个顶点将被丢弃。
然后,OpenGL会重新在裁剪进行的地方构造多边形的边缘。
补充内容:实际上,眼坐标系下坐标在乘以投影矩阵后,裁剪测试和透视除法都是由GPU来执行的。
而后面这两个过程处理的裁剪坐标系数据都是由投影矩阵变换的。
1. 裁剪测试也即视锥剔除-Wc < Xc,Yc,Zc < Wc2. NDC透视除法Xn = Xc / Wc Yn = Yc / Wc Zn = Zc / Wc这里需要注意的是,我们在构造16个参数的投影矩阵的同时,不仅要考虑到裁剪,还要考虑到透视除法的过程。
这样,最终的NDC坐标才会满足:-1 < Xn,Yn,Zn < 12.透视投影在透视投影中,在眼坐标下截头椎体(a truncated pyramid frustum)内的3D点被映射到NDC下一个立方体中;x坐标从[l,r]映射到[-1,1],y坐标从[b,t]映射到[-1,1],z坐标从[n,f]映射到[-1,1]。
透视投影变换的推导过程-3D基础知识感觉很多书上都没讲清楚透视投影变换的推导过程,自己推导了下,以前一直含糊的关于方形/非方形的视平面和屏幕的宽高比的问题也有了答案.本文组织如下:1.相机空间到视平面的变换2.视平面到屏幕的变换3.综合4.一般情形1.相机空间到视平面的变换* p (xc,0, zc)/ |/ |/ |X |/ |^ *p |(xp,0,zp)| / | || / | || / | |C(cam) |/ | |--------*----|----*------------->Z0 dx zc(X-Z平面的投影示图)a.透视投影一般的视景体为棱台,相机空间的物体会投影到视平面z=d,这里考虑左手坐标系,矩阵使用行优先方式。
如图所示,由相似三角形知识可知相机空间中的物体投影到视平面上的坐标为:xp = xc*(dx/zc)yp = yc*(dy/zc)其中,xc,yc,zc为相机空间坐标,xp,yp,zp为视平面坐标,dx,dy为x,y轴向的视距view distance,视平面到camera的距离,故相机空间投影到视平面上的矩阵Tcp为:|dx 0 0 0 ||0 dy 0 0 ||0 0 1 1 ||0 0 0 0 |(验证:T cp右乘点p(xc,yc,zc,1)得点p (xc*dx, yc*dy, zc, zc),转换为3D坐标为(xc*dx/zc, yc*dy/zc, 1),正确。
)*************************************************************** *****注:因为转换过程中点使用的是4D齐次坐标,所以最后需转换为3D坐标。
4D齐次坐标(x,y,z,w)转换为3D坐标的方法为除以w分量,即对应3D坐标为(x/w,y/w,z/w)。
*************************************************************** *****考虑dx/zc和dy/zc项,如果dx != dy,则投影后x,y的比例会发生变化(原因:投影前坐标比例为xc/yc,投影后为xp/yp = xc*(dx/zc)/yc*(dy/zc) = xc*dx/yc*dy),从而投影后的图像的x,y比例会发生变形。