相机镜面反射

除了常见的反射探针,SSR,之前变换相机矩阵,还有一种最简单的方式就是直接添加一个镜面相机。

相机镜面反射

脚本

脚本方面主要是使镜面相机和主相机镜像同步,包含FOV等等。

    void MirrorCam()
    {
        Camera camera = originalCamera;

#if UNITY_EDITOR
        var focusedWindow = EditorWindow.focusedWindow;
        if (focusedWindow == null)
            return;

        var type = focusedWindow.GetType().Name;
        switch (type)
        {
            case "SceneView":
            case "GameView":
                currentView = type;
                break;
        }

        if (Application.isPlaying == false && currentView == "SceneView")
        {
            var sceneView = SceneView.lastActiveSceneView;
            camera = sceneView.camera;
        }
#endif

        if (camera != null)
        {
            mirrorCamera.fieldOfView = camera.fieldOfView;
            mirrorCamera.aspect = camera.aspect;
            MirrorTransformForPlane(mirrorCamera.transform, camera.transform, plane);
        }
    }

    public static Quaternion mirrorRot(Transform plane, Quaternion cam)
    {
        var forward = plane.forward;
        var reflect = Vector3.Reflect(cam * Vector3.forward, forward);
        var reflectup = Vector3.Reflect(cam * Vector3.up, forward);

        return Quaternion.LookRotation(reflect, reflectup);
    }

    public static Vector3 mirrorPos(Transform plane, Vector3 oldPos)
    {
        var forward = plane.forward;
        var planPos = plane.position;
        var dis = planPos - oldPos;
        var cros = Vector3.Cross(dis, forward).normalized;
        var ccos = Vector3.Cross(cros, forward);
        var refDis = Vector3.Reflect(dis, ccos);
        return refDis + planPos;
    }

    private static void MirrorTransformForPlane(Transform mirrorTransform, Transform originTransform, Transform plane)
    {
        var originPosition = originTransform.position;
        var originRotation = originTransform.rotation;

        var mirrorPosition = mirrorPos(plane, originPosition);
        var mirrorRotation = mirrorRot(plane, originRotation);

        mirrorTransform.position = mirrorPosition;
        mirrorTransform.rotation = mirrorRotation;
    }

这里就设置一下镜面相机的位置和旋转。
编辑器中要特殊对待,取场景的相机。

    private void LateUpdate()
    {
        MirrorCam();
    }

#if UNITY_EDITOR
    void OnRenderObject()
    {
        MirrorCam();
    }
#endif

运行时在LateUpdate中设置,编辑器中就用OnRenderObject吧。

Shader Graph

这里的Shader很简单,用SG连一下就行了。

镜面SG

屏幕UV要取对称,用菲涅尔简单模拟一下全反射,采样一下法线稍微做一下偏移。


相机镜面反射
https://www.kuanmi.top/2023/07/30/MirrorCamera/
作者
KuanMi
发布于
2023年7月31日
许可协议