在实践中,常常需要为类似荧幕,LED广告牌等平面制作反射。
但会遇到各种问题,例如在使用屏幕空间反射时,平面必须在画面内
平面反射捕获与光线追踪又代价高昂
因此,在一些情况下依然会使用一种历史悠久的反射手法
这种old school的做法,核心原理就是在地下放一个对称的面片(如下图所示)
其中,有关的Shader都在地下的面片中
- 地面上部的面片是普通的半透明,这是为了防止其参与SSR屏幕空间反射
- 地面和周围模型,都是正常的模型和材质
- 只有藏在地下,用于表现反射的面片是特殊的,接下来我们就制作它
制作
创建材质
我们拷贝一个地面上部面片的材质
M_Plane
为地面上面片材质M_Plane_R
为地面下的反射材质
他们现在内容相同,材质如下
放置对称模型
复制模型并对称
不用说,首先复制一个面片,然后将面片Z轴翻转
更换材质
然后为下部面片更换材质为M_Plane_R
>
接下来将两个面片的对称轴移动到地面水平位置,此时下部面片已经进入地下,看不到了
制作Shader
接下来我们就要开始制作反射Shader(M_Plane_R
)了
1.禁用深度测试
打开M_Plane_R
,第一步就是为其禁用深度测试
现在,透明被绘制出来了
2.制作自定义深度
现在我们要自己写一个深度
这里利用半透明的特性,SceneDepth-PixelDepth
求得面片到表面距离
然后对距离进行一个Remap
,让透明度根据距离进行线性衰减
最后使用Power
,Exp=2 (图里写错成0)让这个过渡以指数进行衰减
效果如下:
到此老派的做法已经完成了
我把反射面片附加到了上部模型,使其一起移动,效果如下
改进
我们并不在此结束,因为效果仍然有巨大改进空间
在延迟渲染引擎中,半透明本质是一种后期效果,因此它可以拿到Gbuffer
粗糙度
接下来我们尝试为其应用粗糙度
我们可以获取Gbuffer中的粗糙度,然后对贴图进行高斯模糊等处理
0成本模糊方案
考虑我们制作这个反射,本身就是为了节省成本
因此这里使用了一种0成本的模糊方案,这要求贴图有MIP
为TextureSample
选择MIP模式
演示不同值的影响
随着MIP的增大,贴图分辨率逐渐减小,也就会变得模糊,这张贴图有13个等级的MIP
我们利用这个特性进行0成本的模糊。
原理演示:
如图所示,这里我们使用了粗糙度作为蒙版输入MIP:
随着粗糙度增加,反射光线理应减少,表现为更多的地面颜色
因此翻转粗糙度,乘入透明度,以减少光线
法线
现在只可以在平面进行投影
但我们还可以拿到法线Gbuffer
那么我们待续…