unity-shader-屏幕空间反射ssr

顾名思义, 是基于屏幕 rt 的. 使用 RayMarching ( unity-shader-光线步进RayMarching.md ) 与 SignedDistanceField ( unity-shader-SignedDistanceField(SDF).md ) 技术进行 碰撞检测.
这个 shader 并不适用于 移动平台, 只能跑在 游戏主机 及 桌面pc 上, 因为使用了 延迟渲染 gbuffer 中的 法线图.


前篇

Raymarch

Raymarch 叫光线步进,是光线追踪在光栅化中运行的一个形式,当光线沿着他的方向向前走一个单位距离,检查一下是否碰到物体。有则停下,返回颜色或者深度结果。没有则继续向前,直到走到最大步数并终止。

下图是raymarch示意图

第四个步进的时候才碰撞到物体


效果


原理

前置条件

使用 Deferred Shading, 因为要使用到 法线图 及 高光图中.a 通道, 另外在使用到 深度图

流程

参考: https://github.com/bodhid/UnityScreenSpaceReflections 的流程分析

笔记仓库中的 SSR-Simple

总的流程分两步, 异步是正常的 延迟渲染, 然后通过 后处理, 计算出 反射 部分的 RT, 然后根据 光滑度 及 反射因子 进行 lerp 插值得到最终的像素

  1. 后处理计算出 反射 部分的 RT

    1. 利用 深度图, 计算出像素点的世界坐标位置.

      利用深度图 构建 ndc 坐标 (注意 z 值应该做平台区分, dx (01) 和 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;
    2. 使用 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
    3. 进行 RayMarching 碰撞算法, 如图所示

  2. 将 反射 部分的 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);
    }
  3. 然后根据 光滑度 及 反射因子 进行 lerp 插值得到最终的像素

    1
    2
    3
    4
    5
    6
    7
    8
    float4 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 中的 法线图.