PlanarReflection.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using UnityEngine;
  2. public class PlanarReflection : MonoBehaviour
  3. {
  4. public bool VR = false;
  5. public int ReflectionTexResolution = 512;
  6. public float Offset = 0.0f;
  7. [Range(0, 1)]
  8. public float ReflectionAlpha=0.5f;
  9. public bool BlurredReflection;
  10. public LayerMask LayersToReflect = -1;
  11. private Camera reflectionCamera;
  12. private RenderTexture reflectionTexture = null, reflectionTextureRight = null;
  13. private static bool isRendering = false;
  14. private Material material;
  15. private Camera cam;
  16. private static readonly int reflectionTexString = Shader.PropertyToID("_ReflectionTex");
  17. private static readonly int reflectionTexRString = Shader.PropertyToID("_ReflectionTexRight");
  18. private static readonly int reflectionAlphaString = Shader.PropertyToID("_RefAlpha");
  19. private static readonly string blurString = "BLUR";
  20. private static readonly string vrString = "VRon";
  21. private Matrix4x4 reflectionMatrix;
  22. private Vector4 reflectionPlane;
  23. private Vector3 posistion;
  24. private Vector3 normal;
  25. private Vector4 oblique;
  26. private Matrix4x4 worldToCameraMatrix;
  27. private Vector3 clipNormal;
  28. private Vector4 clipPlane;
  29. private Vector3 oldPosition;
  30. Vector3 eulerAngles;
  31. public void Start()
  32. {
  33. cam = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
  34. material = GetComponent<Renderer>().sharedMaterials[0];
  35. QualitySettings.pixelLightCount = 0;
  36. GameObject go = new GameObject(GetInstanceID().ToString(), typeof(Camera), typeof(Skybox));
  37. reflectionCamera = go.GetComponent<Camera>();
  38. reflectionCamera.enabled = false;
  39. reflectionCamera.transform.position = transform.position;
  40. reflectionCamera.transform.rotation = transform.rotation;
  41. reflectionCamera.gameObject.AddComponent<FlareLayer>();
  42. reflectionCamera.cullingMask = ~(1 << 4) & LayersToReflect.value;
  43. reflectionCamera.cameraType = CameraType.Reflection;
  44. go.hideFlags = HideFlags.HideAndDontSave;
  45. if (reflectionTexture)
  46. {
  47. DestroyImmediate(reflectionTexture);
  48. }
  49. reflectionTexture = new RenderTexture(ReflectionTexResolution, ReflectionTexResolution, 16);
  50. reflectionTexture.isPowerOfTwo = true;
  51. reflectionTexture.hideFlags = HideFlags.DontSave;
  52. if (reflectionTextureRight)
  53. {
  54. DestroyImmediate(reflectionTextureRight);
  55. }
  56. reflectionTextureRight = new RenderTexture(ReflectionTexResolution, ReflectionTexResolution, 16);
  57. reflectionTextureRight.isPowerOfTwo = true;
  58. reflectionTextureRight.hideFlags = HideFlags.DontSave;
  59. if (cam.clearFlags == CameraClearFlags.Skybox)
  60. {
  61. Skybox sky = cam.GetComponent(typeof(Skybox)) as Skybox;
  62. Skybox mysky = reflectionCamera.GetComponent(typeof(Skybox)) as Skybox;
  63. if (!sky || !sky.material)
  64. {
  65. mysky.enabled = false;
  66. }
  67. else
  68. {
  69. mysky.enabled = true;
  70. mysky.material = sky.material;
  71. }
  72. }
  73. }
  74. public void OnWillRenderObject()
  75. {
  76. if (isRendering)
  77. {
  78. return;
  79. }
  80. isRendering = true;
  81. posistion = transform.position;
  82. normal = transform.up;
  83. reflectionCamera.clearFlags = cam.clearFlags;
  84. reflectionCamera.backgroundColor = cam.backgroundColor;
  85. reflectionCamera.farClipPlane = cam.farClipPlane;
  86. reflectionCamera.nearClipPlane = cam.nearClipPlane;
  87. reflectionCamera.orthographic = cam.orthographic;
  88. reflectionCamera.fieldOfView = cam.fieldOfView;
  89. reflectionCamera.aspect = cam.aspect;
  90. reflectionCamera.orthographicSize = cam.orthographicSize;
  91. reflectionPlane = new Vector4(normal.x, normal.y, normal.z, -Vector3.Dot(normal, posistion) - Offset);
  92. reflectionMatrix.m00 = (1F - 2F * reflectionPlane[0] * reflectionPlane[0]);
  93. reflectionMatrix.m01 = (-2F * reflectionPlane[0] * reflectionPlane[1]);
  94. reflectionMatrix.m02 = (-2F * reflectionPlane[0] * reflectionPlane[2]);
  95. reflectionMatrix.m03 = (-2F * reflectionPlane[3] * reflectionPlane[0]);
  96. reflectionMatrix.m10 = (-2F * reflectionPlane[1] * reflectionPlane[0]);
  97. reflectionMatrix.m11 = (1F - 2F * reflectionPlane[1] * reflectionPlane[1]);
  98. reflectionMatrix.m12 = (-2F * reflectionPlane[1] * reflectionPlane[2]);
  99. reflectionMatrix.m13 = (-2F * reflectionPlane[3] * reflectionPlane[1]);
  100. reflectionMatrix.m20 = (-2F * reflectionPlane[2] * reflectionPlane[0]);
  101. reflectionMatrix.m21 = (-2F * reflectionPlane[2] * reflectionPlane[1]);
  102. reflectionMatrix.m22 = (1F - 2F * reflectionPlane[2] * reflectionPlane[2]);
  103. reflectionMatrix.m23 = (-2F * reflectionPlane[3] * reflectionPlane[2]);
  104. reflectionMatrix.m30 = 0F;
  105. reflectionMatrix.m31 = 0F;
  106. reflectionMatrix.m32 = 0F;
  107. reflectionMatrix.m33 = 1F;
  108. oldPosition = cam.transform.position;
  109. reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflectionMatrix;
  110. worldToCameraMatrix = reflectionCamera.worldToCameraMatrix;
  111. clipNormal = worldToCameraMatrix.MultiplyVector(normal).normalized;
  112. clipPlane = new Vector4(clipNormal.x, clipNormal.y, clipNormal.z, -Vector3.Dot(worldToCameraMatrix.MultiplyPoint(posistion + normal * Offset), clipNormal));
  113. if (!VR)
  114. {
  115. RenderObjectCamera(cam.projectionMatrix, false);
  116. material.DisableKeyword(vrString);
  117. }
  118. else
  119. {
  120. RenderObjectCamera(cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left), false);
  121. RenderObjectCamera(cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right), true);
  122. material.EnableKeyword(vrString);
  123. }
  124. material.SetTexture(reflectionTexString, reflectionTexture);
  125. material.SetFloat(reflectionAlphaString, ReflectionAlpha);
  126. if (VR)
  127. {
  128. material.SetTexture(reflectionTexRString, reflectionTextureRight);
  129. }
  130. if (BlurredReflection)
  131. {
  132. material.EnableKeyword(blurString);
  133. }
  134. else
  135. {
  136. material.DisableKeyword(blurString);
  137. }
  138. isRendering = false;
  139. }
  140. void OnDisable()
  141. {
  142. //if (reflectionTexture)
  143. //{
  144. // DestroyImmediate(reflectionTexture);
  145. // reflectionTexture = null;
  146. //}
  147. //if (reflectionTextureRight)
  148. //{
  149. // DestroyImmediate(reflectionTextureRight);
  150. // reflectionTextureRight = null;
  151. //}
  152. //if (reflectionCamera)
  153. //{
  154. // DestroyImmediate(reflectionCamera.gameObject);
  155. // reflectionCamera = null;
  156. //}
  157. }
  158. private void RenderObjectCamera(Matrix4x4 projection, bool right)
  159. {
  160. oblique = clipPlane * (2.0F / (Vector4.Dot(clipPlane, projection.inverse * new Vector4(sgn(clipPlane.x), sgn(clipPlane.y), 1.0f, 1.0f))));
  161. projection[2] = oblique.x - projection[3];
  162. projection[6] = oblique.y - projection[7];
  163. projection[10] = oblique.z - projection[11];
  164. projection[14] = oblique.w - projection[15];
  165. reflectionCamera.projectionMatrix = projection;
  166. reflectionCamera.targetTexture = right ? reflectionTextureRight : reflectionTexture;
  167. GL.invertCulling = true;
  168. reflectionCamera.transform.position = reflectionMatrix.MultiplyPoint(oldPosition);
  169. eulerAngles = cam.transform.eulerAngles;
  170. reflectionCamera.transform.eulerAngles = new Vector3(0, eulerAngles.y, eulerAngles.z);
  171. reflectionCamera.Render();
  172. reflectionCamera.transform.position = oldPosition;
  173. GL.invertCulling = false;
  174. }
  175. private static float sgn(float a) => a > 0.0f ? 1.0f : a < 0.0f ? -1.0f : 0.0f;
  176. }