DynamicOcclusionDepthBuffer.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using UnityEngine;
  2. using System.Collections;
  3. namespace VLB
  4. {
  5. [ExecuteInEditMode]
  6. [HelpURL(Consts.HelpUrlDynamicOcclusionDepthBuffer)]
  7. public class DynamicOcclusionDepthBuffer : DynamicOcclusionAbstractBase
  8. {
  9. /// <summary>
  10. /// The beam can only be occluded by objects located on the layers matching this mask.
  11. /// It's very important to set it as restrictive as possible (checking only the layers which are necessary)
  12. /// to perform a more efficient process in order to increase the performance.
  13. /// It should NOT include the layer on which the beams are generated.
  14. /// </summary>
  15. public LayerMask layerMask = Consts.DynOcclusionLayerMaskDefault;
  16. /// <summary>
  17. /// Whether or not the virtual camera will use occlusion culling during rendering from the beam's POV.
  18. /// </summary>
  19. public bool useOcclusionCulling = Consts.DynOcclusionDepthBufferOcclusionCullingDefault;
  20. /// <summary>
  21. /// Controls how large the depth texture captured by the virtual camera is.
  22. /// The lower the resolution, the better the performance, but the less accurate the rendering.
  23. /// </summary>
  24. public int depthMapResolution = Consts.DynOcclusionDepthBufferDepthMapResolutionDefault;
  25. /// <summary>
  26. /// Fade out the beam before the occlusion surface in order to soften the transition.
  27. /// </summary>
  28. public float fadeDistanceToSurface = Consts.DynOcclusionFadeDistanceToSurfaceDefault;
  29. protected override string GetShaderKeyword() { return "VLB_OCCLUSION_DEPTH_TEXTURE"; }
  30. protected override MaterialManager.DynamicOcclusion GetDynamicOcclusionMode() { return MaterialManager.DynamicOcclusion.DepthTexture; }
  31. Camera m_DepthCamera = null;
  32. bool m_NeedToUpdateOcclusionNextFrame = false;
  33. void ProcessOcclusionInternal()
  34. {
  35. UpdateDepthCameraPropertiesAccordingToBeam();
  36. m_DepthCamera.Render();
  37. }
  38. protected override bool OnProcessOcclusion(ProcessOcclusionSource source)
  39. {
  40. Debug.Assert(m_Master && m_DepthCamera);
  41. if (source == ProcessOcclusionSource.RenderLoop && SRPHelper.IsUsingCustomRenderPipeline()) // Recursive rendering is not supported on SRP
  42. m_NeedToUpdateOcclusionNextFrame = true;
  43. else
  44. ProcessOcclusionInternal();
  45. return true;
  46. }
  47. void Update()
  48. {
  49. if (m_NeedToUpdateOcclusionNextFrame && m_Master && m_DepthCamera)
  50. {
  51. ProcessOcclusionInternal();
  52. m_NeedToUpdateOcclusionNextFrame = false;
  53. }
  54. }
  55. void UpdateDepthCameraPropertiesAccordingToBeam()
  56. {
  57. Debug.Assert(m_Master);
  58. Debug.Assert(m_DepthCamera);
  59. float apexDist = m_Master.coneApexOffsetZ;
  60. m_DepthCamera.transform.localPosition = m_Master.beamLocalForward * (-apexDist);
  61. m_DepthCamera.transform.localRotation = m_Master.beamInternalLocalRotation;
  62. var scale = m_Master.lossyScale;
  63. if (!Mathf.Approximately(scale.y * scale.z, 0))
  64. {
  65. const float kMinNearClipPlane = 0.1f; // should be the same than in shader
  66. m_DepthCamera.nearClipPlane = Mathf.Max(apexDist, kMinNearClipPlane) * scale.z;
  67. m_DepthCamera.farClipPlane = (m_Master.maxGeometryDistance + apexDist) * scale.z;
  68. m_DepthCamera.aspect = scale.x / scale.y;
  69. m_DepthCamera.fieldOfView = scale.y * m_Master.coneAngle / scale.z;
  70. }
  71. }
  72. public bool HasLayerMaskIssues()
  73. {
  74. if(Config.Instance.geometryOverrideLayer)
  75. {
  76. int layerBit = 1 << Config.Instance.geometryLayerID;
  77. return ((layerMask.value & layerBit) == layerBit);
  78. }
  79. return false;
  80. }
  81. protected override void OnValidateProperties()
  82. {
  83. base.OnValidateProperties();
  84. depthMapResolution = Mathf.Clamp(Mathf.NextPowerOfTwo(depthMapResolution), 8, 2048);
  85. fadeDistanceToSurface = Mathf.Max(fadeDistanceToSurface, 0f);
  86. }
  87. void InstantiateOrActivateDepthCamera()
  88. {
  89. if (m_DepthCamera != null)
  90. {
  91. m_DepthCamera.gameObject.SetActive(true); // active it in case it has been disabled by OnDisable()
  92. }
  93. else
  94. {
  95. m_DepthCamera = new GameObject("Depth Camera").AddComponent<Camera>();
  96. if (m_DepthCamera && m_Master)
  97. {
  98. m_DepthCamera.enabled = false;
  99. m_DepthCamera.cullingMask = layerMask;
  100. m_DepthCamera.clearFlags = CameraClearFlags.Depth;
  101. m_DepthCamera.depthTextureMode = DepthTextureMode.Depth;
  102. m_DepthCamera.renderingPath = RenderingPath.VertexLit; // faster
  103. m_DepthCamera.useOcclusionCulling = useOcclusionCulling;
  104. m_DepthCamera.gameObject.hideFlags = Consts.ProceduralObjectsHideFlags;
  105. m_DepthCamera.transform.SetParent(transform, false);
  106. var rt = new RenderTexture(depthMapResolution, depthMapResolution, 16, RenderTextureFormat.Depth);
  107. m_DepthCamera.targetTexture = rt;
  108. UpdateDepthCameraPropertiesAccordingToBeam();
  109. #if UNITY_EDITOR
  110. UnityEditor.GameObjectUtility.SetStaticEditorFlags(m_DepthCamera.gameObject, m_Master.GetStaticEditorFlagsForSubObjects());
  111. m_DepthCamera.gameObject.SetSameSceneVisibilityStatesThan(m_Master.gameObject);
  112. #endif
  113. }
  114. }
  115. }
  116. protected override void OnEnablePostValidate()
  117. {
  118. InstantiateOrActivateDepthCamera();
  119. }
  120. protected override void OnDisable()
  121. {
  122. base.OnDisable();
  123. if (m_DepthCamera) m_DepthCamera.gameObject.SetActive(false);
  124. }
  125. protected override void Awake()
  126. {
  127. base.Awake();
  128. #if UNITY_EDITOR
  129. MarkMaterialAsDirty();
  130. #endif
  131. }
  132. protected override void OnDestroy()
  133. {
  134. base.OnDestroy();
  135. DestroyDepthCamera();
  136. #if UNITY_EDITOR
  137. MarkMaterialAsDirty();
  138. #endif
  139. }
  140. void DestroyDepthCamera()
  141. {
  142. if (m_DepthCamera)
  143. {
  144. if (m_DepthCamera.targetTexture)
  145. {
  146. m_DepthCamera.targetTexture.Release();
  147. DestroyImmediate(m_DepthCamera.targetTexture);
  148. m_DepthCamera.targetTexture = null;
  149. }
  150. DestroyImmediate(m_DepthCamera.gameObject); // Make sure to delete the GAO
  151. m_DepthCamera = null;
  152. }
  153. }
  154. protected override void OnModifyMaterialCallback(MaterialModifier.Interface owner)
  155. {
  156. Debug.Assert(owner != null);
  157. owner.SetMaterialProp(ShaderProperties.DynamicOcclusionDepthTexture, m_DepthCamera.targetTexture);
  158. owner.SetMaterialProp(ShaderProperties.DynamicOcclusionDepthProps, fadeDistanceToSurface);
  159. }
  160. #if UNITY_EDITOR
  161. bool m_NeedToReinstantiateDepthCamera = false;
  162. void MarkMaterialAsDirty()
  163. {
  164. // when adding/removing this component in editor, we might need to switch from a GPU Instanced material to a custom one,
  165. // since this feature doesn't support GPU Instancing
  166. if (!Application.isPlaying)
  167. m_Master._EditorSetBeamGeomDirty();
  168. }
  169. protected override void OnValidate()
  170. {
  171. base.OnValidate();
  172. m_NeedToReinstantiateDepthCamera = true;
  173. }
  174. void LateUpdate()
  175. {
  176. if (!Application.isPlaying)
  177. {
  178. if (m_NeedToReinstantiateDepthCamera)
  179. {
  180. DestroyDepthCamera();
  181. InstantiateOrActivateDepthCamera();
  182. m_NeedToReinstantiateDepthCamera = false;
  183. }
  184. if(m_Master && m_Master.enabled)
  185. ProcessOcclusion(ProcessOcclusionSource.EditorUpdate);
  186. }
  187. }
  188. #endif // UNITY_EDITOR
  189. }
  190. }