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个必须的 ...
随机推荐
- jquery学习笔记(4)--实现table隔行变色以及单选框选中
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...
- <bootstrap>bs2和3的区别</bootstrap>
实验室的list网站开始动工了,准备打算用bootstrap作布局. 大前天去本部停了长html5峰会大连站的讲演,着急往回赶,很多感兴趣的东西都没有听到,但是还是了解了一些html5的新特性 电脑端 ...
- linux内核设计与实现学习笔记-模块
模块 1.概念: 如果让LINUX Kernel单独运行在一个保护区域,那么LINUX Kernel就成为了“单内核”. LINUX Kernel是组件模式的,所谓组件模式是指:LINUX K ...
- poj 1564 Sum It Up
题目连接 http://poj.org/problem?id=1564 Sum It Up Description Given a specified total t and a list of n ...
- hdu 3342 Legal or Not
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3342 Legal or Not Description ACM-DIY is a large QQ g ...
- jQuery 获取 select 值和文本
jQuery("#select1").val();是取得选中的值, jQuery("#select1").text();就是取得的文本.
- 分享一下 aix安装python提示C编译器问题的办法
今天在AIX上面安装Python-2.7.2时失败,报下面的错误 checking for --enable-universalsdk... no checking for --with-univer ...
- Python实现kNN(k邻近算法)
Python实现kNN(k邻近算法) 运行环境 Pyhton3 numpy科学计算模块 计算过程 st=>start: 开始 op1=>operation: 读入数据 op2=>op ...
- FPGA控制HC595
/*****************************************************************************Copyright: 2013File na ...
- Html5最简单的游戏Demo——Canvas绘图的弹弹球
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...