Outliner.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEngine;
  6. using UnityEngine.Rendering;
  7. using UnityEngine.Serialization;
  8. namespace EPOOutline
  9. {
  10. public enum DilateQuality
  11. {
  12. Base,
  13. High,
  14. Ultra
  15. }
  16. public enum RenderingMode
  17. {
  18. LDR,
  19. HDR
  20. }
  21. public enum OutlineRenderingStrategy
  22. {
  23. Default,
  24. PerObject
  25. }
  26. public enum RenderStage
  27. {
  28. BeforeTransparents,
  29. AfterTransparents
  30. }
  31. public enum BufferSizeMode
  32. {
  33. WidthControllsHeight,
  34. HeightControlsWidth,
  35. Scaled,
  36. Native
  37. }
  38. [ExecuteAlways]
  39. [RequireComponent(typeof(Camera))]
  40. public class Outliner : MonoBehaviour
  41. {
  42. #if UNITY_EDITOR
  43. private static GameObject lastSelectedOutliner;
  44. private static List<Outliner> outliners = new List<Outliner>();
  45. #endif
  46. private static List<Outlinable> temporaryOutlinables = new List<Outlinable>();
  47. private OutlineParameters parameters = new OutlineParameters();
  48. #if UNITY_EDITOR
  49. private OutlineParameters editorPreviewParameters = new OutlineParameters();
  50. #endif
  51. private Camera targetCamera;
  52. [SerializeField]
  53. private RenderStage stage = RenderStage.AfterTransparents;
  54. [SerializeField]
  55. private OutlineRenderingStrategy renderingStrategy = OutlineRenderingStrategy.Default;
  56. [SerializeField]
  57. private RenderingMode renderingMode;
  58. [SerializeField]
  59. private long outlineLayerMask = -1;
  60. [SerializeField]
  61. private BufferSizeMode primaryBufferSizeMode;
  62. [SerializeField]
  63. [Range(0.15f, 1.0f)]
  64. private float primaryRendererScale = 0.75f;
  65. [SerializeField]
  66. private int primarySizeReference = 800;
  67. [SerializeField]
  68. [Range(0.0f, 2.0f)]
  69. private float blurShift = 1.0f;
  70. [SerializeField]
  71. [Range(0.0f, 2.0f)]
  72. private float dilateShift = 1.0f;
  73. [SerializeField]
  74. [FormerlySerializedAs("dilateIterrations")]
  75. private int dilateIterations = 1;
  76. [SerializeField]
  77. private DilateQuality dilateQuality;
  78. [SerializeField]
  79. [FormerlySerializedAs("blurIterrations")]
  80. private int blurIterations = 1;
  81. [SerializeField]
  82. private BlurType blurType = BlurType.Box;
  83. [Obsolete]
  84. public float InfoRendererScale
  85. {
  86. get
  87. {
  88. throw new NotImplementedException();
  89. }
  90. set
  91. {
  92. throw new NotImplementedException();
  93. }
  94. }
  95. public int PrimarySizeReference
  96. {
  97. get
  98. {
  99. return primarySizeReference;
  100. }
  101. set
  102. {
  103. primarySizeReference = value;
  104. }
  105. }
  106. public BufferSizeMode PrimaryBufferSizeMode
  107. {
  108. get
  109. {
  110. return primaryBufferSizeMode;
  111. }
  112. set
  113. {
  114. primaryBufferSizeMode = value;
  115. }
  116. }
  117. private CameraEvent Event
  118. {
  119. get
  120. {
  121. return stage == RenderStage.BeforeTransparents ? CameraEvent.AfterForwardOpaque : CameraEvent.BeforeImageEffects;
  122. }
  123. }
  124. public OutlineRenderingStrategy RenderingStrategy
  125. {
  126. get
  127. {
  128. return renderingStrategy;
  129. }
  130. set
  131. {
  132. renderingStrategy = value;
  133. }
  134. }
  135. public RenderStage RenderStage
  136. {
  137. get
  138. {
  139. return stage;
  140. }
  141. set
  142. {
  143. stage = value;
  144. }
  145. }
  146. public DilateQuality DilateQuality
  147. {
  148. get
  149. {
  150. return dilateQuality;
  151. }
  152. set
  153. {
  154. dilateQuality = value;
  155. }
  156. }
  157. private RenderingMode RenderingMode
  158. {
  159. get
  160. {
  161. return renderingMode;
  162. }
  163. set
  164. {
  165. renderingMode = value;
  166. }
  167. }
  168. public float BlurShift
  169. {
  170. get
  171. {
  172. return blurShift;
  173. }
  174. set
  175. {
  176. blurShift = Mathf.Clamp(value, 0, 2.0f);
  177. }
  178. }
  179. public float DilateShift
  180. {
  181. get
  182. {
  183. return dilateShift;
  184. }
  185. set
  186. {
  187. dilateShift = Mathf.Clamp(value, 0, 2.0f);
  188. }
  189. }
  190. public long OutlineLayerMask
  191. {
  192. get
  193. {
  194. return outlineLayerMask;
  195. }
  196. set
  197. {
  198. outlineLayerMask = value;
  199. }
  200. }
  201. public float PrimaryRendererScale
  202. {
  203. get
  204. {
  205. return primaryRendererScale;
  206. }
  207. set
  208. {
  209. primaryRendererScale = Mathf.Clamp01(value);
  210. }
  211. }
  212. [Obsolete("Fixed incorrect spelling. Use BlurIterations instead")]
  213. public int BlurIterrations
  214. {
  215. get
  216. {
  217. return BlurIterations;
  218. }
  219. set
  220. {
  221. BlurIterations = value;
  222. }
  223. }
  224. public int BlurIterations
  225. {
  226. get
  227. {
  228. return blurIterations;
  229. }
  230. set
  231. {
  232. blurIterations = value > 0 ? value : 0;
  233. }
  234. }
  235. public BlurType BlurType
  236. {
  237. get
  238. {
  239. return blurType;
  240. }
  241. set
  242. {
  243. blurType = value;
  244. }
  245. }
  246. [Obsolete("Fixed incorrect spelling. Use DilateIterations instead")]
  247. public int DilateIterration
  248. {
  249. get
  250. {
  251. return DilateIterations;
  252. }
  253. set
  254. {
  255. DilateIterations = value;
  256. }
  257. }
  258. public int DilateIterations
  259. {
  260. get
  261. {
  262. return dilateIterations;
  263. }
  264. set
  265. {
  266. dilateIterations = value > 0 ? value : 0;
  267. }
  268. }
  269. private void OnValidate()
  270. {
  271. if (blurIterations < 0)
  272. blurIterations = 0;
  273. if (dilateIterations < 0)
  274. dilateIterations = 0;
  275. }
  276. private void OnEnable()
  277. {
  278. if (targetCamera == null)
  279. targetCamera = GetComponent<Camera>();
  280. targetCamera.forceIntoRenderTexture = targetCamera.stereoTargetEye == StereoTargetEyeMask.None || !UnityEngine.XR.XRSettings.enabled;
  281. #if UNITY_EDITOR
  282. outliners.Add(this);
  283. #endif
  284. parameters.CheckInitialization();
  285. parameters.Buffer.name = "Outline";
  286. #if UNITY_EDITOR
  287. editorPreviewParameters.CheckInitialization();
  288. editorPreviewParameters.Buffer.name = "Editor outline";
  289. #endif
  290. }
  291. private void OnDestroy()
  292. {
  293. #if UNITY_EDITOR
  294. GameObject.DestroyImmediate(editorPreviewParameters.BlitMesh);
  295. if (editorPreviewParameters.Buffer != null)
  296. editorPreviewParameters.Buffer.Dispose();
  297. #endif
  298. GameObject.DestroyImmediate(parameters.BlitMesh);
  299. if (parameters.Buffer != null)
  300. parameters.Buffer.Dispose();
  301. }
  302. private void OnDisable()
  303. {
  304. if (targetCamera != null)
  305. UpdateBuffer(targetCamera, parameters.Buffer, true);
  306. #if UNITY_EDITOR
  307. RemoveFromAllSceneViews();
  308. outliners.Remove(this);
  309. #endif
  310. #if UNITY_EDITOR
  311. foreach (var view in UnityEditor.SceneView.sceneViews)
  312. {
  313. var viewToUpdate = (UnityEditor.SceneView)view;
  314. viewToUpdate.camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, editorPreviewParameters.Buffer);
  315. viewToUpdate.camera.RemoveCommandBuffer(CameraEvent.AfterForwardOpaque, editorPreviewParameters.Buffer);
  316. }
  317. #endif
  318. }
  319. private void UpdateBuffer(Camera targetCamera, CommandBuffer buffer, bool removeOnly)
  320. {
  321. targetCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, buffer);
  322. targetCamera.RemoveCommandBuffer(CameraEvent.AfterForwardOpaque, buffer);
  323. if (removeOnly)
  324. return;
  325. targetCamera.AddCommandBuffer(Event, buffer);
  326. }
  327. private void OnPreRender()
  328. {
  329. if (GraphicsSettings.renderPipelineAsset != null)
  330. return;
  331. parameters.OutlinablesToRender.Clear();
  332. SetupOutline(targetCamera, parameters, false);
  333. }
  334. private void SetupOutline(Camera cameraToUse, OutlineParameters parametersToUse, bool isEditor)
  335. {
  336. UpdateBuffer(cameraToUse, parametersToUse.Buffer, false);
  337. UpdateParameters(parametersToUse, cameraToUse, isEditor);
  338. parametersToUse.Buffer.Clear();
  339. if (renderingStrategy == OutlineRenderingStrategy.Default)
  340. {
  341. OutlineEffect.SetupOutline(parametersToUse);
  342. parametersToUse.BlitMesh = null;
  343. parametersToUse.MeshPool.ReleaseAllMeshes();
  344. }
  345. else
  346. {
  347. temporaryOutlinables.Clear();
  348. temporaryOutlinables.AddRange(parametersToUse.OutlinablesToRender);
  349. parametersToUse.OutlinablesToRender.Clear();
  350. parametersToUse.OutlinablesToRender.Add(null);
  351. foreach (var outlinable in temporaryOutlinables)
  352. {
  353. parametersToUse.OutlinablesToRender[0] = outlinable;
  354. OutlineEffect.SetupOutline(parametersToUse);
  355. parametersToUse.BlitMesh = null;
  356. }
  357. parametersToUse.MeshPool.ReleaseAllMeshes();
  358. }
  359. }
  360. #if UNITY_EDITOR
  361. private void RemoveFromAllSceneViews()
  362. {
  363. foreach (var view in UnityEditor.SceneView.sceneViews)
  364. {
  365. var viewToUpdate = (UnityEditor.SceneView)view;
  366. var eventTransferer = viewToUpdate.camera.GetComponent<OnPreRenderEventTransferer>();
  367. if (eventTransferer != null)
  368. eventTransferer.OnPreRenderEvent -= UpdateEditorCamera;
  369. viewToUpdate.camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, editorPreviewParameters.Buffer);
  370. viewToUpdate.camera.RemoveCommandBuffer(CameraEvent.AfterForwardOpaque, editorPreviewParameters.Buffer);
  371. }
  372. }
  373. private void LateUpdate()
  374. {
  375. if (lastSelectedOutliner == null && outliners.Count > 0)
  376. lastSelectedOutliner = outliners[0].gameObject;
  377. var isSelected = Array.Find(UnityEditor.Selection.gameObjects, x => x == gameObject) ?? lastSelectedOutliner != null;
  378. if (isSelected)
  379. lastSelectedOutliner = gameObject;
  380. foreach (var view in UnityEditor.SceneView.sceneViews)
  381. {
  382. var viewToUpdate = (UnityEditor.SceneView)view;
  383. var eventTransferer = viewToUpdate.camera.GetComponent<OnPreRenderEventTransferer>();
  384. if (eventTransferer != null)
  385. eventTransferer.OnPreRenderEvent -= UpdateEditorCamera;
  386. UpdateBuffer(viewToUpdate.camera, editorPreviewParameters.Buffer, true);
  387. }
  388. if (!isSelected)
  389. return;
  390. foreach (var view in UnityEditor.SceneView.sceneViews)
  391. {
  392. var viewToUpdate = (UnityEditor.SceneView)view;
  393. if (!viewToUpdate.sceneViewState.showImageEffects)
  394. continue;
  395. var eventTransferer = viewToUpdate.camera.GetComponent<OnPreRenderEventTransferer>();
  396. if (eventTransferer == null)
  397. eventTransferer = viewToUpdate.camera.gameObject.AddComponent<OnPreRenderEventTransferer>();
  398. eventTransferer.OnPreRenderEvent += UpdateEditorCamera;
  399. }
  400. }
  401. private void UpdateEditorCamera(Camera camera)
  402. {
  403. SetupOutline(camera, editorPreviewParameters, true);
  404. }
  405. #endif
  406. public void UpdateSharedParameters(OutlineParameters parameters, Camera camera, bool editorCamera)
  407. {
  408. parameters.DilateQuality = DilateQuality;
  409. parameters.Camera = camera;
  410. parameters.IsEditorCamera = editorCamera;
  411. parameters.PrimaryBufferScale = primaryRendererScale;
  412. parameters.PrimaryBufferSizeMode = primaryBufferSizeMode;
  413. parameters.PrimaryBufferSizeReference = primarySizeReference;
  414. parameters.BlurIterations = blurIterations;
  415. parameters.BlurType = blurType;
  416. parameters.DilateIterations = dilateIterations;
  417. parameters.BlurShift = blurShift;
  418. parameters.DilateShift = dilateShift;
  419. parameters.UseHDR = camera.allowHDR && (RenderingMode == RenderingMode.HDR);
  420. parameters.EyeMask = camera.stereoTargetEye;
  421. parameters.OutlineLayerMask = outlineLayerMask;
  422. parameters.Prepare();
  423. }
  424. private void UpdateParameters(OutlineParameters parameters, Camera camera, bool editorCamera)
  425. {
  426. parameters.DepthTarget = RenderTargetUtility.ComposeTarget(parameters, BuiltinRenderTextureType.CameraTarget);
  427. var targetTexture = camera.targetTexture == null ? camera.activeTexture : camera.targetTexture;
  428. if (UnityEngine.XR.XRSettings.enabled
  429. && !parameters.IsEditorCamera
  430. && parameters.EyeMask != StereoTargetEyeMask.None)
  431. {
  432. var descriptor = UnityEngine.XR.XRSettings.eyeTextureDesc;
  433. parameters.TargetWidth = descriptor.width;
  434. parameters.TargetHeight = descriptor.height;
  435. }
  436. else
  437. {
  438. parameters.TargetWidth = targetTexture != null ? targetTexture.width : camera.scaledPixelWidth;
  439. parameters.TargetHeight = targetTexture != null ? targetTexture.height : camera.scaledPixelHeight;
  440. }
  441. parameters.Antialiasing = editorCamera ? (targetTexture == null ? 1 : targetTexture.antiAliasing) : CameraUtility.GetMSAA(targetCamera);
  442. parameters.Target = RenderTargetUtility.ComposeTarget(parameters, BuiltinRenderTextureType.CameraTarget);
  443. parameters.Camera = camera;
  444. Outlinable.GetAllActiveOutlinables(parameters.Camera, parameters.OutlinablesToRender);
  445. RendererFilteringUtility.Filter(parameters.Camera, parameters);
  446. UpdateSharedParameters(parameters, camera, editorCamera);
  447. }
  448. }
  449. }