You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
6.6 KiB

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. [ExecuteInEditMode]
  5. [RequireComponent(typeof(WaterBase))]
  6. public class PlanarReflection : MonoBehaviour
  7. {
  8. // reflection
  9. public LayerMask reflectionMask;
  10. public bool reflectSkybox = false;
  11. public Color clearColor = Color.grey;
  12. public System.String reflectionSampler = "_ReflectionTex";
  13. // height
  14. public float clipPlaneOffset = 0.07F;
  15. private Vector3 oldpos = Vector3.zero;
  16. private Camera reflectionCamera;
  17. private Material sharedMaterial = null;
  18. private Dictionary<Camera, bool> helperCameras = null;
  19. public void Start ()
  20. {
  21. sharedMaterial = ((WaterBase)gameObject.GetComponent(typeof(WaterBase))).sharedMaterial;
  22. }
  23. private Camera CreateReflectionCameraFor(Camera cam)
  24. {
  25. System.String reflName = gameObject.name+"Reflection"+cam.name;
  26. GameObject go = GameObject.Find(reflName);
  27. if(!go)
  28. go = new GameObject(reflName, typeof(Camera));
  29. if(!go.GetComponent(typeof(Camera)))
  30. go.AddComponent(typeof(Camera));
  31. Camera reflectCamera = go.camera;
  32. reflectCamera.backgroundColor = clearColor;
  33. reflectCamera.clearFlags = reflectSkybox ? CameraClearFlags.Skybox : CameraClearFlags.SolidColor;
  34. SetStandardCameraParameter(reflectCamera,reflectionMask);
  35. if(!reflectCamera.targetTexture)
  36. reflectCamera.targetTexture = CreateTextureFor(cam);
  37. return reflectCamera;
  38. }
  39. private void SetStandardCameraParameter(Camera cam, LayerMask mask)
  40. {
  41. cam.cullingMask = mask & ~(1<<LayerMask.NameToLayer("Water"));
  42. cam.backgroundColor = Color.black;
  43. cam.enabled = false;
  44. }
  45. private RenderTexture CreateTextureFor(Camera cam)
  46. {
  47. RenderTexture rt = new RenderTexture(Mathf.FloorToInt(cam.pixelWidth*0.5F), Mathf.FloorToInt(cam.pixelHeight*0.5F), 24);
  48. rt.hideFlags = HideFlags.DontSave;
  49. return rt;
  50. }
  51. public void RenderHelpCameras (Camera currentCam)
  52. {
  53. if (null == helperCameras)
  54. helperCameras = new Dictionary<Camera, bool>();
  55. if(!helperCameras.ContainsKey(currentCam)) {
  56. helperCameras.Add(currentCam, false);
  57. }
  58. if(helperCameras[currentCam]) {
  59. return;
  60. }
  61. if(!reflectionCamera)
  62. reflectionCamera = CreateReflectionCameraFor(currentCam);
  63. RenderReflectionFor(currentCam, reflectionCamera);
  64. helperCameras[currentCam] = true;
  65. }
  66. public void LateUpdate ()
  67. {
  68. if (null != helperCameras)
  69. helperCameras.Clear();
  70. }
  71. public void WaterTileBeingRendered (Transform tr, Camera currentCam)
  72. {
  73. RenderHelpCameras(currentCam);
  74. if(reflectionCamera && sharedMaterial) {
  75. sharedMaterial.SetTexture(reflectionSampler, reflectionCamera.targetTexture);
  76. }
  77. }
  78. public void OnEnable()
  79. {
  80. Shader.EnableKeyword("WATER_REFLECTIVE");
  81. Shader.DisableKeyword("WATER_SIMPLE");
  82. }
  83. public void OnDisable()
  84. {
  85. Shader.EnableKeyword("WATER_SIMPLE");
  86. Shader.DisableKeyword("WATER_REFLECTIVE");
  87. }
  88. private void RenderReflectionFor (Camera cam, Camera reflectCamera)
  89. {
  90. if(!reflectCamera)
  91. return;
  92. if(sharedMaterial && !sharedMaterial.HasProperty(reflectionSampler)) {
  93. return;
  94. }
  95. reflectCamera.cullingMask = reflectionMask & ~(1<<LayerMask.NameToLayer("Water"));
  96. SaneCameraSettings(reflectCamera);
  97. reflectCamera.backgroundColor = clearColor;
  98. reflectCamera.clearFlags = reflectSkybox ? CameraClearFlags.Skybox : CameraClearFlags.SolidColor;
  99. if(reflectSkybox)
  100. {
  101. if(cam.gameObject.GetComponent(typeof(Skybox)))
  102. {
  103. Skybox sb = (Skybox)reflectCamera.gameObject.GetComponent(typeof(Skybox));
  104. if (!sb)
  105. sb = (Skybox)reflectCamera.gameObject.AddComponent(typeof(Skybox));
  106. sb.material = ((Skybox)cam.GetComponent(typeof(Skybox))).material;
  107. }
  108. }
  109. GL.SetRevertBackfacing(true);
  110. Transform reflectiveSurface = transform; //waterHeight;
  111. Vector3 eulerA = cam.transform.eulerAngles;
  112. reflectCamera.transform.eulerAngles = new Vector3(-eulerA.x, eulerA.y, eulerA.z);
  113. reflectCamera.transform.position = cam.transform.position;
  114. Vector3 pos = reflectiveSurface.transform.position;
  115. pos.y = reflectiveSurface.position.y;
  116. Vector3 normal = reflectiveSurface.transform.up;
  117. float d = -Vector3.Dot(normal, pos) - clipPlaneOffset;
  118. Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
  119. Matrix4x4 reflection = Matrix4x4.zero;
  120. reflection = CalculateReflectionMatrix(reflection, reflectionPlane);
  121. oldpos = cam.transform.position;
  122. Vector3 newpos = reflection.MultiplyPoint (oldpos);
  123. reflectCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
  124. Vector4 clipPlane = CameraSpacePlane(reflectCamera, pos, normal, 1.0f);
  125. reflectCamera.projectionMatrix = cam.CalculateObliqueMatrix(clipPlane);
  126. reflectCamera.transform.position = newpos;
  127. Vector3 euler = cam.transform.eulerAngles;
  128. reflectCamera.transform.eulerAngles = new Vector3(-euler.x, euler.y, euler.z);
  129. reflectCamera.Render();
  130. GL.SetRevertBackfacing(false);
  131. }
  132. private void SaneCameraSettings(Camera helperCam)
  133. {
  134. helperCam.depthTextureMode = DepthTextureMode.None;
  135. helperCam.backgroundColor = Color.black;
  136. helperCam.clearFlags = CameraClearFlags.SolidColor;
  137. helperCam.renderingPath = RenderingPath.Forward;
  138. }
  139. static Matrix4x4 CalculateReflectionMatrix (Matrix4x4 reflectionMat, Vector4 plane)
  140. {
  141. reflectionMat.m00 = (1.0F - 2.0F*plane[0]*plane[0]);
  142. reflectionMat.m01 = ( - 2.0F*plane[0]*plane[1]);
  143. reflectionMat.m02 = ( - 2.0F*plane[0]*plane[2]);
  144. reflectionMat.m03 = ( - 2.0F*plane[3]*plane[0]);
  145. reflectionMat.m10 = ( - 2.0F*plane[1]*plane[0]);
  146. reflectionMat.m11 = (1.0F - 2.0F*plane[1]*plane[1]);
  147. reflectionMat.m12 = ( - 2.0F*plane[1]*plane[2]);
  148. reflectionMat.m13 = ( - 2.0F*plane[3]*plane[1]);
  149. reflectionMat.m20 = ( - 2.0F*plane[2]*plane[0]);
  150. reflectionMat.m21 = ( - 2.0F*plane[2]*plane[1]);
  151. reflectionMat.m22 = (1.0F - 2.0F*plane[2]*plane[2]);
  152. reflectionMat.m23 = ( - 2.0F*plane[3]*plane[2]);
  153. reflectionMat.m30 = 0.0F;
  154. reflectionMat.m31 = 0.0F;
  155. reflectionMat.m32 = 0.0F;
  156. reflectionMat.m33 = 1.0F;
  157. return reflectionMat;
  158. }
  159. static float sgn (float a) {
  160. if (a > 0.0F) return 1.0F;
  161. if (a < 0.0F) return -1.0F;
  162. return 0.0F;
  163. }
  164. private Vector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)
  165. {
  166. Vector3 offsetPos = pos + normal * clipPlaneOffset;
  167. Matrix4x4 m = cam.worldToCameraMatrix;
  168. Vector3 cpos = m.MultiplyPoint (offsetPos);
  169. Vector3 cnormal = m.MultiplyVector (normal).normalized * sideSign;
  170. return new Vector4 (cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot (cpos,cnormal));
  171. }
  172. }