unity学习笔记之屏幕空间反射(1)
本来打算在opengl里面实现的,但是gl配置起来比较麻烦。所以就先在unity里面实现。在以后有空的时候再到opengl里头重新写一个。【算法原理】
屏幕空间反射需要在相机中发射出n条光线,然后根据物体的法向量和摄像机的射线方向计算出这条光线的反射方向。再对他进行raymarch计算。
那么问题来了,什么是raymarch?
Raymarch叫光线步进,是光线追踪在光栅化中运行的一个形式,当光线沿着他的方向向前走一个单位距离,检查一下是否碰到物体。有则停下,返回颜色或者深度结果。没有则继续向前,直到走到最大步数并终止。
下图是raymarch示意图:
1,从摄像机方向发出射线,碰到物体。
光线方向和法线计算出反射光线的方向,走第一步,没有碰到物体。
第二步依然没有
N步之后碰到了,并返回结果
具体的实现开下面的代码
【ray tracing前的准备】
首先,将unity摄像机改为延迟着色的管线。
http://pic2.zhim.com/v2-f399ce869a56d7e38fa33cbcdaeb1c11_b.jpg并新建一个后期脚本,挂在摄像机上。屏幕空间的算法本质上就是后期计算,有点像nuke吧。
Graphics.blit可以把当前帧缓冲渲染出来最终结果发送到shader当中去。因此,在shader中为 _mainTex。Ps:_mainTex输出的结果是lighting之后的结果
顺带再传个worldtoCamera矩阵进去,在unity shader编写的时候死活找不到这个矩阵。
在shader中使用一下参数获得gbuffer的信息。
这里有我们要用到的深度
_CameraGBufferTexture1 为specular
_CameraGBufferTexture2为world normal
在顶点着色阶段,我们在这里算出ray的起点
在片段着色器中算出反射光线的起点,方向:
并带入到追踪的function中
在进行raymarch时有个问题,在求交小物体的时候精度不高,会出现下图问题
如果为了求交这样的小物体把每次步进的距离减小,并增加步进的次数,虽然可以解决,但是每个物体的大小都不一样,并不是哪个场景都适用的。而且,更多的步进次数意味着更多的消耗,因此,binary search呼之欲出。
在物体求交之后,使用原来步进距离的二分之一再次求交一边,很好的解决了这个问题。
下图为binary search代码:
得到的结果去采样lighting之后的结果
最终效果:
目前只是简单的实现了屏幕空间反射的效果。在后面的文章中,会加入jitter,将3Draymarch升级为2d raymarch ,hiz优化等
技术参考链接:
页:
[1]