相机镜面反射
除了常见的反射探针,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连一下就行了。
屏幕UV要取对称,用菲涅尔简单模拟一下全反射,采样一下法线稍微做一下偏移。
相机镜面反射
https://www.kuanmi.top/2023/07/30/MirrorCamera/