3D流水线

 

渲染流水线
        对于Direct3D,上述过程通常被认为是一个渲染流水线。
        未经转换和照明的顶点从一端进入,在内部这些顶点将完成几个连续操作。然后,经过转换和照明处理的顶点从另一端出来。
 
        渲染流水线的大部分过程都是在进行坐标转换 ,将顶点从一个坐标系转换到别的坐标系。
 
        在使用Direct3D来进行转换时,用户只需要提供描述系统转换的完整转换矩阵,通过IDirect3DDevice->SetTransform方法来实现相应的变换。
 
HRESULT SetTransform(
           D3DTRANSFORMSTATETYPE State, //变换的类型
           CONST D3DMATRIX *pMatrix  //进行变换的变换矩阵);
 
 
世界变换
 
渲染流水线的第一步是将物体从本地坐标系转换到世界空间,这一过程称为世界变换。
       它的作用是:  把独立的物体放在一个统一的坐标系内,组合成一个完整的场景。在世界变换中主要完成的是对模型的转换,包括旋转、缩放、平移等。
       设置世界变换的函数如下:
  
g_pD3Ddevice->SetTransform(
                                 D3DTS_WORLD, &matWorld);
g_pD3DDevice为有效的Direct3D设备指针
matWorld代表一个变换矩阵。
 
 
视图变换
  
把物体转换到世界空间后,接下来就需要确定视图空间,这个过程称为视图变换。
 
      首先我们需要确定虚拟摄像机的属性。在Direct3D中,关于虚拟摄像机的属性主要包括:摄像机位置、摄像机的朝向和摄像机的正方向,分别用向量表示。可以从以下函数生成视图变换的矩阵。     
 
D3DXMATRIX *D3DXMatrixLookAtLH(         
          D3DXMATRIX *pOut,         //输出用于视图变换的矩阵
          CONST D3DXVECTOR3 *pEye,    //摄像机的位置
          CONST D3DXVECTOR3 *pAt,       //摄像机朝向的位置
          CONST D3DXVECTOR3 *pUp       //摄像机的正方向
      );
 
 
接下来,使用下面的函数来设置视图变换。
 
g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
g_pD3DDevice为有效的Direct3D设备指针
matWorld代表一个视图变换矩阵
  
投影变换
 
把摄像机观察到的三维景像显示在二维的平面上,这种三维到二维的变换就是投影变换。实际应用中,主要的投影变换有两种类型:
Ø正交投影
Ø    透视投影
 
  
1.  正交投影
     
       在正交投影中,投影向量与观察平面垂直,物体坐标沿观察坐标系的z轴平行投影到观察平面上,观察点和观察平面的距离不影响物体的大小。    
  
可以使用下面的函数来得到正交投影的变换矩阵:
  
D3DXMATRIX *D3DXMatrixOrthoLH(         
         D3DXMATRIX *pOut, //输出用于正交投影的变换矩阵
         FLOAT w, //取景体宽度
         FLOAT h, //取景体高度
         FLOAT zn, //取景体离摄像机的最近距离
         FLOAT zf //取景体离摄像机的最远距离
      );
  
2.  透视投影
 
       透视投影的特点:是越远的物体在投影平面上的成像越小,这样生成的投影图更加具有纵深感。
 
      透视投影的观察范围是一个平截台体。平截台体是指一个去除了尖头的锥体。在计算机图形学中,观察平截面的概念是,锥体的尖头位于虚拟摄像机的位置,而摄像机指向该锥体的底部,将锥体的四个侧面向屏幕的四边投影,并切除远近裁剪平面位置的锥体的前后部分。得到的观察平截面代表摄影空间在渲染场景中的可见部分。实际应用中,如果我们要实现一个三维的场景,则我们通常使用透视投影。
  
下面的函数用于定义透视变换的矩阵:
 D3DXMATRIX *D3DXMatrixPerspectiveFovLH(         
        D3DXMATRIX *pOut, //输出用于透视投影的变换矩阵
          FLOAT fovY, //摄像机镜头的夹角(在y轴上的成像角度)
          FLOAT Aspect, //平截台体的纵横比
          FLOAT zn, //近平截面的距离
          FLOAT zf //远平截面的距离
   );
  
顶点从均匀转化为非均匀:
 
Ø在顶点坐标信息里除顶点位置信息外再加一个W分量坐标,设定其初始值为1.0。
Ø在顶点通过T&L流水线中的多个矩阵传送时,w坐标将改变它的值。w值不为1.0的顶点是均匀的。当转换换结束时,就需要把顶点恢复为不均匀的形式,这是通过x、y和z坐标除以w完成的。w坐标的倒数也被存储起来。这个过程非常必要,因为光栅处理程序需要得到以非均匀x、y和z坐标以及均匀w的倒数值(reciprocal-of-homogeneous-w, RHW)表示的顶点。
 
 
视口变换
  
空间变换的最后一步是通过定义屏幕显示区域的实际宽、高等参数,将顶点从投影坐标转换为最终显示的以像素为单位的屏幕坐标。
  
在Direct3D中定义的视口结构:
 
typedef struct _D3DVIEWPORT9 {
          DWORD X; //视口区域的左上角x坐标
          DWORD Y; //视口区域的左上角y坐标
          DWORD Width; //视口区域的宽度
          DWORD Height; //视口区域的高度
          float MinZ;   //视口内景物的最小深度值,0-1.0之间,通常为0
          float MaxZ;   //视口内景物的最大深度值,0-1.0之间,通常为1
      } D3DVIEWPORT9;
  
通常情况下,参数MinZ和MaxZ被设为0和1.0f,即取景范围的最近和最远距离,表示在投影取景范围内,顶点只要满足了x∈(-1.0f , 1.0f)、y∈(-1.0f , 1.0f)和z∈(0.0f , 1.0f),就能通过裁剪,予以显示。
  
SetViewport()相当于把投影空间的顶点P(x,y,z)乘以以下变换矩阵:
 
 

 

经过转换后,顶点P的屏幕二维坐标x’,y’为:
      x, = x × Width/2 + X + Width/2
      y, = y × Height/2 + Y + Height/2
      z’值为:
      z, = z × (MaxZ - MinZ) + MinZ
  
光栅化
经过视口变换,我们获得了一系列2D三角形。光栅化阶段被用于在描绘三角形时,计算每个像素的颜色值。
  
光栅化过程需要进行大量计算,并通常由特定的图像硬件来完成。光栅化的结果时一个2D图像,将被显示在屏幕上。
 
 
posted @ 2011-11-12 22:15  ☆A希亿  阅读(1380)  评论(2编辑  收藏  举报