在使用D3D开发游戏的过程中,很多情况下都会用到depth buffer来完成特定的效果,比如DOF,Shadows,SSAO等等。在这些情况下我们就可能需要预览depth buffer来确定它是正确的,以免导致后续运算渲染出错。此时有一个问题就出现了,因为原始的depth buffer中保存的depth不是线性的。我们知道,世界坐标系下的顶点在经过视图变换后会被转换到视图空间,此时摄像机在原点,并且我们为摄像机定义了一个近平面和一个远平面:

在经过视图变换后,接着执行的就是投影变换,D3D的透视投影变换矩阵如下,其中,zn就是为摄像机定义的近平面,而zf 就是远平面:

这里,我们因为在讨论depth,所以我们只关心z的变换。z在经过透视投影矩阵的洗礼后,得到的是:

(公式中的z是顶点坐标变换到视图坐标系后的z)

此时的g(z)还不是真正保存到depth buffer中的值,还需要经过perspective divide,也就是我们常说的投影变换后需要进行的步骤:(x, y, z) / w。

最后,我们得到的才是真正保存到depth buffer中的值,他看起来是这样的:

   公式1

根据这个公式,我们来看下图,图中我绘制了两条曲线图,其中一条我们定义近平面zn的值为1,远平面zf 的值为100。而另一条我们定义近平面zn的值为10,远平面zf 的值为100:

此时我们就可以发现,随着z的变化,g(z)并不是线性变化的,靠近近平面的很少一部分z值在变换后却占据了绝大部分的g(z)范围,而很大一部分z值在变换后却需要去争抢剩余的很小一部分g(z)范围(题外话:这也就是导致depth buffer精度问题的原因,以及为什么我们常说把近平面和远平面设置的更加靠近可以减少depth buffer的精度问题)。所以当我们在预览depth buffer时,看到的很大情况下都是白茫茫一片,因为绝大部分z值在变换后都位于g(z)的那一小部分范围内(也就是接近1.0的范围)。

那么我们该如何正确的预览depth buffer呢,没错,就是把depth转换回线性的!

那么该如何转换回线性depth值呢,因为顶点从世界坐标系变换到视图坐标系后,此时的z值仍是线性的,所以我们要做的就是将depth值倒推回它在视图空间的z值。根据公式1,我们来计算视图空间的z值:

现在,我们就得到了视图空间的z值,这个值是线性的。但是,我们还不能用这个值来预览depth,我们还必须把它归一化到区间[0, 1],然后才可以存到render target中用于预览。那么如何把视图空间的z值归一化到[0, 1]呢?因为在视图空间中,摄像机位于原点,并且顶点在可见时它的z值会落在区间[zn, zf],所以我们要做的就是把区间[zn, zf]转换到[0, 1],也就是执行操作:(z - zn) / (zf - zn):

好了,至此,我们已经得到了线性的depth,并且它的值是位于区间[0, 1]的。最后,我们只需要把这个值写入render target进行预览就可以了。

下面展示我写的一个预览depth buffer的Demo,部分核心shader代码如下:

//--------------------------------------------------------------------------------------
// Constant buffers
//-------------------------------------------------------------------------------------
cbuffer ViewDepthPerFramePS : register( b0 )
{
float2 f2ClipPlane; // f2ClipPlane.x stores the near plane and f2ClipPlane.y stores the far plane
} //--------------------------------------------------------------------------------------
// Textures and sampler states
//--------------------------------------------------------------------------------------
Texture2D DebugTexture : register( t0 );
SamplerState PointSampler : register( s0 ); float4 DebugOutputViewDepthPS( VS_OUTPUT pInput ) : SV_TARGET
{
float nonLinearizeDepth = DebugTexture.Sample( PointSampler, pInput.texCoords );
float linearizeDepth = (f2ClipPlane.x * nonLinearizeDepth) / (f2ClipPlane.y - nonLinearizeDepth*(f2ClipPlane.y - f2ClipPlane.x)); return float4( linearizeDepth, linearizeDepth, linearizeDepth, 1.0f );
}

最终效果如图:

D3D depth buffer的预览的更多相关文章

  1. WebRTC 源码分析(二):安卓预览

    有过一定相机开发经验的朋友可能会疑惑,预览还有什么好分析的,不是直接 camera.setPreviewDisplay 或者 camera.setPreviewTexture 就能在 SurfaceV ...

  2. JSP实现word文档的上传,在线预览,下载

    前两天帮同学实现在线预览word文档中的内容,而且需要提供可以下载的链接!在网上找了好久,都没有什么可行的方法,只得用最笨的方法来实现了.希望得到各位大神的指教.下面我就具体谈谈自己的实现过程,总结一 ...

  3. Java实现office文档与pdf文档的在线预览功能

    最近项目有个需求要java实现office文档与pdf文档的在线预览功能,刚刚接到的时候就觉得有点难,以自己的水平难以在三四天做完.压力略大.后面查找百度资料.以及在同事与网友的帮助下,四天多把它做完 ...

  4. .net 实现Office文件预览 Word PPT Excel 2015-01-23 08:47 63人阅读 评论(0) 收藏

    先打个广告: .Net交流群:252713569 本人QQ :524808775 欢迎技术探讨, 近期公司要求上传的PPT和Word都需要可以在线预览.. 小弟我是从来没有接触过这一块的东西 感觉很棘 ...

  5. FlexPaper+SWFTool+操作类=在线预览PDF

    引言 由于客户有在线预览PDF格式的需求,在网上找了一下解决方案,觉得FlexPaper用起来还是挺方便的,flexpaper是将pdf转换为swf格式的文件预览的,所以flexpaper一般和swf ...

  6. fileupload图片预览功能

    FileUpload上传图片前首先预览一下 看看效果: 在专案中,创建aspx页面,拉上FileUpload控件一个Image,将用来预览上传时的图片. <%@ Page Language=&q ...

  7. ReportViewer 不预览,直接导出 PDF文件

    作为笔记记着,以免以后再到处找资料 1. 在不预览的情况下导出文件 先看一个方法说明,想知道ReportViewer支持导出哪些文件类型,在Render方法说明中就有描述 // // Summary: ...

  8. Java+FlexPaper+swfTools仿百度文库文档在线预览系统设计与实现

    笔者最近在给客户开发文档管理系统时,客户要求上传到管理系统的文档(包括ppt,word,excel,txt)只能预览不允许下载.笔者想到了百度文库和豆丁网,百度文库和豆丁网的在线预览都是利用flash ...

  9. springmvc 文件下传、上载、预览。以二进制形式存放到数据库(转载)

    springmvc 文件上传.下载.预览.以二进制形式存放到数据库.数据库中的关于传入附件的字段我写了2个:一个存放内容accessory,一个存放文件的后缀filetype 上传:首先需要2个必须的 ...

随机推荐

  1. WPF 多项选择下拉菜单

    背景 项目中有一个多项选择筛选的功能, 由于筛选条件太多, 用户又习惯在平板上进行操作, 所以要求我们把checkbox 放到一个combobox里面, 然后checkbox的选项要在combobox ...

  2. [转载]--用Python 自动安装软件

    脚本使用了  Python 2.3 + Com 对象,所以你的系统必须安装Python2.3或更高版本同时必须安装  Mark Hammond's Win32all 模块 (特别感谢Mark Hamm ...

  3. 菜鸟学习Spring——60s利用JoinPoint获取参数的值和方法名称

    一.概述 AOP的实现方法在上两篇博客中已经用了两种方法来实现现在的问题来了虽然我们利用AOP,那么客户端如何信息传递?利用JoinPoint接口来实现客户端给具体实现类的传递参数. 二.代码演示. ...

  4. 实习感悟——SQL语句

    在这次实习中用到了很多SQL语句,下面就给大家分享分享: 1.group by 字面意思我们一看就知道groupby通过分组的意思,通过数据库某个字段的分组我们可以做什么?联系到生活中,我们给一组对象 ...

  5. Python常用内建模块

    Python常用内建模块 datetime 处理日期和时间的标准库. 注意到datetime是模块,datetime模块还包含一个datetime类,通过from datetime import da ...

  6. 6.24 AppCan移动开发者大会:议程重大更新,报名即将关闭

    大会倒计时2天,议程重大更新,报名通道即将关闭! 创业6年,由AppCan主办的第一届移动开发者大会将在本周五盛大召开.超过100万开发者线上参与.现场1500人规模.50家移动互联企业深度参与.30 ...

  7. hdu 1496 Equations

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1496 Equations Description Consider equations having ...

  8. C#.Net 图片处理大全

    C# How to: Image filtering by directly manipulating Pixel ARGB values C# How to: Image filtering imp ...

  9. 利用js排序html表格

    在web前端开发中会遇到排序等功能,当然也可以用服务器端来排序,今天我做一个笔记,怎么用js来实现这些复杂的功能呢. 在学习这个之前一定得用html dom jquery 的知识,要不没有办法看明白的 ...

  10. Xcode7免证书真机调试实践

    1.Open Xcode7, click menu "Xcode-Preferences-accounts" to add your AppleId; 2.According to ...