3D坐标系、矩阵变换、视景体与裁剪

背景,员工卷铺盖走人了,也就是说微软搞谁,谁倒霉。直到OpenGL的出现,打破了这一魔咒,在与微软竞争的前期,OpenGL几乎甩了微软几条街,并成为事实上的工业标准。后来在微软的大力绞杀下,OpenGL几乎被完全赶出了游戏领域,退居高端图形领域。基本上现在是微软的Direct 3D统治游戏领域,而OpenGL则在高端专业图形领域占绝对统治地位。微软还是微软,OpenGL已经不是以前的OpenGL了,等会。。等会。。这句话咋这么熟悉?想起来了赵本山的小品里说过:你大爷还是你大爷,你大妈已经不是你5年前的大妈了,为什么这么说呢?话说搞OpenGL的那家公司被微软逼疯了,没错。。解散了。。但是OpenGL并没有消失,而是交给某开源组织托管、开发与维护了。哎。。。不说了,都是泪啊。。凡是牵扯到微软,那就是一部血泪史啊。。逼疯了无数企业。。但是话有说回来,商场上比尔盖茨是个侩子手而慈善上这家伙也不小气。。大把大把的捐钱。。

坐标系空间

在OpenGL里面,3D坐标系的X轴自左向右增大,y轴自下向上增大,z轴正方向从屏幕中心指向观察者。坐标系有以下几种:局部(模型)坐标系、世界坐标系、相机坐标系、屏幕坐标系;对应的矩阵变换则有模型变换、视图(相机)变换、投影变换,其中投影变换分为正视投影、透视投影。而坐标系之间的转换要用到矩阵。世界坐标系相当于是虚拟宇宙,位置固定不变,而局部(模型)坐标系是绘图的一个局部空间,是相对的,相机坐标系是以相机的镜头(或者人的眼睛)来观察物体的视觉空间。在3D中画图是现在局部坐标空间绘制,然后通过矩阵变换转移到世界坐标空间,接着转换到相机空间,然后在投影,最终会在光栅化的二维屏幕上渲染图形。

图一

图二

上面图片一是层次细节LOD地形网格,513像素X513像素,不过并没有达到完全的分辨率,而且不同的地方分辨率不同,此是后话。图片二是用OpenGL加载的一个ms3d格式的三维小汽车,这个小汽车是用3d max制作的3ds文件经过MilkShape 3D转换后得到的ms3d文件。这两个三维模型都是以三角形网格渲染而成的,不同的是图一没有进行文理贴图,而是以线框的模式渲染的,这样做是为了更好的看到3D渲染的细节;对应的图二则是以平滑模式渲染并且贴有文理。从本质上来说三维图像的最小单位是顶点,这些顶点以特定的方式送往3D API(典型的如OpenGL 3d api或者D3D api)并以三角形网格的形式进行渲染。当然也可以选择其他多边形如四边形进行渲染,但是三角形渲染最为方便,几乎所有的3D图形都是以三角形为图元进行渲染。从图一可以看出这个地形是有很多小的三角形网格组成的,事实上这个地形网格是以三角形扇的方式组织渲染的。现在我们看到的这两个图形是在屏幕坐标空间观察的,那么他们的第一站其实就是局部(模型)坐标空间,经过一系列3D流水线最终送往二维屏幕进行光栅化处理和渲染。在局部坐标系的物体有N个顶点组成,如果变换到世界坐标系的话需要对所有顶点做变换,共计N次变换。设物体的任一顶点为(loc_x ,loc_y , loc_z)。这个坐标是在局部坐标系下,要想变换到世界坐标空间需要将局部坐标系的原点移动到对应的位置(world_x,world_y,world_z)处,并且同时移动三维模型的所有顶点坐标。很容易得到最终的坐标:(loc_x+world_x,loc_y+world_y,loc_z+world_z)。现在我们先来看一幅图片:

我们惊奇的发现这个计算结果正是我们想要的,没错,你猜对了,在3D图形里面顶点的变换都是通过矩阵完成的,而这个平移变换是最简单的一种矩阵变换,其他的还有旋转、缩放等等。上面的图一、二就是在3D流水线里经过一些列像上述那样的矩阵变换最终才从幕后走向台前展现在大家眼前。由上可以看出每一个顶点经历了16次乘法运算、12次加法运算,共计28N次计算,当然在矩阵变换之间可能还有进行了诸如光照、纹理等操作。假如一个三维场景共有100万个顶点,那么就要做2800万次计算,这还没有加上后面的相机变换、投影变换所做的矩阵运算以及光栅化、渲染等操作。由此可以看出来运算量是非常的大。那么显卡能承受如此巨大的运算量吗?后面会提到,3D 图形库(如OpenGL)会在图形进行渲染前将不必要的顶点裁剪掉,这样就不用渲染他们了,从而节省了GPU的运算量。但是光是依靠3D 图形库的裁剪功能还是不够,虽然裁剪掉了不需进行渲染的顶点,然而这些顶点已经消耗掉了大量的矩阵运算,尤其是当场景非常细腻的时候也就意味着顶点数目非常巨大。那么有没有方法可以在坐标系统进行矩阵变换前就被提前裁剪掉呢?答案是肯定的。举个例子,对于图一中的地形网格来说,他被渲染到屏幕是有条件的,其一:不在照相机视景体空间内的物体将被忽略不予处理;其二:对于远处的地面以低分辨率渲染,近处则以高分辨率渲染;其三:粗糙的部分以高分辨率渲染,平坦的部分以低分辨率渲染。假如有一个600X600的网格经过测试不在照相机的视景体内,那么这36万个顶点就不用进行后续的大量矩阵运算,而测试所消耗是由8个顶点组成的六面体,这个运算量的消耗无疑是值得的。至于如何进行相机裁剪,在层次细节算法里面将会详细说明。在OpenGL以及D3D里面用户一般不会直接操作矩阵,OpenGL会将用户的函数调用解释为矩阵,比如用户调用gluPerspective(参数。。)时,OpenGL会根据函数的参数设置视图矩阵并与当前的视图矩阵相乘。

世界坐标系空间经过上面的平移操作物体就被移动到世界坐标系,这个坐标系是固定不变的,相当于虚拟宇宙中心。此时物体还不能呈现于屏幕,还要经历九九八十一难才能与观众见面。进入世界坐标系以后,照相机的视点可能不在原点,并且视点可能还不是朝向z轴负方向。此时就要将照相机平移到世界坐标系原点,并且调整方向使相机视点朝向z轴负方向。之所以要这样调整是因为如果相机位于原点并朝向z轴负方向的话会给处理带来极大的方便,至于是什么方便呢,我也不知道,反正是专家说的,至于你信不信,反正我是信了。在说明如何变换到相机空间我们先来看一下几个矩阵操作。设有世界坐标系空间的某一个点A(world_x,world_y,world_z)分别绕x轴 y轴 z轴旋转angle_x、angle_y、angle_z度到达B点。那么求其旋转后的坐标。

人生就像是一场旅行,遇到的既有感人的,

3D坐标系、矩阵变换、视景体与裁剪

相关文章:

你感兴趣的文章:

标签云: