本系列文章由zhmxy555(毛星云)编写,转载请注明出处。
文章链接: http://blog.csdn.net/zhmxy555/article/details/8408723
作者:毛星云(浅墨) 邮箱: happylifemxy@163.com
本篇文章里,我们首先对Direct3D中固定功能渲染流水线相关概念进行了深入的剖析,然后介绍了创建三维游戏世界的四大变换的概念和使用的方方面面,最后依旧是提供文章配套的详细注释的demo源代码的欣赏,并在文章末尾提供了源代码下载。
从本篇文章开始我们就来开始来学习固定渲染流水线这套渲染体系。
其实固定渲染流水线和之后我们要学习的可编程渲染流水线体系有很多异曲同工之妙,所以先学习固定功能渲染流水线体系,再学可编程渲染流水线体系,就可以循序渐进,步步为营地掌握好DirectX。
空间中的物体需要使用三维坐标来描述,而我们的显示器是显然是二维的,所以在屏幕上渲染一个三维场景时,首先需要将物体描述空间物体的三维坐标变换为二维坐标(也就是世界坐标到屏幕坐标),这在Direct3D中称为顶点坐标变换。顶点坐标变换通常通过矩阵来完成。我们之前的几个demo中,演示的是如何显示一个二维的平面图形,它的顶点是以屏幕坐标系的二维值表示的,也是经过顶点坐标变换之后的顶点坐标数据,可以把顶点坐标变换想象成摄像的过程,三维世界的景物通过摄像机拍摄显示在二维的相片之上,有所不同的是把相片换成了屏幕。
文章开头,我们先来看一下固定功能渲染流水线这套渲染体系的核心思想。
一、固定功能渲染流水线概述
在固定功能渲染流水线这套体系中,大体分为两个阶段,第一阶段我们将它称为坐标变换和光照处理阶段(Transforming &Lighting,简称T&L阶段)。在这个阶段中,每个对象的顶点从一个抽象的、浮点坐标变换到基于像素的屏幕空间当中。这里需要注意的是,坐标变换不仅包含物体顶点位置,它还可能包括顶点的法线、纹理坐标等等。并根据场景中光源和物体表面的材质对物体顶点应用不同类型的光照效果。还有其他一些比较重要的任务,比如视口的设置和裁剪也是在第一阶段进行的。讲完第一阶段,我们再来看看第二阶段,第二阶段称为光栅化处理阶段。顶点在经过第一阶段也就是变换与光照阶段的“洗礼”之后,已经略有雏形,在第二阶段,Direct3D将这些已经完成变换和光照阶段的顶点组织为以点、线、面为基础的图元,应用纹理贴图和物体顶点的颜色属性,并根据相关渲染状态的设置(比如着色模式等)
,决定每个像素最终的颜色值,并且在屏幕上显示出来。为了大家更宏观和更深入的理解,浅墨依然是配了一幅图。通过这幅图,大家可以对固定功能渲染流水线的结构脉络做到一目了然。

需要注意的是,渲染流水线中的步骤并不一定都要有的,根据实际情况可以省略一些。比如之前我们给出的几个demo,都是省略了变换和光照阶段,直接将顶点作为屏幕坐标输出显示。因为我们在定义顶点的属性的时候,给我们的顶点定的“标签”是D3DFVF_XYZRHW,表示包含经过坐标变换的顶点坐标值,这样Direct3D就知道这些顶点坐标不需要再经过顶点坐标变换了,他们的坐标值就是最终显示屏幕上的坐标值了。
目前我们重点介绍坐标变换和光照处理阶段(Transforming &Lighting,简称T&L阶段),也就是T&L阶段。在这个过程中,未经过变换和光照的顶点从一端进入,在流水线内部这些顶点将完成几个连续的操作,这几个操作按顺序分别为世界变换,取景变换,光照处理,投影变换以及视口变换。经过这些处理之后的顶点从另一端出来,表示已经完成坐标变换和光照处理了。我们的应用程序是通过指定几个矩阵、视口以及所使用的光线来建立T&L流水线的,然后应用程序将顶点送入流水线,并对这些顶点在流水线中进行坐标变换、照明以及裁剪,将其投影到屏幕空间当中,并根据视口的规定对其进行缩放。顶点在T&L流水线中进过“涅槃”之后,就可以去到第二阶段——光栅化处理阶段去完成新的试炼了。
关于变换和光照渲染流水线阶段,也就是T&L阶段,浅墨也配了一幅图,方便大家的记忆与理解:

二、携手迈向三维世界:四大变换显身手
首先来讲讲周边的概念。
在Direct3D中,如果我们未进行任何空间坐标变换而来绘制图形的话,图形将始终处于应用程序窗口的中心位置,在默认情况下这个位置就会成为世界坐标系的原点(0,0,0)。另外,我们也不能改变观察图形的视角方向。默认情况下的观察方向是世界坐标系的z轴正方向,也就是垂直程序窗口并向里观察的方向。之前我们的几个demo都是默认的z轴正方向为观察方向的。
而为了迈向三维世界,为了能够随心所欲地在三维世界中绘制和观察游戏画面,就是四大变换的show time了。
所谓四大变换,其实是浅墨自己在学习Direct3D的时候自己归纳的一个东西- -,也就是世界变换,取景变换,投影变换和视口变换的总称。
下面我们先来大致概括一下这四大变换的用途。
1. 为了能在世界空间中的指定位置来绘制图形,就需要在绘制图形前进行四大变换之一的世界变换运算。
2. 为了以不同的视角观察图形,就需要用到四大变换之二的取景变换运算。
3. 为了将相对较远的图形投影到同一个平面上并体现出“近大远小”的真实视觉效果,就需要用到四大变换之三的投影变换。
4. 为了控制显示图形的窗口的大小,比例以及深度等等信息,就要用到四大变换之四的视口变换。
下面我们就开始分别展开讲解这四大变换的细节知识。在讲解之前,有必要先跟大家说明一下。这里的四大变换的前三都是以矩阵作为载体的。这四大变换相关知识中或多或少会涉及到矩阵、向量,平面和射线等相关的数学知识,这些数学知识浅墨不准备专门花篇幅讲,因为讲起来都是概念,漫无目的,而且篇幅很长或许会花费几次更新的时间,况且写出来的东西肯定没新意而且没劲,所以没有写出来的必要。如果去学习Direct3D这款API的话,大可不必去纠结那么多数学概念。对矩阵和向量稍微有些了解就足够了,余下的高中数学(高中数学中没有矩阵相关的知识,所以矩阵相关概念需要另外学习)完全可以对付。如果实际过程中有不理解的地方再有的放矢地去查书和资料,这样学习起来会轻松很多,学习效率也会高得多。关于这方面数学知识的查阅资料,可以参看Direct3D 9龙书《Direct3D 9.0 3D游戏开发编程基础》的第一部分,Frank Luna已经为我们讲解得非常到位了。
好了,下面就开始依次讲解吧。
Ⅰ.四大变换之一:世界变换
根据物体模型的大小、方向以及其他模型之间的相对关系,世界变换将物体模型从自身的局部坐标系中转换到时间坐标系中,并将所有的物体模型组织为一个场景,如下图:

就像这个世界上有很多不同的个体,我们每个个体都有自己独特的局部坐标系,而我们每个个体仅仅是这个世界中的一份子而已。就像那句英文名言的前半句一样,to the world,you maybe one person。
世界变换包括平移、旋转和缩放变换,我们可以通过D3DX库中D3DXMatrixTranslation、D3DXMatrixRotation*和D3DXMatrixSaling函数来进行变换,并得到一个世界变换矩阵。
其中D3DXMatrixTranslation用于矩阵的平移操作,D3DXMatrixRotation*用于矩阵的旋转操作,D3DXMatrixSaling用于矩阵的缩放操作(稍后会分别介绍)。这三种变换是矩阵的最常用的变换。
调用这些函数将我们矩阵调整好之后,接着我们就调用IDirect3DDevice9接口的SetTransform方法来运用世界变换矩阵,表示认定某某矩阵就是我们的世界变换矩阵了。
我们可以在DirectX SDK中查到SetTransform方法的原型如下:
- HRESULT SetTransform(
- [in] D3DTRANSFORMSTATETYPE State,
- [in] const D3DMATRIX *pMatrix
- );
cpp运行
■ 第一个参数,D3DTRANSFORMSTATETYPE类型的State,明显的可以看到,它是一个D3DTRANSFORMSTATETYPE枚举类型,用于表示变换的类型,是四大变换前三者之中的哪一种。可以取值为D3DTS_WORLD,表示世界矩阵,或者是D3DTRANSFORMSTATETYPE枚举中的一种,这个D3DTRANSFORMSTATETYPE枚举类型定义如下:
- typedef enum D3DTRANSFORMSTATETYPE {
- D3DTS_VIEW = 2,
- D3DTS_PROJECTION = 3,
- D3DTS_TEXTURE0 = 16,
- D3DTS_TEXTURE1 = 17,
- D3DTS_TEXTURE2 = 18,
- D3DTS_TEXTURE3 = 19,
- D3DTS_TEXTURE4 = 20,
- D3DTS_TEXTURE5 = 21,
- D3DTS_TEXTURE6 = 22,
- D3DTS_TEXTURE7 = 23,
- D3DTS_FORCE_DWORD = 0x7fffffff
- } D3DTRANSFORMSTATETYPE, *LPD3DTRANSFORMSTATETYPE;
cpp运行
其中D3DTS_VIEW表示取景变换,D3DTS_PROJECTION表示投影变换。而D3DTS_TEXTURE0~7显然表示的就是某层纹理(0到7层)对应的变换矩阵了 。
第二个参数,const D3DMATRIX类型的*pMatrix,是一个实实在在有内容的矩阵,显然就是我们想要设置为和第一个参数中指定的类型相挂钩的候选人矩阵了。
接着我们来分别介绍经常会用到的矩阵的一些基本变换方法:
1.矩阵的平移
首先介绍D3DXMatrixTranslation方法,D3D中的平移函数。
在Direct3D里,平移矩阵应是使用最多的矩阵。这是因为每个物体的相对位置,都是通过平移矩阵来创造出来的。物体的整体移动,说白了就是坐标点的移动。比如从点(x,y,z)移动到新的位置(x', y', z')。在Direct3D就为我们提供了D3DXMatrixTranslation方法用于矩阵的平移。我们先来看一下这个函数的原型:
- D3DXMATRIX * D3DXMatrixTranslation(
- __inout D3DXMATRIX *pOut,
- __in FLOAT x,
- __in FLOAT y,
- __in FLOAT z
- );
cpp运行
这个函数其实就是在创造一个有相对于原点(0,0,0)有偏移量的矩阵出来。我们先来看一下各个参数的意义。
█ 第一个参数,D3DXMATRIX类型的*pOut,从类型上来看我们就知道他是一个D3DXMATRIX类型的4 X 4的矩阵,我们调用这个D3DXMatrixTranslation方法,其实就是在为这个矩阵赋值,让这个矩阵相对于原点有一个偏移量,也就是我们需要平移的距离。
而具体的平移操作其实并不是由这个函数完成的。,这个函数其实是在创建一个平移矩阵。
█ 第二个参数,FLOAT类型的x,显然是X轴的平移量。
█ 第三个参数,FLOAT类型的y,显然是Y轴的平移量。
█ 第四个参数,FLOAT类型的z,显然是Z轴的平移量。
比如要沿着Z轴的正方向平移10个单位,就需要按下面来设置平移矩阵:
- D3DXMATRIX mTrans;
- D3DXMatrixTranslation(&mTrans,0,0,10);
cpp运行
然后我们把需要进行平移操作的矩阵,乘以这个创建好mTrans矩阵,就完成了平移操作。比如说我们有一个mMtrix矩阵,我们需要这个mMtrix矩阵沿Z轴正方向平移10个单位,就让mTrans和mMtrix相乘就可以了,他们相乘的结果就是mMtrix矩阵向上平移10个单位后的矩阵。其中相乘操作用 D3DXMatrixMultiply来完成。
- D3DXMATRIX * D3DXMatrixMultiply(
- __inout D3DXMATRIX *pOut,
- __in const D3DXMATRIX *pM1,
- __in const D3DXMATRIX *pM2
- );
cpp运行
第一个参数,为输出的结果。第二和第三个参数为参加乘法的两个矩阵,且pM1在左,pM2在右,因为矩阵相乘涉及到相乘顺序的问题。这个函数的作用可以用一个式子来表示,也就是pM1 * pM2=pOut。
所以,整体来看,要把mMtrix矩阵向Z轴正方向平移10个单位,就是如下的代码:
- D3DXMATRIX mTrans;
- D3DXMatrixTranslation(&mTrans,0,0,10);
- D3DXMatrixMultiply(&mMtrix,&mMtrix,&&mTrans);
cpp运行
再举一个例子,如果我们仅仅是将一个物体沿X轴正方向平移5个单位,Y轴负方向平移3个单位就可以了,也就是只做了平移操作,就可以直接把我们创建的这个中间矩阵作为世界矩阵使用,也就是如下代码:
- D3DXMATRIX mTrans;
- D3DXMatrixTranslation(&mTrans,5,-3,0);
- g_pd3dDevice->SetTransform(D3DTS_WORLD,&mTrans);
cpp运行
2.矩阵的旋转
旋转和平移类似,也是先用一个函数创建好用于旋转的一个中间矩阵,然后让我们需要旋转的那个矩阵右乘这个中间矩阵就好了。关于这个旋转中间矩阵的创建,用的就是地d9
dx9.lib库中的D3DXMatrixRotationX, D3DXMatrixRotationY以及D3DXMatrixRotationZ。这三个函数非常相似,我们就打包起来介绍得了,这三个函数的原型声明如下:
- D3DXMATRIX * D3DXMatrixRotationX(
- __inout D3DXMATRIX *pOut,
- __in FLOAT Angle
- );
- D3DXMATRIX * D3DXMatrixRotationY(
- __inout D3DXMATRIX *pOut,
- __in FLOAT Angle
- );
- D3DXMATRIX * D3DXMatrixRotationZ(
- __inout D3DXMATRIX *pOut,
- __in FLOAT Angle
- );
cpp运行
█ 第一个参数,D3DXMATRIX类型的*pOut,依然是作为输出结果的旋转矩阵。
█ 第二个参数,FLOAT 类型的angle表示要旋转的弧度值。
下面继续来举例子,同样,如果我们只对某个物体在世界坐标系中进行旋转操作的话,也可以把D3DXMatrixRotationX系列函数创造出来的中间矩阵作为我们的世界矩阵。
若要将一个对象沿Y轴旋转90度,也就是如下代码:
- D3DXMATRIX mTrans;
- float fAngle=90*(2.0f*D3DX_PI)/360.0f;
- D3DXMatrixRotationY(&mTrans, fAngle);
- g_pd3dDevice->SetTransform(D3DTS_WORLD,&mTrans);
cpp运行
3.矩阵的缩放
与旋转和平移类似,矩阵缩放也是先用一个函数创建好用于缩放的一个中间矩阵,然后让我们需要缩放那个矩阵右乘这个中间矩阵就好了。关于这个缩放中间矩阵的创建,为D3DXMatrixScaling函数,这个函数的原型如下:
- D3DXMATRIX * D3DXMatrixScaling(
- __inout D3DXMATRIX *pOut,
- __in FLOAT sx,
- __in FLOAT sy,
- __in FLOAT sz
- );
cpp运行
█ 第一个参数,D3DXMATRIX类型的*pOut,依然是作为输出结果的缩放矩阵。
█ 第二个参数到第四个参数,显然就是浮点型的X,Y,Z轴上的缩放比例了。
比如,要将一个物体在Z轴上放大5倍,代码就是这样写:
- D3DXMATRIX mTrans;
- D3DXMatrixScaling(&mTrans,1.0f,1.0f,5.0f);
- g_pd3dDevice->SetTransform(D3DTS_WORLD,&mTrans);
cpp运行
这一小节的最后,最后我们来一个综合的调用实例,比如要将一个物体在X轴上放大3倍,然后又绕Y轴旋转120度,最后又沿Z轴平移正方向10个单位,实现代码如下:
- D3DXMATRIX matWorld;
- D3DXMATRIX matTranslate,matRotation,matScale;
- D3DXMatrixScaling( & matScale,3.0f,1.0f,1.0f);
- float fAngle=120*(2.0f*D3DX_PI)/360.0f;
- D3DXMatrixRotationY(&matRotation, fAngle);
- D3DXMatrixMultiply(&matWorld,& matScale,& matRotation);
- D3DXMatrixTranslation(&matTranslate,0.0f,0.0f,10.0f);
- D3DXMatrixMultiply (&matWorld ,&matWorld,& matTranslate);
- g_pd3dDevice->SetTransform(D3DTS_WORLD,&mTrans);
cpp运行
另外提一个单位化矩阵的函数,也就是D3DXMatrixIdentity函数。其用法非常简单,唯一的参数就是单位化之后的输出矩阵,也就是这样写:
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld); // 单位化世界矩阵
另外再提一点,关于矩阵的乘法,因为Direct3D对D3DXMATRIX矩阵类型进行了扩展,对矩阵乘法进行了重载,所以矩阵的乘法运算可以不用拘泥于上面讲到的D3DXMatrixMultiply()来实现了,可以简单地使用乘法运算符“*”就可以了,即多个矩阵的乘积可以这样写:
matAnswer=mat1*mat2*mat3*mat4……*matN
Ⅱ.四大变换之二:取景变换
取景变换,人如其名,就是用来取景的,也就是设置Direct3D中的虚拟摄像机的位置和观察点。对于处于不同位置的虚拟摄像机和观察点,其观察物体模型的视角方向也有所差异,因此实际看到的物体模型的实际形状也有所不同。正所谓“横看成岭侧成峰”,就像这幅图所传达的观点一样:

为了确定一个虚拟摄像机的位置和观察方向,需要指定虚拟摄像机在世界坐标系中的位置、观察点位置以及正方向。为了能够进行取景变换,首先需要通过D3DX库中的D3DXMatrixLookAtLH函数计算并得到一个取景变换矩阵(或观察矩阵),然后同样调用IDirect3DDevice接口的SetTransform方法应用取景变换。
其中,D3DXMatrixLookAtLH函数的声明如下:
- D3DXMATRIX * D3DXMatrixLookAtLH(
- __inout D3DXMATRIX *pOut,
- __in const D3DXVECTOR3 *pEye,
- __in const D3DXVECTOR3 *pAt,
- __in const D3DXVECTOR3 *pUp
- );
cpp运行
然后依然是函数参数的介绍:
█ 第一个参数,D3DXMATRIX类型的*pOut,最终生成的观察矩阵。
█ 第二个参数,const D3DXVECTOR3类型的*pEye,指定虚拟摄像机在世界坐标系中的位置。
█ 第三个参数,const D3DXVECTOR3类型的*pAt,为观察点在世界坐标系中的位置。
█ 第四个参数,const D3DXVECTOR3类型的*pUp,为摄像机的上向量,通常设为(0,1,0)就可以了。
依然是一个使用的例子,代码如下:
- //建立并设置观察矩阵
- D3DXVECTOR3 vEyePt( 0.0f, 8.0f,-10.0f ); //摄像机的位置
- D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );//观察点的位置
- D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );//向上的向量
- D3DXMATRIX matView;//定义一个世界矩阵
- D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );//计算出取景变换矩阵
- g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); //应用取景变换矩阵
cpp运行
Ⅲ.四大变换之三:投影变换
经过上一步的取景变换之后,物体模型就位于观察坐标系中了,然而为了能够将三维场景显示在我们二维的显示平面上(因为我们的显示屏是二维的),还需要通过投影变换将三维物体投影到二维的平面上,这个过程我们就把它叫做透视投影。下面这幅图中以及显示得很清楚了:

我们可以看到,摄像机的距离和角度唯一确定了落地窗的大小。
就好比一个人站在的一间封闭房间里,房间唯一可以接收到光线的地方是一块高大的落地窗,而房间外面对着落地窗这边的,是一堵无限长无限宽,绵延到世界尽头的白色的墙。人眼透过落地窗看到房子外边三维的世界,最终投影在了那堵二维的墙上。
显然,投影窗口是一个二维平面,用于描述三维物体模型经过透视投影后的二维图像,在Direct3D中投影窗口平面默认定义为z=1的平面。
虚拟摄像机与投影窗口平面共同构成了一个对观察者可见的三维空间。在3D图形学中这部分空间被称作视截体(View Frustum),位于视截体内的物体模型被映射到二维投影投影平面上,而位于视截体外的物体模型或者其中一部分将不可见,这个过程我们称作裁剪(Clipping),(取屏幕内的景物,专注,屏幕外的一律无视)。
投影变换负责将位于视截体内的物体模型映射到投影窗口中。D3DX库中的D3DXMatrixPerspectiveFovLH函数可以用来计算一个视截体,并根据该视截体的描述信息创建一个投影矩阵变换。这个D3DXMatrixPerspectiveFovLH方法可以在MSDN中查到如下函数原型;
- D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
- __inout D3DXMATRIX *pOut,
- __in FLOAT fovy,
- __in FLOAT Aspect,
- __in FLOAT zn,
- __in FLOAT zf
- );
cpp运行
■ 第一个参数,D3DXMATRIX类型的*pOut,它为我们最终生成的投影变换矩阵。
■ 第二个参数,FLOAT类型的fovy,用于指定以弧度为单位的虚拟摄像机在y轴上的成像角度,即视域角度(View of View),成像角度越大,映射到投影窗口中的图形就越小;反之,投影图像就越大。
■ 第三个参数,FLOAT类型的Aspect,用于描述屏幕显示区的横纵比,他的值就为屏幕的宽度/高度。对应不同比例的显示屏幕,比如16/9,4/3等等,最终显示的投影图像可能会使图像被拉伸
■ 第四个参数, FLOAT类型的zn,表示视截体中近裁剪面距我们摄像机的位置,即人眼到“室内落地窗”之间的距离
■ 第五个参数,FLOAT类型的zf,表示视截体中远裁剪面距我们摄像机的位置,即人眼到“室外黑色墙壁”之间的距离
依旧是一个调用实例:
- //建立并设置投影矩阵
- D3DXMATRIXA16 matProj;
- float aspect = (float)(800/600);
- D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, aspect, 1.0f, 100.0f );
- g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
cpp运行
Ⅳ. 四大变换之四:视口变换
终于讲到四大变换的最后一个了。其实这一步非常的简单,也就是填下填空题,然后设置一下就好了。并不像前三大变换一样要用到矩阵相关的知识。下面就一起来具体看看视口变换的相关概念吧。
视口变换用于将投影窗口中的图形转换到显示屏幕的程序窗口中。视口是程序窗口中前的一个矩形区域,他可以是整个程序窗口,也可以是窗口的客户区,也可以是窗口中其他矩形区域,如图所示:

在Direct3D中,视口是由D3DVIEWPROT9结构体来描述的,其中定义了视口的位置,宽度高度等信息,在DirectX SDK 中我们可以查到该结构体的声明如下:
- typedef struct D3DVIEWPORT9 {
- DWORD X; //表示视口相对于窗口的X坐标
- DWORD Y; //视口相对对窗口的Y坐标
- DWORD Width;//视口的宽度
- DWORD Height;//视口的高度
- float MinZ;//视口在深度缓存中的最小深度值
- float MaxZ; //视口在深度缓存中的最大深度值
- } D3DVIEWPORT9, *LPD3DVIEWPORT9;
cpp运行
讲解完概念下面依旧是调用的实例:
方法一:
先做填空题,做完之后调用IDirect3D9Device9接口的SetViewPort方法设置当前窗口中的视口,然后Direct3D将自动完成视口变换。
- D3DVIEWPORT9 vp={0,0,800,600,0,1};
- g_pD3dDevice->SetViewport(&vp);
cpp运行
方法二:
结构体的内容别开来赋值:
- D3DVIEWPORT9 vp;
- vp.X = 0;
- vp.Y = 0;
- vp.Width = 800;
- vp.Height = 600;
- vp.MinZ = 0.0f;
- vp.MaxZ = 1.0f;
- g_pd3dDevice->SetViewport(&vp);
cpp运行
其实也就是填结构体填空题的两种方式而已。
Ⅴ.总结
四大变换分为:世界变换,取景变换,投影变换,视口变换。
1.为了能在世界空间中的指定位置来绘制图形,就需要在绘制图形前进行四大变换之一的世界变换运算。
2.为了以不同的视角观察图形,就需要用到四大变换之二的取景变换运算。
3.为了将相对较远的图形投影到同一个平面上并体现出“近大远小”的真实视觉效果,就需要用到四大变换之三的投影变换。
4.为了控制显示图形的窗口的大小,比例以及深度等等信息,就要用到四大变换之四的视口变换。