D3D depth buffer的预览
在使用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的预览的更多相关文章
- WebRTC 源码分析(二):安卓预览
有过一定相机开发经验的朋友可能会疑惑,预览还有什么好分析的,不是直接 camera.setPreviewDisplay 或者 camera.setPreviewTexture 就能在 SurfaceV ...
- JSP实现word文档的上传,在线预览,下载
前两天帮同学实现在线预览word文档中的内容,而且需要提供可以下载的链接!在网上找了好久,都没有什么可行的方法,只得用最笨的方法来实现了.希望得到各位大神的指教.下面我就具体谈谈自己的实现过程,总结一 ...
- Java实现office文档与pdf文档的在线预览功能
最近项目有个需求要java实现office文档与pdf文档的在线预览功能,刚刚接到的时候就觉得有点难,以自己的水平难以在三四天做完.压力略大.后面查找百度资料.以及在同事与网友的帮助下,四天多把它做完 ...
- .net 实现Office文件预览 Word PPT Excel 2015-01-23 08:47 63人阅读 评论(0) 收藏
先打个广告: .Net交流群:252713569 本人QQ :524808775 欢迎技术探讨, 近期公司要求上传的PPT和Word都需要可以在线预览.. 小弟我是从来没有接触过这一块的东西 感觉很棘 ...
- FlexPaper+SWFTool+操作类=在线预览PDF
引言 由于客户有在线预览PDF格式的需求,在网上找了一下解决方案,觉得FlexPaper用起来还是挺方便的,flexpaper是将pdf转换为swf格式的文件预览的,所以flexpaper一般和swf ...
- fileupload图片预览功能
FileUpload上传图片前首先预览一下 看看效果: 在专案中,创建aspx页面,拉上FileUpload控件一个Image,将用来预览上传时的图片. <%@ Page Language=&q ...
- ReportViewer 不预览,直接导出 PDF文件
作为笔记记着,以免以后再到处找资料 1. 在不预览的情况下导出文件 先看一个方法说明,想知道ReportViewer支持导出哪些文件类型,在Render方法说明中就有描述 // // Summary: ...
- Java+FlexPaper+swfTools仿百度文库文档在线预览系统设计与实现
笔者最近在给客户开发文档管理系统时,客户要求上传到管理系统的文档(包括ppt,word,excel,txt)只能预览不允许下载.笔者想到了百度文库和豆丁网,百度文库和豆丁网的在线预览都是利用flash ...
- springmvc 文件下传、上载、预览。以二进制形式存放到数据库(转载)
springmvc 文件上传.下载.预览.以二进制形式存放到数据库.数据库中的关于传入附件的字段我写了2个:一个存放内容accessory,一个存放文件的后缀filetype 上传:首先需要2个必须的 ...
随机推荐
- 7.css盒模型
所谓的盒模型,其实就是把元素当成盒子,元素里的文本就是盒子里的东西. 而根据元素的特效,其盒模型的特效也不同,下面是一些总结: 1.块级元素(区块) 所谓块级元素,就是能够设置元素尺寸.有隔离其他元素 ...
- 4.html5中超链接
html中超链接都是通过<a>标签实现的,html5也不例外,这里就来探讨一下<a>标签. <a>元素属于文本元素,有一些私有属性或者叫局部属性.那么,相对应的还有 ...
- ping通IP,telnet 3306不通
一个同事装的MySQL数据库,无法连接.1.查看权限2.查看防火墙检查用户权限,防火墙都没问题,就是无法连接,能ping通,但是telnet 3306 端口无法成功.检查了下数据库配置 ...
- oracle11g rman验证备份有效性
RMAN> restore validate controlfile; Starting restore at 21-NOV-13using target database control fi ...
- ASP.NET基础笔记
MSDN: ...
- 九度oj 1523 从上往下打印二叉树
原题链接:http://ac.jobdu.com/problem.php?pid=1523 建树,再层次遍历bfs.为了找根方便些,加了father指针... 如下: #include<algo ...
- func_num_args(),func_get_arg(),func_get_args()
<?php function testFunction1(){ return func_num_args(); } function testFunction2(){ return func_g ...
- [转]webrtc学习: 部署stun和turn服务器
[转]webrtc学习: 部署stun和turn服务器 http://www.cnblogs.com/lingdhox/p/4209659.html webrtc的P2P穿透部分是由libjingle ...
- Windows Server 2003服务器.net4.0+IIS6.0的服务器,IE11浏览器访问的不兼容性
工作中发生了一件诡异的事情: 程序在Win7+.NET4.0+IIS7.5的服务器部署,IE8和IE11请求时,响应的样式都正常. 但是在美的同事反映说,Windows Server 2003服务器. ...
- Android实现入门界面布局
Android实现入门界面布局 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 代码实现 首先是常量的定义,安卓中固定字符串应该定义在常量中. stri ...