MirrorReflection.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. using System;
  2. using System.Collections;
  3. using UnityEngine;
  4. public class MirrorReflection : MonoBehaviour
  5. {
  6. public void OnWillRenderObject()
  7. {
  8. if (!base.enabled || !base.GetComponent<Renderer>() || !base.GetComponent<Renderer>().sharedMaterial || !base.GetComponent<Renderer>().enabled)
  9. {
  10. return;
  11. }
  12. Camera current = Camera.current;
  13. if (!current)
  14. {
  15. return;
  16. }
  17. if (MirrorReflection.s_InsideRendering)
  18. {
  19. return;
  20. }
  21. MirrorReflection.s_InsideRendering = true;
  22. Camera camera;
  23. this.CreateMirrorObjects(current, out camera);
  24. Vector3 position = base.transform.position;
  25. Vector3 up = base.transform.up;
  26. int pixelLightCount = QualitySettings.pixelLightCount;
  27. if (this.m_DisablePixelLights)
  28. {
  29. QualitySettings.pixelLightCount = 0;
  30. }
  31. this.UpdateCameraModes(current, camera);
  32. float w = -Vector3.Dot(up, position) - this.m_ClipPlaneOffset;
  33. Vector4 plane = new Vector4(up.x, up.y, up.z, w);
  34. Matrix4x4 zero = Matrix4x4.zero;
  35. MirrorReflection.CalculateReflectionMatrix(ref zero, plane);
  36. Vector3 position2 = current.transform.position;
  37. Vector3 position3 = zero.MultiplyPoint(position2);
  38. camera.worldToCameraMatrix = current.worldToCameraMatrix * zero;
  39. Vector4 clipPlane = this.CameraSpacePlane(camera, position, up, 1f);
  40. Matrix4x4 projectionMatrix = current.projectionMatrix;
  41. MirrorReflection.CalculateObliqueMatrix(ref projectionMatrix, clipPlane);
  42. camera.projectionMatrix = projectionMatrix;
  43. camera.cullingMask = (-17 & this.m_ReflectLayers.value);
  44. camera.targetTexture = this.m_ReflectionTexture;
  45. GL.SetRevertBackfacing(true);
  46. camera.transform.position = position3;
  47. Vector3 eulerAngles = current.transform.eulerAngles;
  48. camera.transform.eulerAngles = new Vector3(0f, eulerAngles.y, eulerAngles.z);
  49. camera.Render();
  50. camera.transform.position = position2;
  51. GL.SetRevertBackfacing(false);
  52. Material[] sharedMaterials = base.GetComponent<Renderer>().sharedMaterials;
  53. foreach (Material material in sharedMaterials)
  54. {
  55. if (material.HasProperty("_ReflectionTex"))
  56. {
  57. material.SetTexture("_ReflectionTex", this.m_ReflectionTexture);
  58. }
  59. }
  60. Matrix4x4 lhs = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, new Vector3(0.5f, 0.5f, 0.5f));
  61. Vector3 lossyScale = base.transform.lossyScale;
  62. Matrix4x4 matrix4x = base.transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1f / lossyScale.x, 1f / lossyScale.y, 1f / lossyScale.z));
  63. matrix4x = lhs * current.projectionMatrix * current.worldToCameraMatrix * matrix4x;
  64. foreach (Material material2 in sharedMaterials)
  65. {
  66. material2.SetMatrix("_ProjMatrix", matrix4x);
  67. }
  68. if (this.m_DisablePixelLights)
  69. {
  70. QualitySettings.pixelLightCount = pixelLightCount;
  71. }
  72. MirrorReflection.s_InsideRendering = false;
  73. }
  74. private void OnDisable()
  75. {
  76. if (this.m_ReflectionTexture)
  77. {
  78. UnityEngine.Object.DestroyImmediate(this.m_ReflectionTexture);
  79. this.m_ReflectionTexture = null;
  80. }
  81. IDictionaryEnumerator enumerator = this.m_ReflectionCameras.GetEnumerator();
  82. try
  83. {
  84. while (enumerator.MoveNext())
  85. {
  86. object obj = enumerator.Current;
  87. UnityEngine.Object.DestroyImmediate(((Camera)((DictionaryEntry)obj).Value).gameObject);
  88. }
  89. }
  90. finally
  91. {
  92. IDisposable disposable;
  93. if ((disposable = (enumerator as IDisposable)) != null)
  94. {
  95. disposable.Dispose();
  96. }
  97. }
  98. this.m_ReflectionCameras.Clear();
  99. }
  100. private void UpdateCameraModes(Camera src, Camera dest)
  101. {
  102. if (dest == null)
  103. {
  104. return;
  105. }
  106. dest.clearFlags = src.clearFlags;
  107. dest.backgroundColor = src.backgroundColor;
  108. if (src.clearFlags == CameraClearFlags.Skybox)
  109. {
  110. Skybox skybox = src.GetComponent(typeof(Skybox)) as Skybox;
  111. Skybox skybox2 = dest.GetComponent(typeof(Skybox)) as Skybox;
  112. if (!skybox || !skybox.material)
  113. {
  114. skybox2.enabled = false;
  115. }
  116. else
  117. {
  118. skybox2.enabled = true;
  119. skybox2.material = skybox.material;
  120. }
  121. }
  122. dest.farClipPlane = src.farClipPlane;
  123. dest.nearClipPlane = src.nearClipPlane;
  124. dest.orthographic = src.orthographic;
  125. dest.fieldOfView = src.fieldOfView;
  126. dest.aspect = src.aspect;
  127. dest.orthographicSize = src.orthographicSize;
  128. }
  129. private void CreateMirrorObjects(Camera currentCamera, out Camera reflectionCamera)
  130. {
  131. reflectionCamera = null;
  132. if (!this.m_ReflectionTexture || this.m_OldReflectionTextureSize != this.m_TextureSize)
  133. {
  134. if (this.m_ReflectionTexture)
  135. {
  136. UnityEngine.Object.DestroyImmediate(this.m_ReflectionTexture);
  137. }
  138. this.m_ReflectionTexture = new RenderTexture(this.m_TextureSize, this.m_TextureSize, 16);
  139. this.m_ReflectionTexture.name = "__MirrorRef" + base.gameObject.name;
  140. this.m_ReflectionTexture.isPowerOfTwo = true;
  141. this.m_ReflectionTexture.hideFlags = HideFlags.DontSave;
  142. this.m_OldReflectionTextureSize = this.m_TextureSize;
  143. }
  144. reflectionCamera = (this.m_ReflectionCameras[currentCamera] as Camera);
  145. if (!reflectionCamera)
  146. {
  147. GameObject gameObject = new GameObject(string.Concat(new object[]
  148. {
  149. "Mirror Refl Camera id",
  150. base.gameObject.GetInstanceID(),
  151. " for ",
  152. currentCamera.GetInstanceID()
  153. }), new Type[]
  154. {
  155. typeof(Camera),
  156. typeof(Skybox)
  157. });
  158. reflectionCamera = gameObject.GetComponent<Camera>();
  159. reflectionCamera.enabled = false;
  160. reflectionCamera.transform.position = base.transform.position;
  161. reflectionCamera.transform.rotation = base.transform.rotation;
  162. reflectionCamera.gameObject.AddComponent<FlareLayer>();
  163. gameObject.hideFlags = HideFlags.HideAndDontSave;
  164. this.m_ReflectionCameras[currentCamera] = reflectionCamera;
  165. }
  166. }
  167. private static float sgn(float a)
  168. {
  169. if (a > 0f)
  170. {
  171. return 1f;
  172. }
  173. if (a < 0f)
  174. {
  175. return -1f;
  176. }
  177. return 0f;
  178. }
  179. private Vector4 CameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
  180. {
  181. Vector3 v = pos + normal * this.m_ClipPlaneOffset;
  182. Matrix4x4 worldToCameraMatrix = cam.worldToCameraMatrix;
  183. Vector3 lhs = worldToCameraMatrix.MultiplyPoint(v);
  184. Vector3 rhs = worldToCameraMatrix.MultiplyVector(normal).normalized * sideSign;
  185. return new Vector4(rhs.x, rhs.y, rhs.z, -Vector3.Dot(lhs, rhs));
  186. }
  187. private static void CalculateObliqueMatrix(ref Matrix4x4 projection, Vector4 clipPlane)
  188. {
  189. Vector4 b = projection.inverse * new Vector4(MirrorReflection.sgn(clipPlane.x), MirrorReflection.sgn(clipPlane.y), 1f, 1f);
  190. Vector4 vector = clipPlane * (2f / Vector4.Dot(clipPlane, b));
  191. projection[2] = vector.x - projection[3];
  192. projection[6] = vector.y - projection[7];
  193. projection[10] = vector.z - projection[11];
  194. projection[14] = vector.w - projection[15];
  195. }
  196. private static void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat, Vector4 plane)
  197. {
  198. reflectionMat.m00 = 1f - 2f * plane[0] * plane[0];
  199. reflectionMat.m01 = -2f * plane[0] * plane[1];
  200. reflectionMat.m02 = -2f * plane[0] * plane[2];
  201. reflectionMat.m03 = -2f * plane[3] * plane[0];
  202. reflectionMat.m10 = -2f * plane[1] * plane[0];
  203. reflectionMat.m11 = 1f - 2f * plane[1] * plane[1];
  204. reflectionMat.m12 = -2f * plane[1] * plane[2];
  205. reflectionMat.m13 = -2f * plane[3] * plane[1];
  206. reflectionMat.m20 = -2f * plane[2] * plane[0];
  207. reflectionMat.m21 = -2f * plane[2] * plane[1];
  208. reflectionMat.m22 = 1f - 2f * plane[2] * plane[2];
  209. reflectionMat.m23 = -2f * plane[3] * plane[2];
  210. reflectionMat.m30 = 0f;
  211. reflectionMat.m31 = 0f;
  212. reflectionMat.m32 = 0f;
  213. reflectionMat.m33 = 1f;
  214. }
  215. public bool m_DisablePixelLights = true;
  216. public int m_TextureSize = 256;
  217. public float m_ClipPlaneOffset = 0.07f;
  218. public LayerMask m_ReflectLayers = -1;
  219. private Hashtable m_ReflectionCameras = new Hashtable();
  220. private RenderTexture m_ReflectionTexture;
  221. private int m_OldReflectionTextureSize;
  222. private static bool s_InsideRendering;
  223. }