深度缓冲区
深度缓冲区是Direct3D用来存储绘制到屏幕上每一个像素点的深度信息的—块内存缓冲区。
它为每个像素存储一个深度值(z值),这个深度值是从摄像机到对应该像素点的顶点之间的距离。
深度缓冲区的大小和颜色缓冲区(Frame Buffer)的大小一致。
例如:
如果要绘制一个640×480分辨率的图片,则在深度缓冲区中就将存储640×480个深度信息。
深度缓冲区的格式决定着深度测试的精确性,一个24位的深度缓冲区比16位的深度缓冲区更为精确。
通常应用程序在24位的深度缓冲区下就能得到比较精确的结果。Direct3D最高可以支持32位的深度缓冲区。
并不是所有的硬件都能支持32位的深度缓冲区。在确定深度缓冲区的格式之前,需要检查硬件支持的深度缓冲区格式。
深度缓冲区格式 | 描述 |
D3DFMT_D32 | 32位的深度缓冲区 |
D3DFMT_D15S1 | 15位的深度缓冲区和1位的模版缓冲区 |
D3DFMT_D24S8 | 32位的深度缓冲区,24位存储深度值,8位存储模板值 |
D3DFMT_D24X8 | 32位的深度缓冲区,24位存储深度值,8位保留位 |
D3DFMT_D24X4S4 | 32位的深度缓冲区,24位存储深度值,4位存储模板值,4位保留位 |
D3DFMT_D16 | 16位的深度缓冲区 |
检查硬件支持的缓冲区格式
并不是所有的硬件都能支持32位的深度缓冲区。在确定深度缓冲区的格式之前,需要检查硬件支持的深度缓冲区格式。
D3DDISPLAYMODE d3ddm;
if(FAILED(m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddm)))//通过引擎指针获得显卡的显示模式的结构体都d3ddm并通过检测它的格式支持几位
return false;
//选择深度缓冲区格式
if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,d3ddm.Format, D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE, D3DFMT_D32) == D3D_OK)
//选择32位深度缓冲区
{
d3dpp.AutoDepthStencilFormat = D3DFMT_D32;
d3dpp.EnableAutoDepthStencil = TRUE;
}
else if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8) == D3D_OK)
{//选择24位深度缓冲区
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
d3dpp.EnableAutoDepthStencil = TRUE;
}
else if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16) == D3D_OK)
{//选择16位深度缓冲区
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.EnableAutoDepthStencil = TRUE;
}
Else{
d3dpp.EnableAutoDepthStencil = FALSE;
}
深度测试
Direct3D通过比较当前绘制的像素点的深度和对应深度缓冲区的点的深度值来决定是否绘制当前像素。如果深度测试为TRUE,则绘制当前像素,并用当前像素点深度值更新深度缓冲区,反之则不予绘制。
深度缓冲能确定哪个对象在前,哪一个对象在后,从而正确的渲染对象。
深度测试的算法有很多种,并不是只能设置深度值小的点通过深度测试,Direct3D中可以由程序员选择需要的深度测试算法。调用IDirect3DDevice9::SetRenderState()函数设置深度测试函数,将第一个参数设为D3DRS_ZFUNC,第二个参数设为想要设置的深度测试算法,它属于D3DCMPFUNC枚举类型。
typedef enum _D3DCMPFUNC {
D3DCMP_NEVER = 1, //深度测试函数总是返回FALSE
D3DCMP_LESS = 2, //测试点深度值小于深度缓冲的值时返回TRUE
D3DCMP_EQUAL = 3, //测试点深度值等于深度缓冲的值时返回TRUE
D3DCMP_LESSEQUAL = 4, //测试点深度值小于等于深度缓冲的值时返回TRUE
D3DCMP_GREATER = 5, //测试点深度值大于深度缓冲的值时返回TRUE
D3DCMP_NOTEQUAL = 6, //测试点深度值不等于深度缓冲的值时返回TRUE
D3DCMP_GREATEREQUAL = 7, //测试点深度值大于等于深度缓冲的值时返回TRUE
D3DCMP_ALWAYS = 8, //深度测试函数总是返回TRUE
D3DCMP_FORCE_DWORD = 0x7fffffff
} D3DCMPFUNC;
通常情况下,深度测试算法总是设置为D3DCMP_LESS,表示当测试点深度值小于深度缓冲中的相应值时返回TRUE,即距离摄像机更近的点通过深度测试并绘制相应的像素点
// g_pDevice为有效的Direct3D设备
g_pDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESS );
深度缓冲的使用
为了正确地绘制场景中的物体需要使用深度缓冲。一般按照一下步骤就可以实现:
1)创建深度缓冲区
若要在Direct3D图形程序中应用深度测试,首先必须在创建Direct3D渲染设备时创建深度缓冲区,并设置深度缓冲区的格式。
// 表示由Direct3D创建并管理一个深度缓冲区
d3dpp.EnableAutoDepthStencil = true;
//深度缓冲区的每一个像素由16位的整数值表示
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
//在d3dpp是设备参数结构体的实例 ,可用检查硬件支持的缓冲区格式代替
2)激活深度测试
Direct3D渲染设备创建好后,调用Direct3D中渲染状态设置的函数,SetRenderState()来激活深度测试。
// g_pd3dDevice为有效的D3D设备
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
3)设置深度测试函数
调用IDirect3DDevice9::SetRenderState()设置深度测试函数,将第一个参数设为D3DRS_ZFUNC,第二个参数设为想要设置的深度测试算法。
// g_pd3dDevice为有效的Direct3D设备
g_pd3dDevice ->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESS );
4)设置深度缓冲区更新
设置了深度测试函数后,还需要设置深度测试成功时对深度缓冲区如何操作,是保持原来的深度值,还是用当前像素的深度值更新对应的数值。
调用函数SetRenderState()设置深度缓冲区的更新,将第一个参数设为D3DRS_ZWRITEENABLE,第二个参数设为TRUE,表示允许应用程序在绘制像素时更新深度缓冲区。
// 设置深度缓冲区更新
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
5)清空深度缓冲区
因为场景内的物体是可以动得,另外摄像机也可以随便移动,所以物体的深度值是在不停的更新的。所以在绘制图形之前,把深度缓冲区全部清空一次,以便于重新更新图形的深度。
g_pd3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0xffffffff,1.0f,0.0f)