unity-shader-屏幕空间反射ssr
顾名思义, 是基于屏幕 rt 的. 使用 RayMarching ( unity-shader-光线步进RayMarching.md ) 与 SignedDistanceField ( unity-shader-SignedDistanceField(SDF).md ) 技术进行 碰撞检测.
这个 shader 并不适用于 移动平台, 只能跑在 游戏主机 及 桌面pc 上, 因为使用了 延迟渲染 gbuffer 中的 法线图.
前篇
- unity学习笔记之屏幕空间反射(1) - https://zhuanlan.zhihu.com/p/61402704
- UnityShader——屏幕空间反射(一) - https://blog.csdn.net/NotMz/article/details/80513711
- Screen Space Reflection 学习笔记 - https://blog.csdn.net/hehemingsgc6/article/details/53888902
- 相关 git 仓库
Raymarch
Raymarch 叫光线步进,是光线追踪在光栅化中运行的一个形式,当光线沿着他的方向向前走一个单位距离,检查一下是否碰到物体。有则停下,返回颜色或者深度结果。没有则继续向前,直到走到最大步数并终止。
下图是raymarch示意图
第四个步进的时候才碰撞到物体
效果
原理
前置条件
使用 Deferred Shading, 因为要使用到 法线图 及 高光图中.a 通道, 另外在使用到 深度图
流程
参考: https://github.com/bodhid/UnityScreenSpaceReflections 的流程分析
笔记仓库中的 SSR-Simple
总的流程分两步, 异步是正常的 延迟渲染, 然后通过 后处理, 计算出 反射 部分的 RT, 然后根据 光滑度 及 反射因子 进行 lerp 插值得到最终的像素
后处理计算出 反射 部分的 RT
利用 深度图, 计算出像素点的世界坐标位置.
利用深度图 构建 ndc 坐标 (注意 z 值应该做平台区分, dx (0
1) 和 opengl(-11) 不一样), 再用 vp矩阵的 逆矩阵 (有 csharp 中计算好传入 shader) 算出 世界坐标1
(xyzMatrix = mul(_CAMERA_XYZMATRIX, float4(uv_depth*2.0 - 1.0, SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv_depth), 1.0))) / xyzMatrix.w;
使用 gbuff 中的 法线图, 算出 反射 方向
1
2
3
4// 从 gbuffer 的 法线图 获取 世界空间下的 法线值, 并转到 [-1, 1] 区间下
float3 worldNormal = tex2D(_CameraGBufferTexture2, i.uv).rgb * 2.0 - 1.0;
// dir 是 观察方向的 反射方向, 且有 步进
dir = reflect(viewDir, worldNormal) * sampleDistance;//sample dis进行 RayMarching 碰撞算法, 如图所示
将 反射 部分的 RT 进行 高斯模糊 一下, 效果会好点
1
2
3
4
5
6
7//blur SSR result
for (int i = 0; i < blurAmount; ++i) {
blurMaterial.SetVector("_Direction", new Vector4(1, 0, 0, 0));
Graphics.Blit(tempA, tempB, blurMaterial);
blurMaterial.SetVector("_Direction", new Vector4(0, 1, 0, 0));
Graphics.Blit(tempB, tempA, blurMaterial);
}然后根据 光滑度 及 反射因子 进行 lerp 插值得到最终的像素
1
2
3
4
5
6
7
8float4 ssr = tex2D(_SSR,i.uv); // _SSR 反射 部分的 RT
// 取出 gbuffer 的 光滑度
float smoothness = tex2D(_CameraGBufferTexture1,i.uv).a;
float4 col = tex2D(_MainTex, i.uv); // _MainTex 正常渲染的 后处理 原图
// ssr.a 是 碰撞的 步进次数相关, 步进越大表示应该反射的效果越差
return col * lerp(1, ssr, smoothness * ssr.a);
unity 内置 Post-processing 中的 ssr
官网文档: Screen Space Reflection - https://docs.unity3d.com/Manual/PostProcessing-ScreenSpaceReflection.html
for Projects running on current-gen consoles and desktop computers. It’s not suitable for mobile development. Because it relies on the Normals G-Buffer, it is only available in the deferred rendering path.
可以跑在 游戏主机 及 桌面pc, 不适用于 移动平台. 因为使用了 延迟渲染 gbuffer 中的 法线图.