现在的位置: 首页 > 综合 > 正文

DirectX 9.0 学习笔记

2013年12月03日 ⁄ 综合 ⁄ 共 14348字 ⁄ 字号 评论关闭

                DirectX 9.0
1:平面(法向量(normal vector)和平面中一点表示。
2,D3DX库用如下结构体来表示一个平面类,typedef struct D3DXPLANE{}
3点和平面的空间关系
      Direct3D 基础
一:
1, 初始化Direct3D
2,  Direct3d 可以被视作应用程序与图形设备(3d硬件)的交互中介
3, 一个中间环节 HAL(hardware abstraction layer)硬件抽象层,HAL是一个指示设备完成某些操作的设备的相关代码集。规范 specification
4, 软件定点运算???
二:
REF设备:Direct3D提供了参考光栅设备(reference rasterizer device),它能以软件的方式完全支持direct3d API。
注意:REF设备仅用于开发阶段,它与direct SDK捆绑(ship)在一起,无法发布给最终的用户,此外REF设备的速度十分的缓慢,在测试以外的其他场合都很不实用。
D3DDEVTYPE :HAL 设备用值D3DDEVTYPE_HAL来指定,
      1.2    COM(组建对象模型)
COM(Component Object Model)是一项能使Direct 独立于编程语言并具备向下兼容的技术,可将其视为一个C++类来使用
创建COM接口时不可使用C++关键字new ,用完后应该用 Release方法而不是delete,
注意:COM接口都有一个前缀I,
  1.3 预备知识
1.3.1 表面
表面主要是Direct3d 用于存储2D图像数据的一个像素矩阵。
线性数组(linear array)
跨度(pitch,stride的同义语)用字节表示,
       代码中用 接口 IDirect3DSurface9来描述表面。
      获取(retrieve)
     1.3.2 多重采样
用像素矩阵表示图像时往往出现块状(blocky-looking)效应,多重采样(multisampling)时一项用于平滑块状图像的技术。
全屏反走样(full-screen antialiasing)
多重采样会降低应用程序的运行速度。如果要使用多重采样技术 ,请务必使用IDirect3D9::CheckDeviceMultiSmpleType 方法来检查你的设备是否支持多重采样。
   1.3.3 像素格式
1.3.4 内存池(memory Pool)
  内存池可以用D3DPOOL 枚举类型来表示,、
显存(video memory)
1.3.5 交换链和页面置换
 表面集合(collection),交换链(Swap Chain),该集合用接口Idirect3DswapChain9 来表示,
置换技术(page Flipping),这两项技术主要用于生成更加平滑的动画。
前台缓存槽(front buffer slot),帧频(frame rate),后台缓存(back buffer)
1.3.6 深度缓存
深度缓存(depth buffer)是一个只含有特定像素的深度信息而不含图像数据的表面。
深度项(entry)。
Z-缓存 (z-buffering)。//前面的物体遮挡后面的物体。
深度缓存的格式决定了深度测试的精度。
1.3.7 定点运算
 定点运算(vertex processing) 分为两种,即:软件定点运算(software vertex process)或硬件定点运算(hardware vertex proceeding)。无论怎样 ,软件定点运算总是被支持,所以总是可以实现的。但我们应该始终优先考虑硬件定点运算的方式,因为速度更快,而且可以不占用cpu资源,也就意味着cpu可以被解放出来进行其他的运算。
  注意:图像卡支持硬件定点运算的另外一种等价的说法是该图形卡支持变换和光照的硬件计算。
1.3.8 设备性能
bool supporthardware ;
if(caps.DevCaps &D3DDEVCAPS_HWTRANSFORMNDLIGHT)
{
     Supporthardware=true;
}
Else
{
       Supporthardware=FALSE;
}
注:DevCaps 表示“设备性能 (Device Capabilities)”
                        1.4   Direct3D 的初始化
初始化的过程可以分为如下的步骤:
1:获取接口IDirect3d 的指针。获取物理硬件信息并创建接口IDirect3Ddevice9该接口为一个C++对象。
2:检查设备性能(D3DCAPS9),判断主显卡(primary display adapter)是否支持硬件定点运算。
3:初始化D3DPRESENT_PARAMETERS结构中的一个实例。
4:利用已经初始化的D3DPRESENT_PARAMETERS结构创建IDirect3Ddevice对象。
1.4.1 获取接口IDirect3D9的指针
  IDirect3D9 * _d3d9;
 _d3d9=Direct3DCreate9(D3D_SDK_VERSION);
 _d3d9对象的用途:设备枚举(device enumeration)以及创建IDirect3DDevice9类型的对象。
1.4.2 校验硬件顶点运算
  1.4.3填充D3DPRESENT_PARAMETER结构
1.4.4创建IDirect3DDevice接口
HRESULT IDirect3D9::createDevice();
          1.5 例程,Direct3D的初始化
InitD3D 函数对应用程序主窗口进行初始化,如果成功,则返回一个已经创建好的IDirect3DDevice接口指针。(这个函数我们可以指定窗口的尺寸,运行模式)。
   EnterMsgLoop 该函数封装了应用程序的消息循环。
     1.5.2  例程框架
。。。。bool Setup()例程所需进行的全部设置和初始化都在改函数中进行。如分配资源,检查设备性能,设置应用程序的状态。
。。。。。void Cleanup()该函数用于释放在setUP函数中分配的任何资源。
。。。。。bool Display(float timedelta).实现全部的绘制代码以及相邻帧之间应该执行的操作。
1.5.3 例程 D3D初始化
              第二章 绘制流水线
绘制流水线(rendering pipeline)
场景(scene)是物体和模型的集合。
任何物体都可以用三角形网格(triangle mesh)逼近表示。三角形网格是构建物体模型的基本单位。多边形(polygons),图元(primitives),网格几何元(mesh geometry),
定点格式:
  定点除了包含空间信息外,还包含其他的附加属性,如颜色属性,法线(normal)属性,
灵活定点格式(flexible vertex format  fvf),
2.1.2
三角形单元
三角形个定点的指定顺序非常重要,我们称为绕序(winding order),
2.1.3 索引
索引(indices),其原理,我们创建一个定点列表和一个索引列表,定点列表包含了全部独立定点,索引列表包含了指向定点列表的索引,这些三角形规定了为构建三角形单元,各定点应按何种方式来组织,
 定点列表可以这样来建:
Vertex  vertexlist【4】={v0,v1,v2,v3}
接下来,借助索引列表来定义顶点列表中顶点的组织方式以构成两个三角形单元。
WORD indexList【6】={0,1,2,0,2,3}
2.2 虚拟摄像机
可见的空间体积(volume of space)。视域体(frustum)
丢弃看不见的视域体的这类数据运算过程我们称为裁剪(clipping)。
投影窗口(projection window)是一个2D区域,
2.3 绘制流水线
一个简单的绘制流水线
局部坐标系-》世界坐标系-》观察坐标系-》背面消隐-》光照-》裁剪-》投影-》视口坐标系-》光栅化。
局部坐标系到世界坐标系的变换:
Device-》SetTransform(D3DTS_WORLD,&worldMatrix);
2.3.1 局部坐标系
  局部坐标系(local space)又叫建模坐标系(modeling space),是用于定义构成物体三角形单元列表的坐标系,
2.3.2世界坐标系
 世界坐标系又叫全局坐标系,一个位于局部坐标系的物体通过一个叫世界变换(world transform)的运算(过程)变换的世界坐标系(world space),该变换通常包括平移(translation),旋转(rotation)以及比例(scaling)运算,
  世界变换用一个矩阵来表示,并由Direct3D通过IDirect3DDevice9::SetTransform方法来加以应用,该方法的第一个参数表示要变换的类型,如 要进行世界变换则要设为:D3DTS_WOLRD,第二个参数表示采用的世界变换矩阵。
2.3.3 观察坐标系
在世界空间中,集合体和摄像机都是相对世界坐标系定义的,
取景变换(view space transformation),我们称变换后的集合体位于观察坐标系(view space)中,
取景变换矩阵(即观察矩阵)可由如下D3DX函数计算得到:
D3DXMATRIX *D3DXMaTrixLookAtlLH();
例如摄像机位于(5,3,-10),其观察点位世界坐标系的原点(0,0,0),我们就可以这样创建取景变换矩阵:
  D3DXVECTOR3 position(5.0f,3.0f,-10.0f);
  D3DXVECTOR3 targetPoint(0.0f,0.0f,0.0f);
  D3DXVECTOR3 worldUp(0.0f,1.0f,0.0f);
D3DXMATRIX   V;
  D3DXMatrixLookAtLH(&v,&targetPoint,&worldUp);
Device->SetTransform(D3DTS_VIEW,&v);
2.3.4背面消隐
每个多边形都有两个侧面(sides),我们把其中的一个侧面标记为正面(front side),另一个侧面标记为背面(back side),通常,多边形的背面是看不见的,因为场景中的多数物体都是封闭的(enclosed volume),背面消隐(backface culling)。
Direct3D认为顶点排列顺序为顺时针(观察坐标系中)的三角形单元是正面朝向的,顶点排列顺序为逆时针(观察坐标系)的三角形单元是背面朝向的。
如果因为某种原因,默认的消隐方式不能满足用户的要求,我们可以通过修改绘制状态(render state)D3DRS_CULLMODE来达到目的。
 Device->SetRenderState(D3DRS_CULLMODE,Value);
其中,value的值可以取:
D3DCULL_NONE 完全禁止背面消隐
D3DCULL_CW   只对顺时针绕序的三角形单元进行消隐
D3DCULL_CCW  默认值,只对逆时针绕序的三角形单元进行消隐
2.3.5 光照
光源是在世界坐标系中定义的,但必须经过取景变换到观察坐标系中才可以使用。
固定的流水线(fixed function pipeline)。
2.3.6裁剪
一个三角形单元与视域体的相对位置关系有以下三种:
。。完全在内部 
。。完全在外部 将被踢出
。。部分在内(外),
2.3.7 投影
观察坐标系中,我们的任务是获取3D场景的2D表示,从N维变换到N-1维的过程称为投影(projection),
我们只关心透视投影(perspective projection),它可以产生“透视缩短(foreshortening)”的视觉效果,即近大远小,
投影变换定义了视域体,并负责视域体中的几何体投影到投影窗口,投影矩阵比较复杂,我们将使用D3DX函数,其功能是依据视域体的描述信息创建一个投影矩阵。
D3DXMATRIX  *D3DMatriPerspectiveFovLH(D3DXMATRI &pout,
                                      FLOAT fovy,FLOAT Aspect,FLOAT zn,FLOAT zf);
横纵比(aspect ratio)参数,投影窗口中的几何体最终将变换到屏幕显示区,从方形的投影窗口到矩阵的显示屏的变换会导致拉伸畸形(stretching distortion),所谓纵横比就是显示屏纵横两维尺寸的比率,常用于矫正由方形到矩形的映射而引发的畸形。
纵横比(aspect ratio)=屏幕宽度(screen width)/屏幕高度(screen height)。
Zn 近裁剪面到坐标原点的距离
Zf 远裁剪面到原点的距离
2.3.8 视口变换
  视口变换(viewport transform)的任务就是将顶点坐标从投影窗口转换到屏幕的一个矩形区域中,该矩形区域成为视口(viewpoint)。
在Direct3D中,视口用结构D3DVIEWPORT9来表示。
Typedef strut D3DVIEWPORT9{
DWORD X,
DWORD Y,
DWORD width,
DWORD height,//前四个变量定义了矩形相对于父窗口的位置和大小
DWORD MINZ,//指定了深度缓存中的最小深度值。
DWORD MAXZ//深度缓存中最大深度值
}D3DVIEWPOER9;
 注意,MINZ MAXZ的范围设定在【0,1】,除非你想最求某中特效,否则其值都应该限制在这个范围。
实例:
D3DVIEWPORT9 vp={0,0,640,480,0,1};
Device->SetViewport(&vp);
2.3.9 光栅化
光栅化(rasterization)的任务就是为了绘制每个三角形单元,如何计算构成三角形单元的每个像素的颜色值。光栅化的计算量非常大,我们一般要借助专门的图形卡的加速功能,光栅化的最终结构就是显示在屏幕上的一幅2D图像。
         小结
在观察坐标系中,摄像机位于坐标原点,光轴方向与z轴正向一致,物体变换到观察坐标系后,就可以通过投影映射到投影窗口中,视口变换将投影窗口中的几何体在映射到视口中,最终在绘制流水线的光栅阶段计算出最终显示的2D图像的每个像素的颜色值。
                      第三章 Direct3D中的绘制
3.1 顶点缓存与索引缓存
   顶点缓存和索引缓存(vertex/index buffer)是两类相似的接口。
为什么不用数组呢?因为顶点缓存和索引缓存可以被放置在显存(video memory)中,进行绘制时,使用显存中的数据将获得比使用系统内存中的数据开得多的绘制速度。
在代码中 ,顶点缓存用接口IDirect3DVertexBuffer9 表示,索引缓存用接口IDirect3DIndexBuffer9表示。
3.1.1
创建顶点缓存和索引缓存
HRESULT IDirect3DDevice9::CreateVertexBuffer(
UINT Length,//为缓存分配的字节数 如果有8个定点,则为 8*sizeof(Vertex)
DWORD Usage,////缓存的一些附加属性
DWORD FVF,//存储在定点缓存中顶点的灵活顶点格式
D3DPOOL POOL,//容纳缓存的内存池
IDirect3DVretexBuffer9 **ppvertexBuffer,//用于接收所创建的顶点缓存的指针
HANDLE *Psharehandle);//不使用,该值设为0
HRESULT IDirect3DDevice9 ::CreateIndexBuffer(
UINT Length,
DWORD Usage,
D3DFORMAT Format,//指定索引的大小,设为D3DFMT_INDEX16表示16位索引,
IDirect3DIndexBuffer9 **ppIndexBuffer,//用于接收所创建的索引缓存指针
HANDLE psharedhandle);
注意:
创建缓存时,如果未使用D3DUSAGE_DYNAMIC,则所创建的缓存为静态缓存(static Buffer),我们用静态缓存来存储静态数据(那些不需要经常修改或访问的数据),例如,地图和城市建筑的数据,如果使用的动态缓存,动态缓存一般放置在AGP存储区中,其内容可以迅速的更新,动态缓存的一个最大的优点是更新的速度非常的快,它的一个很常见的例子就是粒子系统,
3.1.2
访问缓存内容
可以借助方法Lock来获取指向缓存内容的指针,但访问完之后,必须对缓存进行解锁(unlock),
HRESULT IDirect3DVertexBuffer9::Lock(
UINT offsetToLock,从哪里开始锁定
UINT SizeToLock,//要锁定的长度(字节数)
BYTE **ppbdata,//指向被锁定的存储区位置的指针
DWORD flags//锁定的方式,
};
3.1.3 获取顶点缓存和索引缓存的信息
D3DVERTEXBUFFER_DESC vbDescription;
vertexBuffer->GetDesc(&vbDescription);
               3.2 绘制状态
Direct3D封装了多种绘制状态(rendering state),这些绘制状态将影响几何体的绘制方式。
HRESULT IDirect3DDevice9::SetRenderState(
D3DRENDERSTATETYPE State,
DWORD Value);
3.3 绘制的准备工作
在绘制之前,我们还有三个步骤需要完成:
(1):指定数据流输入源。将顶点缓存和数据流进行连接。方法
HRESULT IDirect3DDevice9::SetStreamSource(
UINT,//标识与顶点缓存建立连接的数据流,我们总设为0
IDirect3DVertexBuffer9,//指向与给定数据流建立连接的顶点缓存的指针
UINT,//自数据流的起点的一个偏移量。单位为字节,
UIN);//将要连接到数据流的顶点缓存中每个元素的大小,单位为字节
例如:
_device->SetStreamSource(0,vb,0,sizeof(Vertex));
(2),这只顶点格式
_device->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);
(3),设置索引缓存
_device->SetIndices(_ib);
3.4 使用顶点缓存和索引缓存进行绘制
即使用DrawPrimitive 或DrawIndexedPrimitive方法将待绘制几何体的信息通过绘制流水线传输,这两个方法从顶点数据流中获取顶点信息,并从当前设定的索引缓存中提取索引信息。
3.5 D3DX几何体
 D3DX库提供了如下6个网格创建函数:
。D3DXCreateBox
D3DXCreateSphere
D3DXCreateCylinder
D3DXCreateTeapot
D3DXCreatePolygon
D3DXCreateTorus
上述六个方法都非常的相似,都使用D3DX网格数据结构ID3DXMesh和ID3DXBuffer接口,
   3.6 例程,三角形,立方体,茶壶,D3DXCreate*
  第四章  颜色
这一章我们学习如何为几何体添加颜色
4.1 颜色的表示
1.在Direct3D中,颜色用RGB三元组来表示,三种颜色的加性混合(additive mixing)决定了最终的颜色。
2.RGB数据可用两种不同的格式来保存,第一种是D3DCOLOR,它实际上与DWORD类型完全相同,共有32位,Direct3D提供了D3DCOLOR_ARGB宏帮助我们完成这项工作,如:
D3DCOLOR  brightRed=D3DCOLOR_ARGB(255,255,0,0);
D3DCOLOR_XRGB可以代替D3DCOLOR_ARGB;
在Direct3D中,存储颜色数据的另外一种结构是D3DCOLORVALUE,我们用单精度浮点数来度量每个颜色的亮度值,范围为0-1,
我们也可以用D3DXCOLOR替代D3DCOLORVALUE,且两种都有4个浮点类型的成员,这样我们就可以将其表达成一个4D向量,故其运算与向量完全一样,在D3DXCOLOR中颜色的乘法表示成各分量的值分别相乘。
4.2 顶点颜色
图元的颜色有构成该图元的顶点颜色决定。
Struct colorVertex{
Float x,y,z;
D3DCOLOR color;
Static const DWORD FVF;
}
Const DWORD ColorVertex::FVF=D3DFVF_XYZ|D3DFVF_DIFFUSE;
4.3着色(shading)
目前我们使用两种着色模式(shading mode),平面着色(flat shading)和Gouraud着色(gourand shading)。
如果使用平面着色模式,则每个图元的每个像素被一致的赋予该图元的第一个顶点所指定的颜色。平面着色容易使物体呈现块状,这是因为各颜色没有平滑的过渡,平滑着色(smooth shading),其中各图元的颜色由个顶点的颜色线性插值得到,
着色模式由Direct3D状态机(state maching)控制,
Device->SetRenderState(D3DRS_SHARDMODE,D3DSHADE_FLAT或者D3DSHADE_GOURAUD);
4.4 具有颜色的三角形
第五章 光照
光照(lighting)有助于描述实体形状和立体感。使用光照我们无需自行指定顶点的颜色值,Direct3D会将顶点送入光照计算引擎(light engine),依据光源类型,材质(material)以及物体表面相对于光源的朝向,计算出每个顶点的颜色值,基于某中光照模型计算出的个顶点的颜色,绘制结果更加的逼真。
5.1 光照的组成
在Direct3D的光照模型中,光源发出的光由以下三个分量或三种类型的光组成。
。环境光(Ambient light),反射
。漫射光(Diffuse light),这种类型光沿着特定的方向传播。当它到达某一表面时,将沿着各个方向均匀反射。漫射光方程(diffuse lighting equation).
.镜面光(specular light),这种类型的光沿着特定方向传播,光到达某一表面时,将严格的按照另一个方向反射。因为镜面光的计算量非常大,所以Direct3D为其提供了开关选项,一般都是关了的,如果要开启,必须:
Device->SetRenderState(D3DRS_SPECULARENALE,true);
每种类型的光都可以用结构D3DCOLORVALUE 或D3DXCOLOR来表示。这些类型描述了光线的颜色,
5.2 材质
材质允许我们定义物体表面对个颜色光的反射比例。材质结构用D3DMATERIAL9来表示。
Typedef struct D3DMATERIAL9{
D3DCOLORVALUE ;//材质对漫射光的反射率
D3DCOLORVALUE;//材质对环境光的反射率
D3DCOLORVALUE;镜面光的反射率
D3DCOLORVALUE;增强物体的亮度
Float ;镜面高光点的锐度(sharpness),该值越大,高光点的锐角越大
}D3DMATERIAL9,*LPD3DMATERIAL9;
具体使用例子见书
5.3 顶点法线  是一个描述多边形朝向的向量。
顶点法线(Vertex normal)正是基于上述思路而产生的,
光照计算是对每个顶点进行的,所以Direct3D需要知道表面再每个顶点处的局部朝向(法线方向),注意顶点法线和表面法线不一定相同,例如近似的求和园。
Struct Vertex{
Float x,y,z;
Float _nx,_ny,_nz;
Static const DWORD FVF;
};
Const DWORD Vertex::FVF=D3DFVF_XYZ|D3DFVF_NORMAL;
注意我们去掉了表示颜色的成员变量,这是因为我们将用光照计算顶点的颜色。
一种更好的计算顶点法向量的方法是计算法向量均值(normal averaging),
注意:在变换的过程中,顶点的法向量可能已经不再规范化,所以,要规范化
Device->SetRenderState(D3DRS_NORMALIZENORMALS,TRUE);
   5.4 光源
Direct3D支持三种光源
。点光源(point light),在世界坐标系中有固定的位置
。方向光(directional lights),该光源没有位置信息,
。聚光灯(spot lights),这种类型的光源与手电筒类似。有位置信息,光线呈锥形(conical shape)。有两个角度,
在程序代码中,光源用结构D3DLIGHT9来表示。
  5.5 例程 光照
为一个场景添加光照的步骤如下:
(1):启用光照
(2):为每个物体创建一种材质,并在绘制相应物体前启用(设置)该材质,
(3):创建一种或多种光源,设置并启用
(4):启用所用其余的光照状态,如镜面高光(specular highlightings)。
 第六章 纹理映射(texture mapping)
借此此技术 ,我们可以将图像数据映射到三角形单元中,增加立体感,真实感。
在Direct3D中,纹理用接口IDirect3DTexture9表示,纹理类似于一个表面的像素矩阵,
6.1 纹理坐标
纹理元:
为了处理不同尺度的纹理,Direct3D将纹理坐标做了规范化处理,使之限定在区间【0,1】中。
为了实现该映射,必须修改顶点坐标。
增加:float _u,_v;
6.2 创建并启用纹理
HRESULT D3DXCreateTextureFromFile();
创建纹理
IDirect3DTextrue9 *_stone;
D3DXCreateTextureFromFile(_device,”stone.bmp”,&_stone);
设置当前纹理
Device->SetTexture(0,_stone);
禁用某一层纹理
Device->SetTexture(0,0);
renderObjectWithoutTexture();
     6.3纹理过滤器
纹理过滤技术主要处理纹理三角形与屏幕三角形的大小不一样的问题。
Direct3D提供了3种类型的纹理过滤器(fileter)。纹理过滤方式可以用方法;
Device3DDevice->SetSamplerState来设置。
最近点采样(nearest point samping)。
线性纹理过滤(linear filtering)
各向异性纹理过滤(anisotropic filtering),但使用此纹理时,必须对D3DSAMP_MAXAISOTROPIC 水平值进行设定,改值越大,图像效果就越好。请调用IDirect3DDevice9::GetDeviceCaps函数检验返回D3DCAPS9结构参数。
Device->SetSamplerstate(0,D3DSAMP_MAXANISOTROPIC,4);
6.4 多级渐进纹理
多级渐进纹理链(Chain of mipmap),方法是,有某一纹理创建一系列分辨率逐渐减小的纹理图像,并且对每种分辨率下的纹理所采用的过滤方式进行定制,以保证保留那些较重要的细节。
6.4.1 多级渐进纹理过滤器
使用Device->SetSamplerState(0,D3DSAMP_MIPFILTER,filter);
Filter可以取不同的值,如:D3DTEXT_NONE,D3DTEXT_POINT,D3DTEXT_LINEAR.
6.4.2 使用多级渐进纹理
6.5  寻址模式
前面说过纹理坐标必须限制在【0,1】中,但这样是有问题的,Direct3D中定义了4中用来处理纹理坐标值超出【0,1】区间的纹理映射模式,它们分别是:
重复(wrap)寻址模式(address mode),边界颜色(border color )寻址模式,箝位(clamp)寻址模式,以及镜像(mirror)寻址模式。
                 6.6 例程 纹理四边形
现在来总结一下为场景添加纹理映射的步骤:
(1):构造组成物体的顶点,并为其指定纹理坐标
(2):用函数D3DXCreateTextureFromFile为IDirect3DTexture9接口加载一种纹理
(3):设置缩小过滤器,放大过滤器和多级渐进纹理过滤器
(4):绘制物体前,用函数IDirect3DDevice9::SetTexture来设定与该物体关联的纹理。
     第七章 融合技术
融合(blending)技术,可以得到透明效果
7.1  融合方程
融合:将当前计算得到的像素(源像素)颜色值与先前计算得到的像素(目标)颜色值进行合成的做法称为融合。
注意:融合的效果并不局限于普通的玻璃类型的透明效果,
在融合运算时,必须遵循以下的原则:
首先绘制的那些物体不需要进行融合的物体,然后将需要进行融合的物体按照相对于摄像机的深度值进行排序,如果物体已处于观察坐标系中,该运算的效率会相当高,因为此时只需对z分量进行排序,最后,按照自后往前的顺序逐个绘制将要融合运算的物体。
源融合因子,目标融合因子,Direct3D中,默认状态下是禁止融合运算的,可以开启:
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
注意:融合的计算量并不小,当你绘制完需要进行融合的几何体之后,应该禁止Alpha融合,在对三角形单元组进行融合的时候,最好进行批处理,之后应立即绘制出来,这样可以避免在每帧图像中都启用和禁止融合运算。
7.2 融合因子
可以通过绘制状态D3DRS_SRCBLEND,D3DRS_DESTBLEND的值来对源融合因子和目标融合因子分别进行设定。
例如:
Device->SetRenderSate(D3DRS_SRCBLEND,Source);
Device->SetRenderState(D3DRS_DESTBLEND,Destination);
  7.3 透明度
顶点颜色中的Alpha分量和材质。
Alpha分量主要用来指定像素的透明度(transparency)。
源融合因子和目标融合因子分别设置为D3DBLEND_SRCALPHA,D3DBLEND_INVSRCALPA.
7.3.1Alpha 通道
我们往往是从纹理的Alpha通道(channel)中获取Alpha信息。Alpha通道是保留给存储了Alpha分量的纹理元的一个额外的位集合(bits set)。
7.3.2 指定Alpha来源
如果当前的纹理拥有一个Alpha通道,Alpha值就取自该Alpha通道,如果没有Alpha通道,Alpha值就取自顶点的颜色。
      7.4 用DirectX Textrue Tool创建Alpha通道
DDS文件之专门的一种为DirectX应用程序的纹理设计的图像格式。可使用D3DXCreateTextrueFromFile函数将DDS文件加载到纹理中,
     7.5  例程 透明效果
融合处理的步骤总结如下:
(1):设置融合因子D3DRS_SRCBLEND ,D3DRS_DESTBLEND.
(2):如果使用Alpha分量,还需指定其来源
(3):启用Alpha融合绘制状态
               第八章  模板
模板缓存(stencil Buffer)。模板缓存是一个用于获得某种特效(special effect)的离屏(off-screen)缓存,模板缓存的分辨率(resolution)与后台缓存(back Buffer)和深度缓存(depth Buffer)的分辨率完全相同,所以模板缓存与后台缓存和深度缓存中的像素是一一对应的,它允许我们动态的,有针对性的决定是否将某个像素写入后台缓存中。
8.1 模板缓存的使用
1.询问硬件是否支持,再启用 Device->SetRenderState(D3DRS_STENCILENABLE,TRUE/FALSE);
Device->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,0Xff000000,1.0f,0);
D3DCLEAR_STENCIL表明我们要对模板缓存,目标缓存,深度缓存进行清空操作,第六个值为指定要将模板缓存清为何值。

8.1.1 模板缓存格式的查询
8.1.2 模板测试
我们可以使用模板缓存对后台缓存中的某些特定的区域进行绘制,判定是否将某个像素写入后台缓存的决策过程称为模板测试(stencil test),其表达式为:
(ref &mask)ComparisonOperation(value & mask)。
注:模板参考值(ref),模板掩码(mask)按位运算得到左操作数
    返回值为bool型。
8.1.3 模板测试的控制
1.模板参考值
模板参考值(stencil reference value)ref的默认值为0,但可这样将其改为1
Device->SetRenderState(D3DRS_STENCILREF,0X1);
注意:使用的为16进制数
2.模板掩码(mask)
模板掩码用于屏蔽或隐藏ref和value变量中的某些值,例如:
Device->SetRenderState(D3DRS_STENCILMASK,0X0000ffff);
模板值。
我们不能显式的单独设置模板的值,但是可以对模板缓存进行清空操作。
下面我们介绍与模板相关的绘制状态:
比较运算:
我们可以通过绘制状态D3DRS_STENCILFUNC来设置比较运算(comparison operation),该比较运算函数可取自如下枚举类型:
Typedef enum D3DCAMPFUNC{
}
8.1.4 模板缓存的更新:

我们可以基于以下3种可能的情形定义模板缓存中的值如何进行更新:
一:第i行,第j列的像素模板测试失败,我们可以借助绘制状态D3DRS_STENCILFAIL将模板缓存中处于同样位置的项更新为如下:
Device->SetRenderState(D3DRS_STENCILFAIL,StencilOperation);
二:第i行,第j列的像素深度测试失败,这样设置:
Device->SetRenderState(D3DRS_STENCILZFAIL,StencilOperation);
三:第i行,第j列的像素深度测试和模板测试均成功,我们这样设置:
Device->SetRenderState(D3DRS_STENCILPASS,StencilOperation);
StencilOperation的值可取以下的常量:
8.1.5 模板写掩码
写掩码(write mask),该值可以屏蔽我们将写入模板缓存的任何值的某些位:
可用绘制状态D3DRS_STENCILWRITEMASK来设定写掩码的值,默认为0xffffffff。
下例我们将对高16位进行屏蔽:
Device->SetRenderState(D3DRS_STENCILWRITEMASK,0X0000ffff);
8.2 例程  镜面效果
8.2.1 成像中的数学问题:

   D3DX库给我们提供了创建相对于任意平面的镜像变换矩阵:
D3DXMATRIX *D3DXMatrixReflect(
D3DXMATRIX *pout;
CONST D3DXPLANE *pPlane;
);
8.2.2 镜面效果实现概述:

 

抱歉!评论已关闭.