| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- [ExecuteInEditMode]
- [RequireComponent(typeof(Camera))]
- public class MirrorCamera : MonoBehaviour
- {
- public Camera lookCamera;
- public Transform reflectionTransform;
- public Vector3 reflectionPosition;
- public Quaternion reflectionRotation;
- public Vector3 reflectionUp;
- public float clipPlaneOffset = 0.07f;
- private Camera m_Camera;
-
- private void Awake() {
- m_Camera = GetComponent<Camera>();
- }
- private void OnPreRender() {
- GL.invertCulling = true;
- if (reflectionTransform)
- {
- ResetCamera();
- }
- }
- private void OnPostRender() {
- GL.invertCulling = false;
- }
- public void ResetCamera() {
- if (!lookCamera) return;
- Vector3 pos, normal;
- Quaternion rotation;
- if (reflectionTransform)
- {
- pos = reflectionTransform.position;
- normal = reflectionTransform.up;
- rotation = reflectionTransform.rotation;
- }
- else
- {
- pos = reflectionPosition;
- normal = reflectionUp;
- rotation = reflectionRotation;
- }
- transform.position = pos;
- transform.rotation = rotation;
- float d = -Vector3.Dot (normal, pos) - clipPlaneOffset;
- Vector4 reflectionPlane = new Vector4 (normal.x, normal.y, normal.z, d);
- Matrix4x4 reflection = Matrix4x4.zero;
- reflection = CalculateReflectionMatrix (reflection, reflectionPlane);
- Vector3 oldpos = lookCamera.transform.position;
- Vector3 newpos = reflection.MultiplyPoint( oldpos );
- m_Camera.worldToCameraMatrix = lookCamera.worldToCameraMatrix * reflection;
- // Setup oblique projection matrix so that near plane is our reflection
- // plane. This way we clip everything below/above it for free.
- Vector4 clipPlane = CameraSpacePlane( m_Camera, pos, normal, 1.0f );
- //Matrix4x4 projection = cam.projectionMatrix;
- Matrix4x4 projection = lookCamera.CalculateObliqueMatrix(clipPlane);
- m_Camera.projectionMatrix = projection;
- m_Camera.transform.position = newpos;
- Vector3 euler = lookCamera.transform.eulerAngles;
- m_Camera.transform.eulerAngles = new Vector3(0, euler.y, euler.z);
- m_Camera.transform.position = oldpos;
- }
- Vector4 CameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
- {
- Vector3 offsetPos = pos + normal * clipPlaneOffset;
- Matrix4x4 m = cam.worldToCameraMatrix;
- Vector3 cpos = m.MultiplyPoint(offsetPos);
- Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;
- return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
- }
- static float Sgn(float a)
- {
- if (a > 0.0F)
- {
- return 1.0F;
- }
- if (a < 0.0F)
- {
- return -1.0F;
- }
- return 0.0F;
- }
- static Matrix4x4 CalculateReflectionMatrix(Matrix4x4 reflectionMat, Vector4 plane)
- {
- reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
- reflectionMat.m01 = ( - 2F * plane[0] * plane[1]);
- reflectionMat.m02 = ( - 2F * plane[0] * plane[2]);
- reflectionMat.m03 = ( - 2F * plane[3] * plane[0]);
-
- reflectionMat.m10 = ( - 2F * plane[1] * plane[0]);
- reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
- reflectionMat.m12 = ( - 2F * plane[1] * plane[2]);
- reflectionMat.m13 = ( - 2F * plane[3] * plane[1]);
- reflectionMat.m20 = ( - 2F * plane[2] * plane[0]);
- reflectionMat.m21 = ( - 2F * plane[2] * plane[1]);
- reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
- reflectionMat.m23 = ( - 2F * plane[3] * plane[2]);
-
- reflectionMat.m30 = 0F;
- reflectionMat.m31 = 0F;
- reflectionMat.m32 = 0F;
- reflectionMat.m33 = 1F;
- return reflectionMat;
- }
- }
|