第八章 几何变换与裁剪

来源:互联网 发布:淘宝泄露买家信息处罚 编辑:程序博客网 时间:2024/06/04 19:42

                                                                           第八章   几何变换与裁剪


一、虚拟世界的想象

 

         APO超级电脑建立了数万万亿的虚拟物体、生命体三维模型;浩瀚的虚空有着似乎无数的太阳系、星球。那时,我只是一只小小鸟;生活在称为地球的一个星球上。我建立了世界空间坐标,以地球南北为Y轴,东西为X轴,纵深为Z轴。地球上的大部分物体,如树木、山体等变化缓慢,它们在世界空间中较为稳定。但也有不少运动的生物,比如我。当我展开翅膀在空中飞翔时;只用一只眼,在我视角内场景不断变换;随着移动,在眼空间中;一些物体消失,另一些出现。当我手那一个镜子朝向后时,我又能从镜子里,看到消失的物体;世界真奇妙。我假定,在称为眼空间(或视觉空间)的坐标系统里,眼睛位于坐标系统的原点;场景的方向是z轴方向。当我飞近一个物体时,清晰细腻;飞远时,只有那模糊的形状。我知道,它们一直客观存在而形状无太大变化并变换色彩。黄昏的太阳给万物披上一层金黄;我知道黑夜将来临;万物的色彩也将化成黑色。飞啊飞,到达一个湖;月亮早已在湖面爬行。我想抓住月亮,但往往是抓到一条鱼。湖对面山顶的一颗树就是终点站;在那里,我会思考生命的起源、宇宙的规律;直到初升的太阳。有一天;一个自称APO的精灵,告诉我:你不妨顺着神的足迹,试图建立一个新的世界。从这以后,我终于有了理想。

 

二、 变换与裁剪:


      从世界空间位置到眼空间位置的变换时为视变换。典型的视变换结合了一个平移把眼睛在世界空间的位置移到眼空间的原点,然后适当地旋转眼睛。通过这样做,视变换定义了视点的位置和方向。我们通常把分别代表建模和视变换的两个矩阵结合在一起,组成一个单独的被称为modelview的矩阵。物体模型用一系列三角形来建立;3个顶点界定了一个三角形。很多时候,多个三角形共用一个顶点;而几何变换用顶点就行了。所以,我们建立一个顶点数组;以节省计算量。而三角形用3个顶点索引来描述;另外,我们需要三角形面的法线来计算光照、背面剔除等。

 

    齐次坐标能够用来明确区分向量和点,同时也更易用于进行仿射(线性)几何变换。如果(x,y,z)是个点,则齐次坐标变为(x,y,z,1); 如果(x,y,z)是个向量,则齐次坐标变为(x,y,z,0)。对于平移T、旋转R、缩放S的仿射变换:平移变换只对于点才有意义,因为普通向量没有位置概念,只有大小和方向。而旋转和缩放对于向量和点都有意义。

 

     对于一个普通坐标的点P=(Px,Py, Pz),有对应的一族齐次坐标(wPx,wPy, wPz, w),其中w不等于零。因此,如果把一个点从普通坐标变成齐次坐标,给x,y,z乘上同一个非零数w,然后增加第4个分量w。如果把一个齐次坐标转换成普通坐标,把前三个坐标同时除以第4个坐标,然后去掉第4个分量。由于齐次坐标使用了4个分量来表达3D概念,使得平移变换可以使用矩阵进行,从而仿射(线性)变换的进行更加方便。

 

      虚拟地球上有数不清的物体模型,嗯、使用64位寻址。我们不可能直接都拿它们去做顶点变换。只是对在视野中(视锥体内)可以看见世界的一些三角形进行。而另外那些看不见的三角形,就被裁剪掉。有许多不同的裁剪方法。最简单的裁剪方式就是把世界分成区域,每个区域有一个其他可见区域的列表。那样,只需要显示针对任何给定点的可见部分,如何生成可见视野区域的列表是技巧所在,有许多方法可以用来生成可见区域列表,如BSP树、窥孔等等。BSP表示二叉空间分割,是一种将世界分成小区域的的方法,通过组织世界的多边形,容易确定哪些区域是可见的而哪些是不可见的。它同时也以一种非常有效的方式让你知道你位于世界中的什么地方。在基于窥孔的引擎里,每个区域(或房间)都建造有自己的模型,通过每个区域的门(或窥孔)能够看见另外的区段。渲染器把每个区域作为独立的场景单独绘制。APO采用BSP树,如果知道眼睛的位置;则通过中心数据库查询,会得到眼睛位置附近(一定半径)的物体模型数据。这还跟位置有很大关系,要知道物体是一个容器,有内外之分。比如,你的位置是在房子内或房子外;得到的数据模型肯定是不一样!有运动的生物,或许下一刻,你的数据模型就变化了。许多情形都需考虑,模型是动态的;你的渲染必须快速。物体模型数据可能很大,必须先剔除视锥体外的物体;减少计算量;之后,才开始视变换。离眼睛近的物体模型细腻等级就高,意味着模型的三角形数多;反之就低,模型的三角形数少。当你SQL中央数据库时,物体模型的数据与离眼睛的距离有关的。你在天上往下俯视时,距离远;视锥体内包含的物体多,但模型的三角形数少;这是一种平衡。物体模型的建立、LOD等级等并不是APO显示管理者的事情。所以,三角形调整(曲面细分等功能)可能会被剔除出GPU。数据库返回的是不超过64K个的物体模型数据包。如何剔除视锥体外的物体呢?我不会先做视变换才踢的;万一有千万个顶点呢。能否用物体位置向量 - 眼睛位置向量,即是眼睛到物体的向量 来计算与视向量的夹角大于45度来剔除呢?当然,物体有大小、方向;可能需计算物体包围盒6个点的位置向量比较;看物体方向吧,通常最少需2个位置点来比较。最大64K个物体经向量夹角剔除后剩下最多8K个物体;这些物体需要用三角形顺序及法线与视向量的夹角是否大于90度来做系列三角形背面剔除。形成的新的物体数据包的系列三角形才会做视变换!之后,视锥体外精细剔除:与视锥面相交的三角形会裁剪形成新的在视锥内的三角形,交点是新的顶点。但在这个不规则的视锥体中进行裁剪并非那么容易的事情,所以经过图形学前辈们的精心分析,裁剪被安排到规则观察体(Canonical View Volume, CVV)中进行,CVV是一个正方体,x, y, z的范围都是[-1,1],三角形裁剪就是用这个规则体完成的。所以,事实上是透视投影变换由两步组成:

1)  用透视变换矩阵把顶点从视锥体中变换到裁剪空间的CVV中。

2)  CVV裁剪完成后进行透视除法。

 

最后,在这不到8K个物体我们要做分离成3组独立行进的物体数据包:

1、        物体模型含有透明属性时,该物体模型的系列三角形是要单独一个着色流的。它们要在所有的非半透明多边形绘制之后才能够绘制(混色)。但通常没有太多透明的多边形。

2、        当物体模型含有镜面反射属性时,该物体模型的系列三角形也是要单独一个着色流的;通常使用光线跟踪来着色。那需要用第二视眼、第三视眼。。。来进行递归计算。

3、        剩下的大部分物体是常规的进行几何着色、光照、纹理贴图等。最后在光栅化时进行z缓冲剔除、根据顶点的颜色对三角形其他像素的颜色进行插值等。

 

三、数据包格式

 

    从中央数据库返回的不到64K个物体模型文件,有多种类型。通常有七种类型的物体模型数据包。眼睛(相机)类、光源类、含有全反射属性物体类、含有透明属性物体类、动物类、植物类、常规物体类。文件格式:

 

WTMXWJ{

  BU16   WTMXU;    // 本文件物体模型总数。

  BU16   WTLXU;    // 本文件物体类型总数。

  BU32  Vertices_size; // 顶点总数

  BU32  Triangle_size; // 三角形总数

  BU32  Vertices_IP;   // 顶点数组的首指针。

 

WTMXUU[WTLXU]{    // 有WTLXU个类型的不定长结构数组

  BU32   WTLF_ID;  // 物体类标识。

  BU16   LWTMXU;   // 本类物体模型总数。

  BU16   LWTLXUU;  // 本类型属性。

  BU32W  LWTMX[LWTMXU];  // 本类的物体模型数组。

  BU4WF  Vertices[Vertices_size]; // 顶点数组。Float x,y,z,w

  BU4WF  Vt_color[Vertices_size]; // 顶点颜色数组。Float R,G,B,A

// 光照处理前或后的颜色、用于Gouraud着色等。

 

  BU32   Ta_index[Triangle_size]; // 三角形索引数组

  BU4WF  Ta_id[Triangle_size];  // 三角形顶点索引数组,

//三个顶点的索引 Float x,y,z, 及材质 mati。

 

  BU4WF  Ta_n[Triangle_size];    // 三角形面的法线及长度,

//  Float nx,ny,nz,及法线长度 nlen  的数组。

  BU8WF  Ta_uv[Triangle_size];   // 三角面3个顶点之纹理坐标6W及

// 纹理信息指针、列表 2W  的数组。

 

  BU32Z  name[WTMXU];  // 物体模型名字数组

}


数组的细分主要是考虑流处理器SP的效能。

 

    第0号到6号结构分别是描述眼睛(相机)类、光源类、含有全反射属性物体类、含有透明属性物体类、动物类、植物类、常规物体类。眼睛(相机)也是属于一个物体的。在一个场景中,可能有多个眼睛;这不是一个人的世界。如2人面对面交谈的情景,他说我后面有一只猫是可能的。因为他可以看到我的背面。

 

BU32W  LWTMX[]{  // 本类的物体模型数组项定义。

  BU16  WTID;     // 本文件中的物体ID。

  BU16  state;    // 物体状态。

  BU32  nameID;   // 物体名字ID。32Z的名字数组中的项索引。

  BU32  mati;     // 物体材质。

  BU32  Max_size; // 物体的最大尺寸(长、宽、高、直径)。

  BU32  Maxsm_len;// 最大尺寸面的法线长度。

  BU3W  Maxsm;    // 最大尺寸面的法线。

  BU3W  World_pos; // 物体中心的世界坐标。

  BU32  VerticesU; //物体的顶点数

  BU32  TriangleU; // 物体的三角形数

  BU32  UZIP;      // 数组指针。(指向顶点数组、三角形数组等)

  BU18W  attr;     // 物体属性。不同物体的属性不一样;在这定义。

 

    你可简单的看作APO有15个GPU。不到64K个物体模型文件WTMXWJ,多个GPU针对不同的视眼作变换和裁剪生成多个新的变换后的物体模型文件WTMXWJx。除了最终的帧缓存着色是必须在显示管理者上进行。其它的,实时光线跟踪、光栅化、光照、纹理贴图、着色都可在其它GPU上进行,并都是可编程并行流的。这只是初步规划,最终结论以后面的章节为准。我并不太关心、也可以说不懂OPENGL、D3D的库;我关注的是具体的实现过程及运算速度。


0 0
原创粉丝点击