Posts Tagged ‘RLR’

实时局部反射(Real-time Local Reflection with Bisection Method)

Friday, May 24th, 2013

很长一段时间没发博客了。前一段时间忙着考试。最近才终于又有时间集中开发了。

画了几周时间(确切的说是两周)学了一下DirectX11,感想是API还是比较简单易懂的。以前没有系统学过D3D,这次算是补上了。删掉固定管线以后微软只留下了必要的东西,本来就没有多少使用固定功能管线的经历,刚开始学3D的时候就是从shader开始学的,意外的快速理解了新的API。以前把DirectX10的代码升级到过10.1,能体会到即使是同一级别的API也有或多或少的功能追加。之前从NormalMap开始,从头做起,然后花了不少时间理解Tessellation,回头也发文好好讲讲使用心得。

废话扯完,下面介绍一下才做出来的局部反射,名字是Crytek起的,听起来挺糊涂,更喜欢屏幕空间反射SSR(Screen space reflection)这么叫,通俗易懂。

原理倒是非常简单,通俗点将就是从相机位置开始,与空间内每个点连线,向量和该点法线求个反射,沿线追踪,碰到深度小的就返回颜色信息。关键就看个人自己想怎么实现了。根本也没用到SM4.0以上的功能。

你要是Google搜索RLR出来的八成是gamedev上那小伙的声明,代码也发了。我先没看,自己写了下。结果回头看哪小伙的代码,都要哭出来了。我是标准的在worldspace上作的反射,这小伙在viewspace上,咱开始就很奇怪,难道就为了减少一次View变换?(后来发现其实也没减少),原来他是为了计算步长,希望逐像素进行采样,咱当时也困惑了好久,简单的声明确实能出结果,但是步长不准结果做不到平滑,消耗也很大。咋办?后来想起RefractionMap,是对Parallaxmap的一种改进,步长比较大不要紧。搜索出结果后继续进行进一步二分搜索。这样的话开销少了很多。前面那家伙就是死脑筋迭代了整个反射方向的像素,而且做法比较繁琐。要知道这个不是做镜子,比较极端的状况下,比如步长正好离开屏幕(可以手动纠正,而且往往这种情况下纠正了也没用,很大几率这些点没有反射到物体)。下图是直接通过物体Normal反射的结果(未使用NormalMap),这种情况也只有在实验中会使用到,实际应用中一定是NormalMap结束的反射。

该图是使用NormalMap后的结果进行的局部反射。

暂时今天就完成到这里,在第一张图中很明显反射边缘有锯齿,毕竟是屏幕空间,超出范围就反射不到了。接下来只要把边缘淡出就可以了。但是下图中看来实际使用中由于环境比较复杂,即使不处理也不会有很大的违和感,甚至是减小渲染尺寸也不会有问题。实验室的GTX680台式和家里的GTX670笔记本都还是能达到比较理想的帧数。

更新:进行了fadeout的添加,修正了一些提前跳出计算的失误。现在更精确了。第一幅图更新了一下,挂了FRAPS,下面一张图本身就看不出区别。不过添加法线反射以后明显帧数低了些。