Advertisement
Guest User

PlanarReflection.cs

a guest
Aug 19th, 2020
3,688
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.14 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. namespace UnityStandardAssets.Water
  6. {
  7.     [ExecuteInEditMode]
  8.     // [RequireComponent(typeof(WaterBase))]
  9.     public class PlanarReflection : MonoBehaviour
  10.     {
  11.         public LayerMask reflectionMask;
  12.         public bool reflectSkybox = false;
  13.         public Color clearColor = Color.grey;
  14.         public String reflectionSampler = "_ReflectionTex";
  15.         public float clipPlaneOffset = 0.07F;
  16.  
  17.         public float quality = 0.5f;
  18.         Vector3 m_Oldpos;
  19.         Camera m_ReflectionCamera;
  20.         [SerializeField]
  21.         Material m_SharedMaterial;
  22.         Dictionary<Camera, bool> m_HelperCameras;
  23.  
  24.         public void OnWillRenderObject()
  25.         {
  26.          
  27.             WaterTileBeingRendered(transform, Camera.current);
  28.  
  29.         }
  30.  
  31.         public void Start()
  32.         {
  33.             // m_SharedMaterial = ((WaterBase)gameObject.GetComponent(typeof(WaterBase))).sharedMaterial;
  34.         }
  35.  
  36.  
  37.         Camera CreateReflectionCameraFor(Camera cam)
  38.         {
  39.             String reflName = gameObject.name + "Reflection" + cam.name;
  40.             GameObject go = GameObject.Find(reflName);
  41.  
  42.             if (!go)
  43.             {
  44.                 go = new GameObject(reflName, typeof(Camera));
  45.             }
  46.             if (!go.GetComponent(typeof(Camera)))
  47.             {
  48.                 go.AddComponent(typeof(Camera));
  49.             }
  50.             Camera reflectCamera = go.GetComponent<Camera>();
  51.  
  52.             reflectCamera.backgroundColor = clearColor;
  53.             reflectCamera.clearFlags = reflectSkybox ? CameraClearFlags.Skybox : CameraClearFlags.SolidColor;
  54.  
  55.             SetStandardCameraParameter(reflectCamera, reflectionMask);
  56.  
  57.             if (!reflectCamera.targetTexture)
  58.             {
  59.                 reflectCamera.targetTexture = CreateTextureFor(cam);
  60.             }
  61.  
  62.             return reflectCamera;
  63.         }
  64.  
  65.  
  66.         void SetStandardCameraParameter(Camera cam, LayerMask mask)
  67.         {
  68.             cam.cullingMask = mask;
  69.             cam.backgroundColor = Color.black;
  70.             cam.enabled = false;
  71.         }
  72.  
  73.  
  74.         RenderTexture CreateTextureFor(Camera cam)
  75.         {
  76.             RenderTexture rt = new RenderTexture(Mathf.FloorToInt(cam.pixelWidth * quality),
  77.                 Mathf.FloorToInt(cam.pixelHeight * quality), 24);
  78.             rt.hideFlags = HideFlags.DontSave;
  79.             return rt;
  80.         }
  81.  
  82.  
  83.         public void RenderHelpCameras(Camera currentCam)
  84.         {
  85.             if (null == m_HelperCameras)
  86.             {
  87.                 m_HelperCameras = new Dictionary<Camera, bool>();
  88.             }
  89.  
  90.             if (!m_HelperCameras.ContainsKey(currentCam))
  91.             {
  92.                 m_HelperCameras.Add(currentCam, false);
  93.             }
  94.             if (m_HelperCameras[currentCam])
  95.             {
  96.                 return;
  97.             }
  98.  
  99.             if (!m_ReflectionCamera)
  100.             {
  101.                 m_ReflectionCamera = CreateReflectionCameraFor(currentCam);
  102.             }
  103.  
  104.             RenderReflectionFor(currentCam, m_ReflectionCamera);
  105.  
  106.             m_HelperCameras[currentCam] = true;
  107.         }
  108.  
  109.  
  110.         public void LateUpdate()
  111.         {
  112.             if (null != m_HelperCameras)
  113.             {
  114.                 m_HelperCameras.Clear();
  115.             }
  116.         }
  117.  
  118.  
  119.         public void WaterTileBeingRendered(Transform tr, Camera currentCam)
  120.         {
  121.             RenderHelpCameras(currentCam);
  122.  
  123.             if (m_ReflectionCamera && m_SharedMaterial)
  124.             {
  125.                 m_SharedMaterial.SetTexture(reflectionSampler, m_ReflectionCamera.targetTexture);
  126.             }
  127.         }
  128.  
  129.  
  130.      
  131.  
  132.  
  133.         void RenderReflectionFor(Camera cam, Camera reflectCamera)
  134.         {
  135.             if (!reflectCamera)
  136.             {
  137.                 return;
  138.             }
  139.  
  140.             if (m_SharedMaterial && !m_SharedMaterial.HasProperty(reflectionSampler))
  141.             {
  142.                 return;
  143.             }
  144.  
  145.             reflectCamera.cullingMask = reflectionMask & ~(1 << LayerMask.NameToLayer("Water"));
  146.  
  147.             SaneCameraSettings(reflectCamera);
  148.  
  149.             reflectCamera.backgroundColor = clearColor;
  150.             reflectCamera.clearFlags = reflectSkybox ? CameraClearFlags.Skybox : CameraClearFlags.SolidColor;
  151.             if (reflectSkybox)
  152.             {
  153.                 if (cam.gameObject.GetComponent(typeof(Skybox)))
  154.                 {
  155.                     Skybox sb = (Skybox)reflectCamera.gameObject.GetComponent(typeof(Skybox));
  156.                     if (!sb)
  157.                     {
  158.                         sb = (Skybox)reflectCamera.gameObject.AddComponent(typeof(Skybox));
  159.                     }
  160.                     sb.material = ((Skybox)cam.GetComponent(typeof(Skybox))).material;
  161.                 }
  162.             }
  163.  
  164.             GL.invertCulling = true;
  165.  
  166.             Transform reflectiveSurface = transform; //waterHeight;
  167.  
  168.             Vector3 eulerA = cam.transform.eulerAngles;
  169.  
  170.             reflectCamera.transform.eulerAngles = new Vector3(-eulerA.x, eulerA.y, eulerA.z);
  171.             reflectCamera.transform.position = cam.transform.position;
  172.            
  173.             Vector3 pos = reflectiveSurface.transform.position ;
  174.          
  175.  
  176.  
  177.             pos.y = reflectiveSurface.position.y;
  178.             Vector3 normal = reflectiveSurface.transform.up;
  179.             float d = -Vector3.Dot(normal, pos) - clipPlaneOffset;
  180.             Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
  181.  
  182.             Matrix4x4 reflection = Matrix4x4.zero;
  183.             reflection = CalculateReflectionMatrix(reflection, reflectionPlane);
  184.             m_Oldpos = cam.transform.position;
  185.             Vector3 newpos = reflection.MultiplyPoint(m_Oldpos);
  186.  
  187.             reflectCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
  188.  
  189.             Vector4 clipPlane = CameraSpacePlane(reflectCamera, pos, normal, 1.0f);
  190.  
  191.             Matrix4x4 projection = cam.projectionMatrix;
  192.             projection = CalculateObliqueMatrix(projection, clipPlane);
  193.             reflectCamera.projectionMatrix = projection;
  194.  
  195.             reflectCamera.transform.position = newpos;
  196.             Vector3 euler = cam.transform.eulerAngles;
  197.             reflectCamera.transform.eulerAngles = new Vector3(-euler.x, euler.y, euler.z);
  198.  
  199.             reflectCamera.Render();
  200.  
  201.             GL.invertCulling = false;
  202.         }
  203.  
  204.  
  205.         void SaneCameraSettings(Camera helperCam)
  206.         {
  207.             helperCam.depthTextureMode = DepthTextureMode.None;
  208.             helperCam.backgroundColor = Color.clear;
  209.             helperCam.clearFlags = CameraClearFlags.SolidColor;
  210.             helperCam.renderingPath = RenderingPath.Forward;
  211.         }
  212.  
  213.  
  214.         static Matrix4x4 CalculateObliqueMatrix(Matrix4x4 projection, Vector4 clipPlane)
  215.         {
  216.             Vector4 q = projection.inverse * new Vector4(
  217.                 Sgn(clipPlane.x),
  218.                 Sgn(clipPlane.y),
  219.                 1.0F,
  220.                 1.0F
  221.                 );
  222.             Vector4 c = clipPlane * (2.0F / (Vector4.Dot(clipPlane, q)));
  223.             // third row = clip plane - fourth row
  224.             projection[2] = c.x - projection[3];
  225.             projection[6] = c.y - projection[7];
  226.             projection[10] = c.z - projection[11];
  227.             projection[14] = c.w - projection[15];
  228.  
  229.             return projection;
  230.         }
  231.  
  232.  
  233.         static Matrix4x4 CalculateReflectionMatrix(Matrix4x4 reflectionMat, Vector4 plane)
  234.         {
  235.             reflectionMat.m00 = (1.0F - 2.0F * plane[0] * plane[0]);
  236.             reflectionMat.m01 = (-2.0F * plane[0] * plane[1]);
  237.             reflectionMat.m02 = (-2.0F * plane[0] * plane[2]);
  238.             reflectionMat.m03 = (-2.0F * plane[3] * plane[0]);
  239.  
  240.             reflectionMat.m10 = (-2.0F * plane[1] * plane[0]);
  241.             reflectionMat.m11 = (1.0F - 2.0F * plane[1] * plane[1]);
  242.             reflectionMat.m12 = (-2.0F * plane[1] * plane[2]);
  243.             reflectionMat.m13 = (-2.0F * plane[3] * plane[1]);
  244.  
  245.             reflectionMat.m20 = (-2.0F * plane[2] * plane[0]);
  246.             reflectionMat.m21 = (-2.0F * plane[2] * plane[1]);
  247.             reflectionMat.m22 = (1.0F - 2.0F * plane[2] * plane[2]);
  248.             reflectionMat.m23 = (-2.0F * plane[3] * plane[2]);
  249.  
  250.             reflectionMat.m30 = 0.0F;
  251.             reflectionMat.m31 = 0.0F;
  252.             reflectionMat.m32 = 0.0F;
  253.             reflectionMat.m33 = 1.0F;
  254.  
  255.             return reflectionMat;
  256.         }
  257.  
  258.  
  259.         static float Sgn(float a)
  260.         {
  261.             if (a > 0.0F)
  262.             {
  263.                 return 1.0F;
  264.             }
  265.             if (a < 0.0F)
  266.             {
  267.                 return -1.0F;
  268.             }
  269.             return 0.0F;
  270.         }
  271.  
  272.  
  273.         Vector4 CameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
  274.         {
  275.  
  276.        
  277.             Vector3 offsetPos = pos + normal * clipPlaneOffset;
  278.  
  279.             Matrix4x4 m = cam.worldToCameraMatrix;
  280.             Vector3 cpos = m.MultiplyPoint(offsetPos);
  281.             Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;
  282.  
  283.             return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
  284.         }
  285.     }
  286. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement