仿射坐标与齐次坐标

这是我们经常使用的两种坐标,我们用DX来创建顶点结构是,有这两种坐标

假如FVF使用的是D3DFVF_XYZ时,我们就说我们用的是齐次坐标,齐次坐标表示我们只用3个分量来表示顶点在世界中的位置。

顶点示例

struct Vertex{

   float x,y,z;

奇怪!!难道还有第四个坐标?-------没错!       难道使用4维空间,第四维不是时间吗????----不是!!

为什么要第四个坐标呢?先讲用处再说原因,当我们FVF使用的是D3DFVF_XYZRHW时,我们用的是齐次坐标,由于此标志表示的是这些顶点已经通过变换,可以直接显示在屏幕上,其顶点的中x、y表示的是屏幕坐标,注意此时的(0,0)不是在窗口中心,而是在左上角,这与普通程序一样的坐标空间,而Z值只能在(0,1)之间,因为Z这里表示的是具体的深度值,假如不明白的自己找资料查查为什么最后Z坐标变成了(0,1)里面(提示:投影结果,在3D编程大师技巧里面有详讲变换的)。0表示最眼前,注意这与远近裁剪面不一样那里一般是(1.0f,1000.0f),1表示最近。还有个w分量(见下面的顶点格式)直接置一,因为这是变换后的空间。当然,你不知道w有什么用,等下就告诉你。

顶点示例

struct Vertex{

    float x,y,z,w;

}

 

 

 

为什么要用两种坐标系统

对于第一种坐标表示[x,y,z]

第二种[x,y,z,w]

我们在坐标变换中有旋转,缩放,正交投影,镜像变换,切变等这些都是属于线性变换(具体参见《3D游戏基础:图形游戏开发》的第八章),在这些变换中我们只要3*3的矩阵就可以表示这些变换。但对于像平移之类的变换用3*3的矩阵是表示不了的,但是用4*4的矩阵却可以轻易表示,只要我们的w为一,矩阵的_41、_42、_43就是平移量,不是吗???这可以说是用齐次坐标的一个原因,4*4既可以用来做线性变换有可以用来做平移,不是很好吗,一个矩阵表示全部。有人会说在使用D3DFVF_XYZ时,不是只有3个坐标吗?我想说的是,问得好,假如你编写过shader的话,你就知道Shader中我们就是用矩阵直接乘以3维向量的,因为Shader会自动补第四个数为1(详细的Shader介绍,我推荐看《精通DirectX.3D图形与动画程序设计》王德才的,这本书讲的比较全)。有人又说了,它会自动不全那么为什么还要有第四个量呢,不是多此一举的吗?是的,第四个分量只是让我们知道为什么要有它,实际少用,但第四个确实有他的意义。

    我来介绍一下,2D空间是一个平面,我们把他当作是在3D空间中在z=1处的平面,不是吗???所以实际把2D空间投影到3D就是(x,y,1)

所以二维的齐次坐标为(x,y,w)--->w=1,表示2D坐标投影到3D空间的z=1上,当然你可以投影到3D空间中的z=任意处,所以其实在2D中的坐标是(x/w,y/w),是这样的,z不能为0哦,那么就表示,该点离我们无穷远

    同理在三维中,三维坐标只是四维空间中的一个立体空间,当然我没有机会看4维空间了,所以齐次坐标是(x,y,z,w),同理在3D空间坐标是(x/w,y/w,z/w),不过这有什么用呢?我负责任的告诉你,这真的有用,特别是在,将相机坐标,投影到视平面(什么是视平面我就不说了3D游戏编程大师技巧里说的很清楚)时,因为那里3D转2D。你看3D要转2D那么直接是(x,y,z)---->(x/z,y/z),这就是3D坐标,2D齐次坐标,根据此计算出来的2D坐标,然后用插值求出,两点之间的所有点的z值,这里提一下z缓存的问题,由于z值是由投影后的(x,y)而不是由3D空间点开进行插值的,所以这时的插值绝对会有误差,以为坐标都除了个z,误差加大了,这里不能用z缓存,因为这里算出的Z是非线性的,虽然大部分差不多,但是还是有像素偏差,我们不插值求出z,而是求1/z,为什么呢,因为避免了除z产生的误差。就说到这吧,不想写了,也怕写了看不懂!!

你可能感兴趣的:(3D游戏菜鸟之路)