梅毒口服什么药能预防:图形中投影矩阵的推导
来源:百度文库 编辑:偶看新闻 时间:2024/04/29 14:08:45
进入正题,中算是入道,兴趣大增最近在看OpenGL超级宝典第五版,就决定把扰了我五年的投影变换矩阵搞清楚,下面大部分是抄的(不要见怪,毛病不是一下子就能改掉的,忘原谅)。
经过模型与视点变换、光照等变化后,需要进行投影变换,投影变换的目的就是为了将视景体变换为一个单位立方体,这个立方体的对角线顶点分别为(-1,-1,-1)和(1,1,1)
1:齐次坐标;
“齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易于进行仿射(线性)几何变换”-F.S. Hill, JR
(1)为什么要引入齐次坐标?
我想当然的以为引入齐次坐标主要是为了在进行平移变换时也能很好的用矩阵运算来计算(到此为止)。在计算机图形学中,在没有引进齐次坐标时,向量与点的坐标都是一一个三元组来表示(x,y,z)表示。设坐标系的三个基为 x、y、z,那么向量V(v1,v2,v3)就可以通过以下公式表示V = v1X + v2y + v3z来表示。对于坐标系中的一个点,可以看成是原点所进行的一个位移。P(p1,p2,p3)可以写成如下形式P = o + p1x + p2y + p3z如果向量与点的坐标同时写成矩阵形式得:
表示向量基,右边的为向量与点在同一向量基下的不同坐标表示,由此可以得出向量与点在同一基下有了不同的表示。向量的齐次坐标的第四个分量为0,而点的齐次坐标的第四个分量为1。(I finally understand why CG import homogeneous coordinates….)
以前以为图形学中引入齐次坐标的主要原因是为了能够是平移变换也能像缩放、旋转变换那样通过一个矩阵与一个点的坐标相乘得到。由齐次坐标可以得到,当坐标表示一个点(第四个分量不为0)时,此时对其进行平移操作才会改变坐标值,当坐标表示一个向量(第四个分量为0)时此时对其进行平移操作并不能改变坐标值。通过向量的几何意义也很容易得到,向量只表示了一个方向与大小,并没有位置这个概念,读者可以自行导出。
"After shading rendering system perform projection,which transforms the view volumn into a unit cube with its extreme points at (-1, –1, –1) and (1, 1, 1).The unit cube is called canonical view volume.”
上段话摘自Real-Time-Rendering,可以看出投影变换的主要任务就是使用透视投影矩阵将顶点从视锥体中变换到canonical view volume(CCV 规则观察体中),然后进行裁剪,然后在进行透视除法变换坐标。
我们可以通过两步来进行这个变换:
(1):将投影点投影到投影平面(近平面)
(2):将投影点变换到CCV中(x、y、z都变换到(-1,1)区间中去。
一下做如下嘉定(视锥体的近平面为left、right、top、bottom)分别用(l,r,t,b‘)表示。
对于视锥体的近平面为-n,远裁剪面位-f(f>n),对于点P(x,y,z)通过第一次变换后得到的坐标为q(x’,y’,z’)其中z'=-n;上图中的右图(根据相似三角形)中可以得出:从而得出x’ = –nx/z, y’ = –ny/z;这样得到投影后的点的坐标为:q(-nx/z, –ny/z, –n),由此可以看出所有点投影后z坐标都为-n,此时对于投影点已经没有什么意义,但是对于计算机图形学的其他算法而言,z还有很大作用(如z缓冲算法),在此,可以利用这个点存储z,此时q点的坐标可以处理成为q(-nx/z, –ny/z, z),因为此点坐标是有原有点p通过变化的来,原有点p的齐次坐标为p(x, y, z, 1),q点的齐次坐标为(-nx/z, –ny/z, z, 1) ,结合CVV在对其进行进一步的处理将q点的几次坐标写成如下形式:q(-nx/z,-ny/z, (az+b)/(-z),1)(因为z值主要是zbuffer使用,第三个坐标值只要单调性相同就行,当z=-n时此时(az+b)/(-z)=-1,当z=-f时,(az+b)/(-z)= 1),此时点q的齐次坐标可以表示为q(nx, ny, az+b, –z)(哇咔咔,看到齐次坐标的魅力了吗)。此时变换矩阵可以写为,我们根据求得:
然后在对x、y进行变换,此时得到的p的坐标是(-nx/z, –ny/z, (az+b)/(-z),1),将p点的x、y(第一、第二)坐标分量变换到CVV的(-1,1)上的坐标为p'(x’、y’)(不要弄混)此时建立线性系统(就是方程组)为,求的:,对于透视投影矩阵M,我们得到:M P = p’即:
此时透视投影矩阵就出来了:
OpenGL超级宝典中的代码如下:
01
void m3dMakePerspectiveMatrix(M3DMatrix44f mProjection, float fFov, float fAspect, float zMin, float zMax)
02
{
03
m3dLoadIdentity44(mProjection);
04
05
float yMax = zMin * tanf(fFov * 0.5f);
06
float yMin = -yMax;
07
float xMin = yMin * fAspect;
08
float xMax = -xMin;
09
10
mProjection[0] = (2.0f * zMin) / (xMax - xMin);
11
mProjection[5] = (2.0f * zMin) / (yMax - yMin);
12
mProjection[8] = (xMax + xMin) / (xMax - xMin);
13
mProjection[9] = (yMax + yMin) / (yMax - yMin);
14
mProjection[10] = -((zMax + zMin) / (zMax - zMin));
15
mProjection[11] = -1.0f;
16
mProjection[14] = -((2.0f * (zMax*zMin))/(zMax - zMin));
17
mProjection[15] = 0.0f;
18
}
1
就此告一段落吧。。通过这种方式,可以参考一下Real Timer Rendering推导一下平行投影的投影矩阵推导过程。很多都是从网上借鉴而来,往作者不要见怪。