投影矩阵的推导

投影矩阵的推导
投影矩阵的推导

投影矩阵的推导(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)是坐标系下表达一个向量和点的不同表达方式。这里可以看出,虽然都是用代数分量的形式表达向量和点,但表达一个点比一个向量需要额外的信息。如果我写出一个代数分量表达(1, 4, 7),谁知道它是个向量还是个点!

我们现在把(1)(3)写成矩阵的形式:

这里(a,b,c,o)是坐标基矩阵,右边的列向量分别是向量v和点p在基下的坐标。这样,向量和点在同一个基下就有了不同的表达:3D向量的第4个代数分量是0,而3D点的第4个代数分量是1。像这种这种用4个代数分量表示3D几何概念的方式是一种齐次坐标表示。

“齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易用于进行仿射(线性)几何变换。”——F.S. Hill, JR

这样,上面的(1, 4, 7)如果写成(1,4,7,0),它就是个向量;如果是(1,4,7,1),它就是个点。

下面是如何在普通坐标(OrdinaryCoordinate)和齐次坐标(Homogeneous Coordinate)之间进行转换:

从普通坐标转换成齐次坐标时,

如果(x,y,z)是个点,则变为(x,y,z,1);

如果(x,y,z)是个向量,则变为(x,y,z,0)

从齐次坐标转换成普通坐标时,

如果是(x,y,z,1),则知道它是个点,变成(x,y,z);

如果是(x,y,z,0),则知道它是个向量,仍然变成(x,y,z)

以上是通过齐次坐标来区分向量和点的方式。从中可以思考得知,对于平移T、旋转R、缩放S这3个最常见的仿射变换,平移变

换只对于点才有意义,因为普通向量没有位置概念,只有大小和方向,这可以通过下面的式子清楚地看出:

而旋转和缩放对于向量和点都有意义,你可以用类似上面齐次表示来检测。从中可以看出,齐次坐标用于仿射变换非常方便。

此外,对于一个普通坐标的点P=(Px, Py, Pz),有对应的一族

齐次坐标(wPx, wPy,wPz, w),其中w不等于零。比如,P(1, 4, 7)的齐次坐标有(1, 4, 7, 1)、(2, 8, 14, 2)、(-0.1, -0.4, -0.7, -0.1)等等。因此,如果把一个点从普通坐标变成齐次坐标,给x,y,z乘上同一个非零数w,然后增加第4个分量w;如

果把一个齐次坐标转换成普通坐标,把前三个坐标同时除以第4个坐标,然后去掉第4个分量。

由于齐次坐标使用了4个分量来表达3D概念,使得平移变换可以使用矩阵进行,从而如F.S. Hill, JR所说,仿射(线性)变换的进行更加方便。由于图形硬件已经普遍地支持齐次坐标与矩阵乘法,因此更加促进了齐次坐标使用,使得它似乎成为图形学中的一个标准。

简单的线性插值

线性插值我举的是丁欧南的温度计的例子:

已知有一破温度计(何以谓破?刻度之间间距虽平均,但间距或大于或小于标准值,谓之破),当其插入0 0C水里时显示为50C,当其插入1000C的沸水中时显示为900C,问:当实际水温为500C时此破温度计显示的值是多少?

解:因刻度均匀,所以刻度之间的比例与好温度计相同,由此:设显示的数为T,

(90-T)/(T-5)=(100-50)/(50-0) 解出T=47.5 0C.

结论:由一个数域(如题目中的好温度计两个端点[0,100])映射到另一个数域(如题目中的破温度计的两个端点[5,90])时,如果两个数域都是线性(就如题目中暗示的刻度平均),那么它们对应点成比例(比如50和47.5这一对端点).

这道题的应用是把一组坐标映射到另一个范围,这将在介绍

NDC(Normalized Device Coordinate,归一化的设备坐标)时用到.

透视投影变换

好,有了上面两个理论知识,我们开始分析这次的主角——透视投影变换。这里我们选择OpenGL的透视投影变换进行分析,其

他的APIs会存在一些差异,但主体思想是相似的,可以类似地

推导。经过相机矩阵的变换,顶点被变换到了相机空间。这个时候的多边形也许会被视锥体裁剪,但在这个不规则的体中进行裁剪并非那么容易的事情,所以经过图形学前辈们的精心分析,裁剪被安排到规则观察体(CanonicalView Volume, CVV)中进行,CVV是一个正方体,x, y, z的范围都是[-1,1],多边形裁剪就是用这个规则体完成的。所以,事实上是透视投影变换由两步组成:

1)用透视变换矩阵把顶点从视锥体中变换到裁剪空间的CVV中。2) CVV裁剪完成后进行透视除法(一会进行解释)。

我们一步一步来,我们先从一个方向考察投影关系。

上图是右手坐标系中顶点在相机空间中的情形。设P(x,z)是经过相机变换之后的点,视锥体由eye——眼睛位置,np——近裁剪平面,fp——远裁剪平面组成。N是眼睛到近裁剪平面的距离,F是眼睛到远裁剪平面的距离。投影面可以选择任何平行于近裁剪平面的平面,这里我们选择近裁剪平面作为投影平面。设P’(x’,z’)是投影之后的点,则有z’ = -N。通过相似三角形性质,我们有关系:

同理,有

这样,我们便得到了P投影后的点P’

从上面可以看出,投影的结果z’始终等于-N,在投影面上。实际上,z’对于投影后的P’已经没有意义了,这个信息点已经没用了。但对于3D图形管线来说,为了便于进行后面的片元操作,例如z缓冲消隐算法,有必要把投影之前的z保存下来,方便后面使用。因此,我们利用这个没用的信息点存储z,处理成:

这个形式最大化地使用了3个信息点,达到了最原始的投影变换的目的,但是它太直白了,有一点蛮干的意味,我感觉我们最终的结果不应该是它,你说呢?我们开始结合CVV进行思考,把它写得在数学上更优雅一致,更易于程序处理。假入能够把上面写成这个形式:

那么我们就可以非常方便的用矩阵以及齐次坐标理论来表达投影变换:

其中

哈,看到了齐次坐标的使用,这对于你来说已经不陌生了吧?这个新的形式不仅达到了上面原始投影变换的目的,而且使用了齐

次坐标理论,使得处理更加规范化。注意在把变成

的一步我们是使用齐次坐标变普通坐标的规则完成的。这一步在透视投影过程中称为透视除法(Perspective Division),这是透视投影变换的第2步,经过这一步,就丢弃了原始的z值(得到了CVV中对应的z值,后面解释),顶点才算完成了投影。而在这两步之间的就是CVV裁剪过程,所以裁剪

空间使用的是齐次坐标,主要原因在于透视除法会损失一些必要的信息(如原始z,第4个-z保留的)从而使裁剪变得更加难以处理,这里我们不讨论CVV裁剪的细节,只关注透视投影变换的两步。

矩阵

就是我们投影矩阵的第一个版本。你一定会问为什么要把z写成

有两个原因:

1)P’的3个代数分量统一地除以分母-z,易于使用齐次坐标变为普通坐标来完成,使得处理更加一致、高效。

2)后面的CVV是一个x,y,z的范围都为[-1,1]的规则体,便于进行多边形裁剪。而我们可以适当的选择系数a和b,使得这个式子在z = -N的时候值为-1,而在z = -F的时候值为1,从而在z方向上构建CVV。

接下来我们就求出a和b:

这样我们就得到了透视投影矩阵的第一个版本:

使用这个版本的透视投影矩阵可以从z方向上构建CVV,但是x 和y方向仍然没有限制在[-1,1]中,我们的透视投影矩阵的下一个版本就要解决这个问题。

为了能在x和y方向把顶点从Frustum情形变成CVV情形,我们开始对x和y进行处理。先来观察我们目前得到的最终变换结果:

我们知道-Nx / z的有效范围是投影平面的左边界值(记为left)和右边界值(记为right),即[left, right],-Ny / z则为[bottom, top]。而现在我们想把-Nx / z属于[left, right]映射到x属

于[-1, 1]中,-Ny / z属于[bottom, top]映射到y属于[-1, 1]中。你想到了什么?哈,就是我们简单的线性插值,你都已经掌握了!我们解决掉它:

则我们得到了最终的投影点:

下面要做的就是从这个新形式出发反推出下一个版本的透视投

影矩阵。注意到是经过透视除法的形式,而P’只变化了x和y分量的形式,az+b和-z是不变的,则我们做透视除法的逆处理——给P’每个分量乘上-z,得到

而这个结果又是这么来的:

则我们最终得到:

上面是一般情况,我们要把它变成特殊性版本,即gluPerspective,它是一种左右对称的投影形式,因此我们从对x和y进行插值的那一步来看:

那一步来看:

销掉两边的1/2,得到:

则我们反推出透视投影矩阵:

这就是gluPerspective的投影矩阵了。

结论和用法:相机空间中的顶点,如果在视锥体中,则变换后就在CVV中。如果在视锥体外,变换后就在CVV外。而CVV本身的规则性对于多边形的裁剪很有利。OpenGL在构建透视投影矩阵

的时候就使用了M的形式。注意到M的最后一行不是(0 0 0 1)

而是(0 0 -1 0),因此可以看出透视变换不是一种仿射变换,它是非线性的。另外一点你可能已经想到,对于投影面来说,它的宽和高大多数情况下不同,即宽高比不为1,比如640/480。而CVV的宽高是相同的,即宽高比永远是1。这就造成了多边形的

失真现象,比如一个投影面上的正方形在CVV的面上可能变成了一个长方形。解决这个问题的方法就是在对多变形进行透视变换、裁剪、透视除法之后,在归一化的设备坐标(NormalizedDevice Coordinates)上进行的视口(viewport)变换中进行校正,它会把归一化的顶点之间按照和投影面上相同的比例变换到视口中,从

而解除透视投影变换带来的失真现象。进行校正前提就是要使投影平面的宽高比和视口的宽高比相同。

而r-l和t-b可以分别看作是投影平面的宽w和高h。如果我们不知道right、left、top以及bottom这几个参量,也可以根据视野(FOV – Field Of View)参量来求得。下面是两个平面的视野关系图:

其中,两个fov分别是在x-z以及y-z平面上的视野。如果只给了一个视野,也可以通过投影平面的宽高比计算出来:

用一个视野算出w或者h,然后用宽高比算出h或者w。

我们可以通过一个例子来证明我们矩阵的正确性:

void OpenGlCom::ReSize()

{

RECTrct ;

GetClientRect(m_Hwnd,&rct);

intm_view_width = rct.right- rct.left;

intm_view_height = rct.bottom - rct.top;

glViewport(0,0,m_view_width,m_view_height);

float nearz =5.0;

float farz =80000;

float AspectRatio =float(m_view_height)/

float(m_view_width);

float ViewAngleH =90 * (PI / 180);//90度

float ViewAngleV = atan(tan(ViewAngleH/2) * AspectRatio)* 2;

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

GLfloatm[16];

::ZeroMemory(m,16*sizeof(float));

//////m[8],m[9]=0表示对称视椎体即

gluPerspective///////////

m[0] = 1.0 /tan(ViewAngleV / 2);

m[5] = m[0]*AspectRatio;

m[10] = -(farz +nearz) / (farz - nearz);

m[11] = -1;

m[14] = - 2 * farz *nearz / (farz - nearz); glMultMatrixf(m);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void OpenGlCom::draw()

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glPushMatrix();

glDepthFunc(GL_LEQUAL);

glEnable(GL_DEPTH_TEST);

glBegin(GL_TRIANGLE_FAN);

glTranslatef(0, 0,10.0f);//往视点方向平移10单位显示更大glColor3f(0.8f, 0.8f, 0.6f);

glVertex3f(0,0,-20);

glVertex3f(30,20,-40);

glVertex3f(40,10,-30);

glPopMatrix();

}

我们看看在gluPerspective图形有什么变化呢

将ReSize()改成:

{

RECTrct ;

GetClientRect(m_Hwnd,&rct);

intm_view_width = rct.right- rct.left;

intm_view_height = rct.bottom - rct.top; glViewport(0,0,m_view_width,m_view_height); glMatrixMode(GL_PROJECTION);

glLoadIdentity();

floatfAspect = float(m_view_width) /

float(m_view_height);

gluPerspective(90.0,fAspect, 5.0, 80000.0); glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

接下来,再试试看glFrustum()实现的效果:

将ReSize()改成:

{

摄像机内外参计算过程

摄像机内外参计算过程 罗海风2011-2-28 1.对内参的初始化: 涉及函数:init_intrinsic_param_fisheye.m 输入:x_1,x_2,x_3,…--角点的图像坐标,X_1,X_2,X_3,…--角点的世界坐标; 输出:所有内参,包括摄像机焦距fc,摄像机坐标系原点在图像上的坐标cc,几何畸变系数kc,斜交系数alpha_c,摄像机矩阵KK(包含以上系数)。 焦距的初始值:fc= max(,) _ max(,) nx ny f init nx ny π π ?? ?? =?? ?? ?? ?? 原点坐标的初始值设为图像中心处,即cc= 0.50.5 _ 0.50.5 nx c init ny - ?? =?? - ?? 计算内参时不考虑畸变,畸变系数初始值为零,即kc= 0 _ 0 k init ?? ?? ?? = ?? ?? ?? 不考虑摄像机坐标轴夹角非正交情况,即alpha_c=_0 alpha init= 内参数矩阵初始值 max(,) 00.50.5 max(,) 00.50.5 001 nx ny nx nx ny KK ny π π ?? - ?? ?? ?? =- ?? ?? ?? ?? ?? -------------------(1)

2.对外参的初始化: 涉及函数:comp_ext_calib_fisheye.m 功能:主要是调用compute_extrinsic_init_fisheye.m 和compute_extrinsic_refine_fisheye.m compute_extrinsic_init_fisheye.m 输入:像点的世界坐标和图像坐标x_kk 和X_kk,以及所有内参fc,cc,kc,alpha_c; 输出:所有外参初始值,包括平移矩阵Tckk ,旋转矩阵Rckk 和旋转向量omckk compute_extrinsic_refine_fisheye.m 输入:像点的世界坐标和图像坐标x_kk 和X_kk,最大迭代次数MaxIter 以及所有内参fc,cc,kc,alpha_c; 输出:所有外参初始值,包括平移矩阵Tckk ,旋转矩阵Rckk 和旋转向量omckk 对像点世界坐标和图像坐标进行整理(整理过程考虑到坐标变换和畸变模型,涉及normalize_pixel_fisheye .m 输入:像点图像坐标x_kk,所有内参fc,cc,kc,alpha_c;输出:标准化无畸变图像坐标xn )。 坐标变换首先按照原点坐标进行线性映射,转换成以焦距为单位: 111 222___x kk cc fc x distort x kk cc fc -????? ?=-?????? 然后校正相机平面和图像平面不平行带来的误差: 122_____x distrot alpha c x distrot x distort x distrot -??? =???? 最后进行畸变补偿:(调用函数comp_fisheye_distortion.m 输入:畸变的像点图像坐标xd ,畸变系数k ; 输出: 无畸变的像点图像坐标x ) xd 是畸变后的像素坐标,令__theta d theta theta d == 进入循环20次的补偿迭代,每次循环中有 12 24682468 1121314112223242__11theta d theta d theta k theta k theta k theta k theta k theta k theta k theta k theta ??=??++++++++?? ,其中k 为畸变系数。本程序中,只考虑径向畸变不考虑切向畸变,k 虽然是5x1矢量,但是 最后一位即切向畸变系数没有使用。 然后有1212tan()tan()__theta theta scaling theta d theta d ?? =? ??? 111 1221211 2222Np Np Np Np xd scaling xd scaling xd scaling xn xd scaling xd scaling xd scaling ?? =? ??? 畸变补偿结束。 得到标准化无畸变的世界坐标X_new 和图像坐标xn 。 由这两组坐标计算得到透视投影矩阵H(计算过程见摄像机定标程序中透视投影矩阵H 的计算过程.doc ),并对H 进行整理得到 ((:,1))()((:,2))H H H norm H sc mean norm H = =???? ??

矩阵投影与最小二乘方法

题目:《神奇的矩阵——矩阵投影与最小二乘方法》 学校:哈尔滨工程大学 姓名:黎文科 联系方式: QQ群:53937814 联系方式: 190356321@https://www.360docs.net/doc/9515164988.html,

矩阵投影与最小二乘方法 最小二乘法(Least Squares Method,简记为LSE)是一个比较古老的方法,源于天文学和测地学上的应用需要。在早期数理统计方法的发展中,这两门科学起了很大的作用。丹麦统计学家霍尔把它们称为“数理统计学的母亲”。此后近三百年来,它广泛应用于科学实验与工程技术中。美国统计史学家斯蒂格勒( S. M. Stigler)指出, 最小二乘方法是19世纪数理统计学的压倒一切的主题。1815年时,这方法已成为法国、意大利和普鲁士在天文和测地学中的标准工具,到1825年时已在英国普遍使用。 追溯到1801年,意大利天文学家朱赛普·皮亚齐发现了第一颗小行星谷神星。经过40天的跟踪观测后,由于谷神星运行至太阳背后,使得皮亚齐失去了谷神星的位置。随后全世界的科学家利用皮亚齐的观测数据开始寻找谷神星,但是根据大多数人计算的结果来寻找谷神星都没有结果。时年24岁的高斯也计算了谷神星的轨道。奥地利天文学家海因里希·奥尔伯斯根据高斯计算出来的轨道重新发现了谷神星。高斯于其1809年的著作《关于绕日行星运动的理论》中。在此书中声称他自1799年以来就使用最小二乘方法,由此爆发了一场与勒让德的优先权之争。 近代学者经过对原始文献的研究,认为两人可能是独立发明了这个方法,但首先见于书面形式的,以勒让德为早。然而,现今教科书和著作中,多把这个发明权归功于高斯。其原因,除了高斯有更大的名气外,主要可能是因为其正态误差理论对这个方法的重要意义。勒让德在其著作中,对最小二乘方法的优点有所阐述。然而,缺少误差分析。我们不知道,使用这个方法引起的误差如何,就需建立一种误差分析理论。高斯于1823年在误差e 1 ,… , e n 独立同分布的假定下,证明了最小二乘方法的一个最优性质: 在所有无偏的线性估计类中,最小二乘方法是其中方差最小的!在德国10马克的钞票上有高斯像,并配了一条正态曲线。在高斯众多伟大的数学成就中挑选了这一条,亦可见这一成就对世界文明的影响。 现行的最小二乘法是勒让德( A. M. Legendre)于1805年在其著作《计算慧星轨道的新方法》中提出的。它的主要思想就是选择未知参数,使得理论值与观测值之差的平方和达到最小: 2 211 ()()m m i i i H y y ===-=-∑∑理论值观测值

透视投影与正投影相关函数介绍

OpenGL 入门纪录--2 .透视函数glFrustum(), gluPerspective()函数用法和glOrtho()函数用 法 2008-12-24 16:14 在OpenGL中,如果想对模型进行操作,就要对这个模型的状态(当前的矩阵)乘上这个操作对应的一个矩阵. 如果乘以变换矩阵(平移, 缩放, 旋转), 那相乘之后, 模型的位置被变换; 如果乘以投影矩阵(将3D物体投影到2D平面), 相乘后, 模型的投影方式被设置; 如果乘以纹理矩阵(), 模型的纹理方式被设置. 而用来指定乘以什么类型的矩阵, 就是glMatriMode(GLenum mode); glMatrixMode有3种模式: GL_PROJECTION 投影, GL_MODELVIEW 模型视图, GL_TEXTURE 纹理. 所以,在操作投影矩阵以前,需要调用函数: glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵 然后把矩阵设为单位矩阵: glLoadIdentity(); 然后调用glFrustum()或gluPerspective(),它们生成的矩阵会与当前的矩阵相乘,生成透视的效果; 1.glFrustum() 这个函数原型为: void glFrustum(GLdouble left, GLdouble Right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far); 创建一个透视型的视景体。其操作是创建一个透视投影的矩阵,并且用这个矩阵乘以当前矩阵。这个函数的参数只义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的离视点的距离值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。ne 和far表示离视点的远近,它们总为正值(near/far 必须>0)。 2.gluPerspective()

投影大屏系统混合矩阵说明书

混合矩阵切换器说明书 第一章系统简介 MultiView Matrix 系列混合矩阵切换器,是一款高性能的专业PC信号切换设备,用于多个PC信号输入输出交叉切换,提供四种信号源的输入,信号源分别是是Video,VGA,DVI,YPbPr,每种信号单独传输,单独切换,输出可以是RGB和DVI,使信号传输衰减降至最低,图像信号能高保真输出。广泛应用在大屏幕显示工程、电视教学、指挥控制中心等场合。 Multiview Matrix系列混合矩阵切换器,主板采用自主研发出应于切换系统的巨量数据传输芯片技术,全新推出我公司独创的 180G/s处理高速宽带总线,彻底根除了处理数据总线带宽低下引起的显示速度慢且不稳定的瓶颈。 采用网络控制,可以传输数据量大。 可以支持RGB、DVI、HDTV、S-Video、NTSC/PAL格式信号输入,分辨率从640x480到1920x1200,刷新频率为60Hz;对每路输入信号采样都有特征记忆功能,在前级矩阵中可以任意切换输入信号,只要做过采样调整的信号再此输入,设备会自动配置记忆参数,无需二次采样调整。 可以支持RGB和 DVI信号同时输出,分辨率最高可达到1920x1200,刷新频率为60Hz,方便客户配置显示单元。 第二章技术参数 一计算机输入信号: 数量 4到72路DVI/RGB信号; 类型 DVI(数字)/ RGB(模拟); 分辨率 640x350,640x400,720x400,640x480,848x480,800x600, 848x480,1024x768,1152x864,1280x720,1280X768, 1280X960,1280x1024,1360x768,1400x1050,1440x900, 1600x1200,1680x1050,1792x1344,1856x1392, 1920x1080,1920x1200 像素, 刷新频率为60Hz;

立方体纹理映射

1问题描述与算法思想 1.1纹理映射简介 纹理映射(Texture Mapping)是将纹理空间中的纹理像素映射到屏幕空间中的像素的过程。在三维图形中,纹理映射(Texture Mapping)的方法运用得最广,尤其描述具有真实感的物体。比如绘制一面砖墙,就可以使用一幅具有真实感的图像或者照片作为纹理贴到一个矩形上,这样,一面逼真的砖墙就画好了。如果不用纹理映射的方法,这墙上的每一块砖都要作为一个独立的多边形来绘制。另外,纹理映射能够保证在变换多边形时,多边形上的纹理也会随之变化。例如,用透视投影模式观察墙面时,离视点远的墙壁的砖块的尺寸就会缩小,而离视点近的就会大些,这些是符合视觉规律的。此外,纹理映射也被用在其他一些领域。如飞行仿真中常把一大片植被的图像映射到一些大多边形上用以表示地面,或者用大理石、木材等自然物质的图像作为纹理映射到多边形上表示相应的物体。纹理对象通过一个单独的数字来标识。这允许硬件能够在内存中保存多个纹理,而不是每次使用的时候再加载它们,从而减少了运算量,提高了速度。纹理映射是真实感图像制作的一个重要部分,运用它可以方便的制作出极具真实感的图形而不必花过多时间来考虑物体的表面细节。然而纹理加载的过程可能会影响程序运行速度,当纹理图像非常大时,这种情况尤为明显。如何妥善的管理纹理,减少不必要的开销,是系统优化时必须考虑的一个问题。还好,相关软件提供了纹理对象对象管理技术来解决上述问题。与显示列表一样,纹理对象通过一个单独的数字来标识。 立方体映射(cube-map)纹理是一种特殊类型的纹理,用于环境映射,使用一组图像并把他们作为立方体的面。立方体映射的6个面用正方形并且大小相同的6个子纹理表示。要从立方体纹理中采样的时候,使用的纹理坐标是3维,并且被看做来自原点的方向。方向指向用来读取纹理的立方体映射表面的位置。立方体纹理映射主要思想是通过观察向量和表面的法向量反射来确定采样的纹理坐标。 1.2实验目的 1) 掌握位图纹理读入方法; 2)掌握立方体纹理映射算法。 1.3功能要求 1)建立三维坐标系Oxyz,远点位于屏幕客户区中心,x轴水平向右为正,y轴垂直向上为正,z轴垂直于屏幕指向观察者。 2)设置屏幕背景色为黑色。 3)读入六张构成天空盒的位图作为纹理映射到立方体的可见表面上。 4)按下鼠标左键缩小立方体,按下鼠标右键增大立方体。 5)使用键盘方向旋转纹理立方体。 6)使用动画按钮播放或停止立方体动画。 1.4算法原理(算法思想) 立方体进行纹理映射是纹理对象并不是直接绑定到着色器,而是绑定到一个

透视投影(perspectiveprojection)变换推导

透视投影是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)是坐标系下表达一个向量和点的不同表达方式。这里可以看出,虽然都是用代数分量的形式表达向量和点,但表达一个点比一个向量需要额外的信息。如果我写出一个代数分量表达(1, 4, 7),谁知道它是个向量还是个点! 我们现在把(1)(3)写成矩阵的形式:

openGL投影矩阵原理及数学推导

openGL投影矩阵 概述 显示器是2d的。3d场景需要转换为2d图像才能显示在屏幕上。投影矩阵(GL_PROJECTION)用于完成这个工作。投影矩阵将观察坐标(eye coordinates)转换成裁剪坐标(clip coordinates)。然后,裁剪坐标被除以w,转换为规范化的设备坐标(NDC)。 需要记住的一点是,裁剪操作和规范化都由投影矩阵(GL_PROJECTION)完成。下面介绍如何用6个参数(left,right,bottom,top,near,far)构建投影矩阵。 裁剪(clipping)操作是在裁剪坐标上进行的,安排在透视除法执行之前。裁剪坐标xc,yc,zc同wc比较,若每个分量都落在(-wc,wc)外,那么此坐标将被裁剪掉。 在透视投影中,3d场景中的点(观察坐标)从平截头体中映射到正方体(NDC)中;x坐标从[l,r]映射到[-1,1],y坐标从[b,t]映射到[-1,1],z坐标从[n,f]映射到[-1,1]。 注意到,观察坐标系是右手系,规范设备坐标系是左手系。这就有,在观察坐标系中,摄像机朝向沿着-z,而在NDC中,方向沿着z。由于glFrustum()只接受正参数,所以构造投影矩阵的时候要变号。 openGL中,3d场景中,观察坐标系下的点被投影到近投影面。下图展示了观察坐标系点(xe,ye,ze)投影到近投影面上的点(xp,yp,zp)。 从Top View of Projection看,xe投影到xp,根据等比性质:

从Side View of Projection看,yp计算类似: 注意到,xp和yp依赖于-ze,这一点要引起重视。在观察坐标被投影矩阵转换为裁剪坐标后,裁剪坐标仍然是同质坐标。在规范化阶段执行透视除法变为规范设备坐标(NDC)。 因此,可以将wc的值定为-ze。投影矩阵最后一行为(0,0,-1,0) 下一步,将xp,yp映射到xn,yn,此为线性映射[l,r]=>[-1,1],[b,t]=>[-1,1]:

投影矩阵的定义

视锥就是场景中的一个三维空间,它的位置由视口的摄像机来决定。这个空间的形状决定了摄像机空间中的模型将被如何投影到屏幕上。透视投影是最常用的一种投影类型,使用这种投影,会使近处的对象看起来比远处的大一些。对于透视投影,视锥可以被初始化成金字塔形,将摄像机放在顶端。这个金字塔再经过前、后两个剪切面的分割,位于这两个面之间的部分就是视锥。只有位于视锥内的对象才可见。 视锥由凹视野( 在上图中,变量 投影矩阵是一个典型的缩放和透视矩阵。投影变换将视锥变换成一个直平行六面体的形状。因为视锥的近处比远处小,这样就会对靠近摄像机的对象起到放大的作用,也就将透视应用到了场景当中。 在视锥中,摄像机与空间原点间的距离被定义为变量 视矩阵将摄像机放置在场景的原点。又因为投影矩阵需要将摄像机放在 将两个矩阵相乘,得到下面的矩阵: 下图显示了透视变换如何将一个视锥变换成一个新的坐标空间。注意:锥形体变成了直平行六面体,原点从场景的右上角移到了中心。 在透视变换中,

这个矩阵基于一定的距离(这个距离是从摄像机到邻近的剪切面)对对象进行平移和旋转,但是它没有考虑到视野( 在这个矩阵中, 在程序中,使用视野角度来定义x和y缩放系数比使用视口的水平和垂直尺寸(在摄像机空间中)并不方便多少。下面两式使用了视口的尺寸,并且与上面的公式相等: 在这些公式中,Zn表示邻近的剪切面的位置,变量Vw和Vh表示视口的高和宽。这两个参数与 D3DVIEWPORT2结构中的dwWidth和dwHeight成员相关。 不管你使用那个公式,将同世界和视变换一样,可以调用下面的 D3DMATRIX ProjectionMatrix(const float near_plane,// distance to near clipping plane const float far_plane,// distance to far clipping plane const float fov_horiz,// horizontal field of view angle, in radians const float fov_vert)// vertical field of view angle, in radians { float h, w, Q; w = (float)cot(fov_horiz*0.5); h = (float)cot(fov_vert*0.5); Q = far_plane/(far_plane - near_plane); D3DMATRIX ret = ZeroMatrix(); ret(0, 0) = w; ret(1, 1) = h; ret(2, 2) = Q; ret(3, 2) = -Q*near_plane; ret(2, 3) = 1; return ret; } // end of ProjectionMatrix()

弹塑性矩阵推导

弹塑性矩阵推导

考虑材料的塑性,其增量形式的本构关系可表达为 p d σ=(D -D )d ε (1) 式(1)中,D 为弹性矩阵,p D 为塑性矩阵。 弹性矩阵D 的形式为 422000333242000333224000333000000 000000000K G K G K G K G K G K G K G K G K G G G G ??+--??????-+-???? =??--+?????? ?????? D (2) 体积模量3(12) E K μ= -,剪切模量2(1) E G μ=+。 在应变空间内,塑性矩阵可表达为 1()T f f A ??= ??p D D D σσ (3) 式中, ( )()T T p f f f f A B ????=--????D D σσσσ (4) f 为屈服函数;p σ为塑性应力,p p =σD ε; 1/2(()())T p T p T p f f f f B f f f ωθε??? ???? ??? '=???? ????????? σσ I σσσ (5) [111000]T '=I ;p ω为塑性功;p θ为塑性体应变;p ε为等效塑性应变; κ为反映加载历史的参数。 当p κω=时 当p κθ=时 当p κε=时

对于Drucker-Prager 模型,其屈服条件为 120f I J α== (6) 1x y z I σσσ=++,222222 21()2 x y z xy yz zx J S S S S S S = +++++,α为材料常数。 2 2f J α?''=?I σ (7) 222T x y z xy yz zx S S S S S S '??=??S (8) 22 ()32f K J J αα?'''==+?D D I I σ (9) 222 ( )()(3)92T T T f f A K K G J J ααα??'''===+??D I I σσ (10) 1()T f f A ??= ??p D D D σσ 222 22222 222222112123113211212311321121231131121121121(3)(3)999(9)(9)(9)(T T T T T T K K K G J J K G K G K G J K G J K G J m mn ml S m S m S m mn n nl S n S n S n ml nl l S l S l S l S m S n S l ααααααααβββββββββββββ''= + +''''=++++++=p D I I I I S SS 21121122231122132123123123 1122231231132232 113113113113212113223113)()()S S S S S S m S n S l S S S S S S m S n S l S S S S S ββββββββββββββββββββ?? ? ? ???? ? ? ?????? ?????????? 令4 3 p K G =+,23 q K G =- 弹塑性矩阵可表达为 211212311321121231132 1121231132112112112112112223112213123 123123 112223()(p m q mn q ml S m S m S m q mn p n q nl S n S n S n q ml q nl p l S l S l S l S m S n S l G S S S S S S m S n S l S S G βββββββββββββββββββββββ------------------=-=-----?-?----?-ep p D D D 21231132232 113113113113212 113223 113)()S S S S m S n S l S S S S G S ββββββββββ?? ?? ? ??? ? ? ???? -???----?-?-??? ?

深入探索3D拾取技术

深入探索3D拾取技术 在游戏中,玩家需要通过点击2D屏幕来选择3D物体,这个过程就是拾取(picking)。拾取是3D游戏必不可少的基本操作,它实现了玩家和游戏世界内对象的交互。 虽然拾取技术很基本,但它却迷惑了很多3D初学者。很多朋友都问过我关于拾取的细节问题,这让我觉得很有必要具体探讨一下该技术。其实,拾取之所以让很多开发者感到复杂,主要原因在于它跨域了流水线的多个阶段,并且是逆流水线上行。另外,它是一个2D信息扩展到3D的过程,必须对信息做相应的扩展和额外的计算才能够得到正确的结果。下面我门具体分析一下这个技术。 水流线主要阶段分析 我们来直观地看一下从相机空间到viewport的变换 相机空间中的一个顶点v,经过透视变换后进入了CVV中。这个变换矩阵实际上完成了两个工作: 1)将顶点从3D空间投影到2D的投影平面(Projection Plane)上。 2)将投影平面上的2D投影点通过线性插值变换到齐次裁剪空间CVV中。 这些变换都通过透视矩阵一次完成。我之所以把这一步分解为两步,因为这对于分析拾取很重要。 顶点进入齐次裁剪空间并经过CVV裁剪,最终进行透视除法从4D齐次形式变回成3D形式。然后经过一个线性插值(被封装在视口(viewport)变换中),变换到viewport中,多个点以三角形的形式经过光栅化后被玩家看到。最后一步的点变换可以描述为: 3)将CVV中的点通过线性插值变换到viewport中。

分析了这个变换过程之后,我们知道了从相机空间开始实际处理点位置信息的操作,就是上面的三个步骤。这样,我们可以先把顶点从viewport中先变换回投影平面上,也就是我们可以先完成(2)和(3)的逆处理。这里我们不用考虑裁剪和透视除法这些操作,因为反推的时候,处于视口中的点,已经是经过裁剪后留下的有效点了,必定处于CVV内,也必定处于projection plane内!而且从viewport逆变换到projection plane,点一直保持2D形式。 picking的开始是玩家在屏幕上点击一个位置——这实际上是在viewport中进行了点击。我们通过响应玩家的点击事件,得到在viewport中的点击位置,记为P0(Xp0,Yp0)。然后我们把p0从viewport中线性插值到CVV中,得到P1(Xp1,Yp1): 上面的线性插值(如果对线性插值公式不熟悉,请参考《深入探索透视投影变换》一文中的线性插值部分)公式在x方向上计算出了CVV中的P1,y方向的公式同理。接下来我们再把P1从CVV中变换到projection plane中,得到P2(Xp2,Yp2): y方向的计算同理。P2就是viewport中玩家点击的点在projection plane上所对应的位置。目前来看很好。我们已经获得了相机空间中的投影平面上,玩家点击的位置。但目前的点是一个2D点——它处于投影平面上。玩家需要拾取的是一个3D对象,因此我们需要将2D信息拓展到3D中。 向3D世界拓展 将2D的点信息拓展到3D空间进行picking,会使用射线(ray)进行。ray就是一端固定,另一端无限延伸的线性模型。如下图所示:

透视投影详解

透视投影 透视投影是用中心投影法将形体投射到投影面上,从而获得的一种较为接近视觉效果的单面投影图。它具消失感、距离感、相同大小的形体呈现出有规律的变化等一系列的透视特性,能逼真地反映形体的空间形象。透视投影也称为透视图,简称透视。在建筑设计过程中,透视图常用来表达设计对象的外貌,帮助设计构思,研究和比较建筑物的空间造型和立面处理,是建筑设计中重要的辅助图样。 透视投影符合人们心理习惯,即离视点近的物体大,离视点远的物体小,远到极点即为消失,成为灭点。它的视景体类似于一个顶部和底部都被切除掉的棱椎,也就是棱台。这个投影通常用于动画、视觉仿真以及其它许多具有真实性反映的方面。 在平行投影中,图形沿平行线变换到投影面上;对透视投影,图形沿收敛于某一点的直线变换到投影面上,此点称为投影中心,相当于观察点,也称为视点。平行投影和透视投影区别在于透视投影的投影中心到投影面之间的距离是有限的,而平行投影的投影中心到投影面之间的距离是无限的。当投影中心在无限远时,投影线互相平行,所以定义平行投影时,给出投影线的方向就可以了,而定义透视投影时,需要指定投影中心的具体位置平行投影保持物体的有关比例不变,这是三维绘图中产生比例图画的方法。物体的各个面的精确视图可以由平行投影得到。另一方面,透视投影不保持相关比例,但能够生成真实感视图。对同样大小的物体,离投影面较远的物体比离投影面较近物体的投影图象要小,产生近大远小的效果. 透视投影的原理和实现 by Goncely 摘要:透视投影是3D渲染的基本概念,也是3D程序设计的基础。掌握透视投影的原理对于深入理解其他3D渲染管线具有重要作用。本文详细介绍了透视投影的原理和算法实

投影矩阵的计算过程

投影矩阵的计算过程3d模型经过世界坐标变换、相机坐标变换后,下一步需要投影变换。投影变换的目的就是要把相机空间转换到标准视图空间,在这个空间的坐标都是正规化的,也就是坐标范围都在[-1,1]之间,之所以转换到这个空间是为了后续操作更方便。下面的讨论都是以列向量来表示,这样在变换操作时,采用的是矩阵左乘法,如果采用的是行向量的话,那就相反,矩阵右乘法即是向量在左边乘以变换矩阵。采用哪种表示并不影响结果,只需要把该种表示下得出的变换矩阵转置一下,就是采用另外一种表示模式需要的结果。常见的投影有两种,正交投影和透视投影,正交投影相对来说更简单,所以先来看看正交投影。最简单的正交变换矩阵 1 0 0 0 0 1 0 0 0 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 0 1 0 0 0 1 透视投影类比于我们人眼系统,看一个物体,会有远小近大的效果。在转换到相机空间后,相机是这个空间的原点,和正交投影体是一个长方体或者立方体不同,透视投影体是一个锥体被近平面截取掉头部剩下的空间。假定仍然采用上面的坐标表示。在透视投影下,空间上面的任何一点P投影到近平面上某点q,通过三角几何学我们可以得到qx=px*n/pz ,y点同理。假定直接投影到近平面,则该矩阵很简单,用Ma表示下面的矩阵1 0 0 0 0 1 0 0 0 0 1 0 0 0 1/n 0 则齐次空间某点(x,y,z ,1)被该矩阵转换后变成了(x ,y z, z/n) ,除以z/n,则变成了(nx/z,ny/z,n ,1) 正好吻合上面的公式。 undefined 但是我们知道投影变换需要把坐标变换到-1和1之间,假定先不考虑z轴的变换,在x轴和y轴上面经过上述变换后,已经投影在近平面了,假设近平面xy在[l,r] 和[b,t]之间了,因此只需要和上面的正交投影一样,进行平移和缩放操作就可以了,平移矩阵Mb为 1 0 0 -(l+r)/2 0 1 0 -(t+p)/2 0 0 1 -(f+n)/2 0 0 0 1 以及缩放矩阵Mc 2/(r-l) 0 0 0 0 2/(t-b) 0 0 0 0 2/(f-n) 0 0 0 0 1 McXMbXMa 得到的矩阵为2/(r-l) 0 -(r+l)/(n*(r-l))0 0 2/(t-b) -(t+b)/(n*(t-b)) 0 0 0 j k 0 0 1/n 0 j k 为未知数,这个矩阵也可以同时乘以n,则变为2n/(r-l) 0 -(r+l)/(r-l) 0 0 2n/(t-b) -(t+b)/(t-b) 0 0 0 j k 0 0 1 0 为了求解J k,我们需要把z变换到-1 和1 因此当z=n时为-1,z=f时为1 (j*n+k)/n= j+k/n=-1; 同理j+k/f=1; 得到k=2f*n/(n-f) j=-(n+f)/(n-f) 代入上面的矩阵,就得出通用的正交变换矩阵。而且在一般情况下r=-l ,b=-t 因此上述矩阵可以简化为n/r 0 0 0 0 n/t 0 0 0 0 -(n+f)/(n-f) 2f*n/(n-f) 0 0 1 0 n/r 和n/t可以进一步简化成水平半视角和垂直半视角的三角函数来表示,而水平视角和垂直视角和透视窗口的宽高比有是成正比的,最终上面两行可以用宽高

快速投影Hessian矩阵算法

文章编号:1671 1114(2009)03 0018 04 快速投影Hessian 矩阵算法 收稿日期:2008 03 10 基金项目:天津市高校发展基金项目(20060402) 作 者:汤大林(1965 ),男,高级工程师,主要从事数学建模及应用方面的研究. 汤大林 (天津理工大学理学院,天津300191) 摘 要:分析了求解等式约束非线性规划问题的投影H essian 矩阵算法,找出了算法两步Q 超线性收敛的原因,并用BY RD 的例子说明此算法的收敛效果较差,即甚至不是线性收敛;对算法进行了合理的改进,并用改进后的算法求解BY RD 问题,得到了满意的收敛效果,即Q 超线性收敛.借助数值试验验证了改进算法的快速收敛性.关键词:等式约束非线性规划;投影H essian 矩阵算法;超线性收敛中图分类号:O 221.2 文献标识码:A Q uick projection method with H essian matrix T AN G Dalin (School of Science,T ianjin University of Techn ology,T ian jin 300191,China) Abstract:T he project ion method wit h H essian mat rix used to so lve nonlinear prog ramming w ith equality co nstr aint is analyzed and the r easo n w hy the method is superlinear conver gent by two steps is found o ut.Its bad converg ent effect at linear ity is illuminated by BYRD's example.T he method is impr ov ed and quickly super linear conver gence o f the impr ov ed metho d is illuminated using BY RD's ex ample.T he quickly co nv erg ent effect o f t he impro ved method is verified by a numerical experiment. Key words:nonlinear pr og ramming w ith equality constra int ;project ion method wit h H essian mat rix ;super linear conver gence 1 投影Hessian 矩阵算法的缺点 考察等式约束非线性规划问题: m in x R n f (x ),约束c(x)=0,(1) 其中,目标函数f (x ):R n !R,约束c(x):R n !R m 是二次可微函数,且m ?n,即m 个等式约束.为叙述方便,引入如下记号: x =(x (1),x (2),#,x (n)), c(x)=(c (1)(x ),c (2)(x ),#,c (m)(x ))T , g(x)= f (x )= ( f x (1), f x (2) ,#, f x (n))T , A(x)= c(x)= c (1) x (1) c (2) x (1)# c (m) x (1) c (1) x (2) c (2) x (2)# c (m) x (2) ! c (1) x (n) c (2) x (n)# c (m) x (n ) ,L (x, )=f (x )-?m i=1 (i) c (i)(x ), 其中, (i)为拉格朗日乘子,i =1,2,#,m. 将A(x)QR 分解为A(x)=(y(x),z(x)) (R(x)O ) , 其中y (x),z(x)均为n 阶正交矩阵,R(x)为m 阶上三角矩阵. V ol.29N o.3 Jul.2009 第29卷 第3期2009年7月 天津师范大学学报(自然科学版) Jour nal of T ianjin N orma l U niver sity (N atural Science Edit ion)

深入探索透视投影变换

深入探索透视投影变换 -Twinsen编写 -本人水平有限,疏忽错误在所难免,还请各位数学高手、编程高手不吝赐教 -email: popyy@https://www.360docs.net/doc/9515164988.html, 透视投影是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)

深度探讨透视投影坐标系.

3d图形程序,就一定会做坐标变换。而谈到坐标变换,就不得不提起投影变换,因为它是所有变换中最不容易弄懂的。但有趣的是,各种关于透视变换的文档却依然是简之又简,甚至还有前后矛盾的地方。看来如此这般光景,想要弄清楚它,非得自己动手不可了。所以在下面的文章里,作者尝试推导一遍这个难缠的透视变换,然后把它套用到DX和PS2lib 的实例中去。 1.一般概念 所谓透视投影变换,就是view 空间到project 空间的带透视性质的坐标变换步骤(这两个空间的定义可以参考其他文档和书籍)。我们首先来考虑它应该具有那些变换性质。很显然,它至少要保证我们在view空间中所有处于可视范围内的点通过变换之后,统统落在project空间的可视区域内。好极了,我们就从这里着手——先来看看两个空间的可视区域。 由于是透视变换,view空间中的可见范围既是常说的视平截体(view frustum)。如图, (图1)它就是由前后两个截面截成的这个棱台。 从view空间的x正半轴看过去是下图这个样子。

(图2)接下来是project空间的可视范围。这个空间应当是处于你所见到的屏幕上。实际上将屏幕表面视作project空间的xoy平面,再加一条垂直屏幕向里(或向外)的z轴(这取决于你的坐标系是左手系还是右手系),这样就构成了我们想要的坐标系。好了,现在我们可以用视口(view port)的大小来描述这个可视范围了。比如说全屏幕640*480的分辨率,原点在屏幕中心,那我们得到的可视区域为一个长方体,它如下图(a)所示。 (图3) 但是,这样会带来一些设备相关性而分散我们的注意力,所以不妨先向DirectX文档学学,将project空间的可视范围定义为x∈[-1,1], y∈[-1,1], z∈[0,1]的一个立方体(上图b)。这实际

深入探索透视投影矩阵.

-Twinsen 编写 - 本人水平有限,疏忽错误在所难免,还请各位数学高手、编程高手不吝赐教 -email: 透视投影是 3D 固定流水线的重要组成部分,是将相机空间中的点从视锥 体 (frustum) 变换到规则观察体 (Canonical View Volume) 中,待裁剪完毕后进行透视除法的行为。在算法中它是通过透视矩阵乘法和透视除法两步完成的。 透视投影变换是令很多刚刚进入 3D 图形领域的开发人员感到迷惑乃至神秘的一个图形技术。其中的理解困难在于步骤繁琐,对一些基础知识过分依赖,一旦对它们中的任何地方感到陌生,立刻导致理解停止不前。 没错,主流的 3D APIs 如 OpenGL 、 D3D 的确把具体的透视投影细节封装起来,比如 gluPerspective(…) 就可以根据输入生成一个透视投影矩阵。而且在大多数情况下不需要了解具体的内幕算法也可以完成任务。但是你不觉得,如果想要成为一个职业的图形程序员或游戏开发者,就应该真正降伏透视投影这个家伙么?我们先从必需的基础知识着手,一步一步深入下去(这些知识在很多地方可以单独找到,但我从来没有在同一个地方全部找到,但是你现在找到了)。 我们首先介绍两个必须掌握的知识。有了它们,我们才不至于在理解透视投影变换的过程中迷失方向(这里会使用到向量几何、矩阵的部分知识,如果你对此不是很熟悉,可以参考《向量几何在游戏编程中的使用》系列文章)。 齐次坐标表示 透视投影变换是在齐次坐标下进行的,而齐次坐标本身就是一个令人迷惑的概念,这里我们先把它理解清楚。 根据《向量几何在游戏编程中的使用 6 》中关于基的概念。对于一个向量 v 以及基 oabc ,

相关文档
最新文档