声明:本文完全翻译自DX SDK Documentation

depth buffer,通常被称为z-buffer或者w-buffer,是设备的一个属性,用来存储深度信息,被D3D使用。当D3D渲染一个场景到target surface的时候,它会使用depth-buffer surface上的数据,来决定被rasterized三角面片的pixel间的遮挡关系。

当depth buffer被开启,rendering surface上的每一个点都会被检测。depth buffer上的值可以是点的z坐标值,也可以是在投影空间中齐次坐标的w值。用z坐标的叫z-buffer,用w坐标值的角z-buffer。它们各有优缺点。

在深度测试开始的时候,depth buffer上的深度值被设置为场景中的最大值。rendering surface上的颜色值被设置为背景色或者背景纹理颜色。场景中的每一个三角面片都会被检测它是否跟当前的(x,y)坐标相交,如果相交,z或者w值会被检测是否比depth buffer中对应的值小,如果小,它就会被写入到depth buffer中,三角面片的颜色值会被写入到当前点的rendering surface上。

我们可以通过改变渲染状态D3DRS_ZFUNC的值,来改变D3D的比较方法,以影响depth buffer的值和render-target surface。

市面上的几乎所有减速器都支持z-buffering,使z-buffer是如今最常见的depth buffer类型。然而,无所不在的z-buffer有它的缺点。产生的z值往往不是平均分布在z-buffer 范围内(典型的是,0.0~1.0,包括0跟1)。特别的是,far跟near clipping plane非常影响z值的分布。在支持最普遍的16位depth buffer中,很容易引起远处应该被隐藏的物体显示在rendering surface上。

w-buffering就不存在这个问题,它的值会均匀分布。尤其,far跟near clipping planes的比率不再会影响w值的分布,使程序可以支持非常大的比值。当然,z-buffering不是完美的,它会引起近处本该隐藏的物体显现。另一个缺点是,w-buffering需要硬件支持,并没有z-buffering支持的那么普遍。

在渲染的时候,z-buffering是有overhead的。

Querying for Depth Buffer Support(D3D9)

如同任何特性,程序使用的驱动可能并不支持所有类型的depth buffering。总是要检查驱动的能力,尽管大部分驱动支持z-based buffering,但是并不一定支持w-based buffering。如果你尝试打开一个不支持的特性,驱动并不会崩溃。驱动可能fall back到一个它支持的depth buffering。

在创建设备之前,你可以使用D3D对象检查一下所支持的depth buffering。如果D3D对象告诉说,它支持depth buffering,那么它创建的任何设备都会支持的。

// The following example assumes that pCaps is a valid pointer to an
// initialized D3DCAPS9 structure
if(FAILED(m_pD3D->CheckDeviceFormat(pCaps->AdapterOrdinal,
                                                                        pCaps->DeviceType,
                                                                        AdapterFormat,
                                                                        D3DUSAGE_DEPTHSTENCIL,
                                                                        D3DRTYPE_SURFACE,
                                                                        D3DFMT_D16)))
        return E_FAIL;

同样,我们可以检测depth-stencil的支持情况。

// Reject devices that cannot create a render target of RTFormat while
// the back buffer is of RTFormat and the depth-stencil buffer is
// at least 8 bits of stencil
if(FAILED(m_pD3D->CheckDepthStencilMatch(pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, RTFormat, D3DFMT_D24S8)))
     return E_FAIL;

Create a Depth Buffer

depth buffer是设备的一个属性。要创建一个被D3D管理的depth buffer,对D3DPRESENT_PARAMETERS结构体进行恰当设置。

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

通过设置EnableAutoDepthStencil = TRUE,我们命令D3D管理程序的depth buffer。AutoDepthStencilFormat = D3DFMT_D16 必须是一个有效并支持的depth buffer 格式。D3DFMT_D16是一个16位的depth buffer。

if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dDevice ) ) ) return E_FAIL;

如上代码会创建一个,创建depth buffer的设备。

depth buffer会自动被设为设备的render target。当设备重设后,depth buffer会被自动释放并重新创建,以新的大小。

要创建一个新的depth buffer surface,使用IDirect3DDevice9::CreateDepthStencilSurface。
要将新的depth buffer设置到设备上,用IDirect3DDevice9::SetDepthStencilSurface。
要使用depth buffer在我们程序中,我们需要打开 depth buffer。

Enabling Depth Buffering

在创建好depth buffer后,如果要打开depth buffer,我们可以调用IDirect3DDevice9::SetRenderState方法。设置render state的D3DRS_ZENABLE。
D3DZB_FALSE
Disable depth buffering.
D3DZB_TRUE
Enable z-buffering.
D3DZB_USEW
Enable w-buffering.
 
Retrieving a Depth Buffer

获取一个指向depth buffer surface的指针。
LPDIRECT3DSURFACE9 pZBuffer;

m_d3dDevice->GetDepthStencilSurface( &pZBuffer );

Clearing Depth Buffer

许多C++程序在渲染新的frame前都会清理depth buffer。我们可以显式地清理depth buffer通过调用IDirect3DDevice9::Clear,指明D3DCLEAR_ZBUFFER标签,同时,我们可以指定一个任意深度值。

Changing Depth Buffer Write Access

默认情况下,D3D是允许写depth buffer。不过,我们可以disable这个写的权限,来获得某些特效。

通过调用IDirect3DDevice9::SetRenderState,用参数D3DRS_ZWRITEENABLE,值为0。

Changing Depth Buffer Comparison Functions

默认情况下,在rendering surface上进行深度测试时,如果相应的深度值(z/w)小于depth buffer上的,D3D系统就会更新render-target上相应的点。我们可以更改深度值的比较方法。

通过调用IDirect3DDevice9::SetRenderState,用参数D3DRS_ZFUNC,值为D3DCMPFUNC枚举类型中一个。

[Zz] DX depth buffer的更多相关文章

  1. D3D depth buffer的预览

    在使用D3D开发游戏的过程中,很多情况下都会用到depth buffer来完成特定的效果,比如DOF,Shadows,SSAO等等.在这些情况下我们就可能需要预览depth buffer来确定它是正确 ...

  2. 从depth buffer中构建view-space position

    观察透视投影矩阵: 对于x和y,矩阵变换只是一个缩放系数,那么逆变换就是缩放系数的倒数,所以 设Xndc Yndc为NDC空间中的XY坐标,Xview Yview Zview为view space中的 ...

  3. 测试不同格式下depth buffer的精度

    这篇文章主要是参考MJP的“Attack of The Depth Buffer”,测试不同格式下depth buffer的精度. 测试的depth buffer包含两类: 一是非线性的depth b ...

  4. Cesium 中由 Logarithmic Depth Buffer 引起的模型显示不完整的问题

    当 Cesium 单个模型过长时,会遇到某些视角模型显示不完整的问题,如下图所示: 经过在官方论坛上询问,该问题由 viewer.scene.logarithmicDepthBuffer 开启造成,关 ...

  5. Depth Buffer

    Up until now there is only one type of output buffer you've made use of, the color buffer. This chap ...

  6. Vulkan SDK 之 Depth Buffer

    深度缓冲是可选的,比如渲染一个3D的立方体的时候,就需要用到深度缓冲.Swapchain就算有多个images,此时深度缓冲区也只需要一个.vkCreateSwapchainKHR 会创建所有需要的i ...

  7. depth/stencil buffer的作用 ----------理解模板缓存 opengl

    在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所示,framebuffer中一个像素,有相对应的depth buffer和stencil buf ...

  8. 【D3D12学习手记】4.3.8 Create the Depth/Stencil Buffer and View

    我们现在需要创建深度/模板缓冲区. 如§4.1.5所述,深度缓冲区只是一个2D纹理,用于存储最近的可见对象的深度信息(如果使用模板(stencil),则也会存储模板信息). 纹理是一种GPU资源,因此 ...

  9. Directx11教程(48) depth/stencil buffer的作用

    原文:Directx11教程(48) depth/stencil buffer的作用      在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所 ...

随机推荐

  1. .Net查看项目文件弹出未找到与约束

    项目能打开,但是当要在项目中查看文件时弹出未找到与约束contractname Microsoft.VisualStudio.Utilities.IContentTypeRegistryService ...

  2. linux 创建连接命令 ln -s 软链接

    这是linux中一个非常重要命令,请大家一定要熟悉.它的功能是为某一个文件在另外一个位置建立一个同不的链接,这个命令最常用的参数是-s, 具体用法是:ln -s 源文件 目标文件. 当 我们需要在不同 ...

  3. Quartus 软件的使用之PLL的使用

    练习使用Altera FPGA 内的 PLL IP核: 思路:将clk_50M倍频到clk_100M,然后观察100M时钟. 1.生成PLL的核例化文件,然后调用. 点击NEXT之后,等一会会跳出如下 ...

  4. 搭建邮局(邮件服务器) - hmailserver

    1.查看服务器mx是否解析成功 nslookup  set type=mx   2.hmailserver服务器 smtp设置     3.foxmail 设置   4.使用webmail(after ...

  5. linux tricks 之 BUILD_BUG_ON_ZERO.

    ------------------------------------------- 本文系作者原创, 欢迎大家转载! 转载请注明出处:netwalker.blog.chinaunix.net -- ...

  6. Android虚拟机中的sqlite数据库文件

    Android虚拟机中的sqlite数据库文件 ①

  7. &1的用法

    看到不少大神都喜欢用&1来判断一些东西,但是作为渣渣的我总是不理解这个&1到底是有什么作用. 今天写了程序看了一下,其实是判断奇偶用的. 如果是奇数,其结果为1,偶数结果为false. ...

  8. vim跳到文件头和文末结尾

    gg           : 跳转到文件头 Shift+g   : 跳转到文件末尾

  9. subList和asList

    subList subList返回仅仅只是一个视图.直接上源码 public List<E> subList(int fromIndex, int toIndex) { subListRa ...

  10. Hadoop_10_12虚拟机01_虚拟机NAT方式联网【自己的亲测笔记】

      NAT方式 1.查看网络信息--ifconfig(同windows中的ipconfig相同) 主要关注的是第三行内容,分别是Ip地址.广播地址.子网掩码 2.安装完系统后需要配置三个地方--IP地 ...