Archive for July, 2013

Volume Fog – Ray Tracing Shadows

Saturday, July 27th, 2013

这玩意并不新鲜。很早在Nvidia的demo里面看到过。当初并没有当回事。后来ENIX的引擎演示里面又见到了。再到后来Crytek前段时间的演讲里面也提到这玩意。再后来Killzone:Shadow Fall的资料里面也看到了,看样子不装备不行了。

咱一直认为说到底还是Volume Light,只不过这个是正版的,原来那个所谓屏幕空间容积光只不过是个hack。然后Crytek非要起个新名字叫Fog?!当然项目里面我还是写作Volume Light了。

具体实现可以参考一下Nvidia的文档。里面其实只要看一个开始的本质的理论描述就够了。直接看代码简直就是自寻死路。

简而言之就是做一个fullscreen trace,一步一步向前走,每一步对比一下跟shadowmap的关系。

这回还是费了一番功夫的。

最初是这幅样子。使用了一个很小的尺寸,步长直接给了1000,结果跑到死,效率低:(

这个算法的问题在于,步长如何计算,场景这么大,逐像素trace明显不现实。试了很多方法,又看了原文档,原文档里面通过求depth的最大最小值来确定追踪范围(现在觉得这方法可行,找个时间看看能不能改到CS里面做)。我这里仅仅是做了个“看起来比较舒服”的步长计算。在不要求距离的情况下甚至可以做Full-size的追踪。

理想中的全尺寸。

考虑到逐像素追踪完全不需要采样周围的数据,那么ok,把深度改成宽度,空间换时间,这是分割成两块进行计算的情况:

当采样深度比较大,超过500左右这个效率比直接计算要快,killzone里面提到的分块计算不知道是不是这个意思。

尽管如此还是离实用性差了很远,吃掉了很多时间,缩小分辨率又死的很难看。

总之现在暂时是借用了Nvidia里面的源码进行反锯齿。

最后结果就是这样。远远没有高分辨率好看,但是在现在的技术条件下只能如此。

接下来的优化:

1.back trace追踪

2.max/min depth

3.最理想的方法!:将volume直接渲染到屏幕上,cw/ccw两遍直接求出max/min depth,直接计算volume内部像素。

最后的疑问:

为什么killzone里面说所有的光源都支持volume?

Tile-Based Deferred Rendering

Saturday, July 13th, 2013

Tile-Based Deferred Rendering(TBDR)从SIGGRAPH 2010发表开始逐渐为业界所了解。简要的说就是将屏幕空间划分成为格子状,利用compute shader将格子和光源照射区域进行碰撞检测,仅对碰撞成功的格子进行光照计算,而不用每次都做FullScreenQuad。

以前只知道deferred lighting(light pre-pass),光照都是通过一个一个sphere渲染的。感觉效率其实已经非常不错了。但是实验数据表明TBDR在大量光源存在的情况下明显优于light pre-pass。

顺带一提,由于Tile-Based的思想非常好,有人利用Tile-Based技术又提出了Forward+,也就是将TBDR中计算碰撞的结果直接输出,将这个碰撞列表拿来进行通常的Forward计算。在这里就能利用通常Forward的优势,比如复杂材质,半透明等等。

GPGPU给业界带来了另一个无限创造的可能性。谁利用的充分,谁就占优势。

最后给出截图,顺便代码参考了Intel的例子和某11区的牛人的例子。

黑色块是debug用的光源位置,顺便在cs里面也输出了。