CoreUtils.cs 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine.Experimental.Rendering;
  5. namespace UnityEngine.Rendering
  6. {
  7. using UnityObject = UnityEngine.Object;
  8. /// <summary>
  9. /// Set of utility functions for the Core Scriptable Render Pipeline Library
  10. /// </summary>
  11. public static class CoreUtils
  12. {
  13. /// <summary>
  14. /// List of look at matrices for cubemap faces.
  15. /// Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/bb204881(v=vs.85).aspx
  16. /// </summary>
  17. static public readonly Vector3[] lookAtList =
  18. {
  19. new Vector3(1.0f, 0.0f, 0.0f),
  20. new Vector3(-1.0f, 0.0f, 0.0f),
  21. new Vector3(0.0f, 1.0f, 0.0f),
  22. new Vector3(0.0f, -1.0f, 0.0f),
  23. new Vector3(0.0f, 0.0f, 1.0f),
  24. new Vector3(0.0f, 0.0f, -1.0f),
  25. };
  26. /// <summary>
  27. /// List of up vectors for cubemap faces.
  28. /// Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/bb204881(v=vs.85).aspx
  29. /// </summary>
  30. static public readonly Vector3[] upVectorList =
  31. {
  32. new Vector3(0.0f, 1.0f, 0.0f),
  33. new Vector3(0.0f, 1.0f, 0.0f),
  34. new Vector3(0.0f, 0.0f, -1.0f),
  35. new Vector3(0.0f, 0.0f, 1.0f),
  36. new Vector3(0.0f, 1.0f, 0.0f),
  37. new Vector3(0.0f, 1.0f, 0.0f),
  38. };
  39. /// <summary>Edit Menu priority 1</summary>
  40. public const int editMenuPriority1 = 320;
  41. /// <summary>Edit Menu priority 2</summary>
  42. public const int editMenuPriority2 = 331;
  43. /// <summary>Edit Menu priority 3</summary>
  44. public const int editMenuPriority3 = 342;
  45. /// <summary>Edit Menu priority 4</summary>
  46. public const int editMenuPriority4 = 353;
  47. /// <summary>Asset Create Menu priority 1</summary>
  48. public const int assetCreateMenuPriority1 = 230;
  49. /// <summary>Asset Create Menu priority 2</summary>
  50. public const int assetCreateMenuPriority2 = 241;
  51. /// <summary>Asset Create Menu priority 3</summary>
  52. public const int assetCreateMenuPriority3 = 300;
  53. /// <summary>Game Object Menu priority</summary>
  54. public const int gameObjectMenuPriority = 10;
  55. static Cubemap m_BlackCubeTexture;
  56. /// <summary>
  57. /// Black cubemap texture.
  58. /// </summary>
  59. public static Cubemap blackCubeTexture
  60. {
  61. get
  62. {
  63. if (m_BlackCubeTexture == null)
  64. {
  65. m_BlackCubeTexture = new Cubemap(1, TextureFormat.ARGB32, false);
  66. for (int i = 0; i < 6; ++i)
  67. m_BlackCubeTexture.SetPixel((CubemapFace)i, 0, 0, Color.black);
  68. m_BlackCubeTexture.Apply();
  69. }
  70. return m_BlackCubeTexture;
  71. }
  72. }
  73. static Cubemap m_MagentaCubeTexture;
  74. /// <summary>
  75. /// Magenta cubemap texture.
  76. /// </summary>
  77. public static Cubemap magentaCubeTexture
  78. {
  79. get
  80. {
  81. if (m_MagentaCubeTexture == null)
  82. {
  83. m_MagentaCubeTexture = new Cubemap(1, TextureFormat.ARGB32, false);
  84. for (int i = 0; i < 6; ++i)
  85. m_MagentaCubeTexture.SetPixel((CubemapFace)i, 0, 0, Color.magenta);
  86. m_MagentaCubeTexture.Apply();
  87. }
  88. return m_MagentaCubeTexture;
  89. }
  90. }
  91. static CubemapArray m_MagentaCubeTextureArray;
  92. /// <summary>
  93. /// Black cubemap array texture.
  94. /// </summary>
  95. public static CubemapArray magentaCubeTextureArray
  96. {
  97. get
  98. {
  99. if (m_MagentaCubeTextureArray == null)
  100. {
  101. m_MagentaCubeTextureArray = new CubemapArray(1, 1, TextureFormat.RGBAFloat, false);
  102. for (int i = 0; i < 6; ++i)
  103. {
  104. Color[] colors = { Color.magenta };
  105. m_MagentaCubeTextureArray.SetPixels(colors, (CubemapFace)i, 0);
  106. }
  107. m_MagentaCubeTextureArray.Apply();
  108. }
  109. return m_MagentaCubeTextureArray;
  110. }
  111. }
  112. static Cubemap m_WhiteCubeTexture;
  113. /// <summary>
  114. /// White cubemap texture.
  115. /// </summary>
  116. public static Cubemap whiteCubeTexture
  117. {
  118. get
  119. {
  120. if (m_WhiteCubeTexture == null)
  121. {
  122. m_WhiteCubeTexture = new Cubemap(1, TextureFormat.ARGB32, false);
  123. for (int i = 0; i < 6; ++i)
  124. m_WhiteCubeTexture.SetPixel((CubemapFace)i, 0, 0, Color.white);
  125. m_WhiteCubeTexture.Apply();
  126. }
  127. return m_WhiteCubeTexture;
  128. }
  129. }
  130. static RenderTexture m_EmptyUAV;
  131. /// <summary>
  132. /// Empty 1x1 texture usable as a dummy UAV.
  133. /// </summary>
  134. public static RenderTexture emptyUAV
  135. {
  136. get
  137. {
  138. if (m_EmptyUAV == null)
  139. {
  140. m_EmptyUAV = new RenderTexture(1, 1, 0);
  141. m_EmptyUAV.enableRandomWrite = true;
  142. m_EmptyUAV.Create();
  143. }
  144. return m_EmptyUAV;
  145. }
  146. }
  147. static Texture3D m_BlackVolumeTexture;
  148. /// <summary>
  149. /// Black 3D texture.
  150. /// </summary>
  151. public static Texture3D blackVolumeTexture
  152. {
  153. get
  154. {
  155. if (m_BlackVolumeTexture == null)
  156. {
  157. Color[] colors = { Color.black };
  158. m_BlackVolumeTexture = new Texture3D(1, 1, 1, TextureFormat.ARGB32, false);
  159. m_BlackVolumeTexture.SetPixels(colors, 0);
  160. m_BlackVolumeTexture.Apply();
  161. }
  162. return m_BlackVolumeTexture;
  163. }
  164. }
  165. /// <summary>
  166. /// Clear the currently bound render texture.
  167. /// </summary>
  168. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  169. /// <param name="clearFlag">Specify how the render texture should be cleared.</param>
  170. /// <param name="clearColor">Specify with which color the render texture should be cleared.</param>
  171. public static void ClearRenderTarget(CommandBuffer cmd, ClearFlag clearFlag, Color clearColor)
  172. {
  173. if (clearFlag != ClearFlag.None)
  174. cmd.ClearRenderTarget((clearFlag & ClearFlag.Depth) != 0, (clearFlag & ClearFlag.Color) != 0, clearColor);
  175. }
  176. // We use -1 as a default value because when doing SPI for XR, it will bind the full texture array by default (and has no effect on 2D textures)
  177. // Unfortunately, for cubemaps, passing -1 does not work for faces other than the first one, so we fall back to 0 in this case.
  178. private static int FixupDepthSlice(int depthSlice, RTHandle buffer)
  179. {
  180. if (depthSlice == -1 && buffer.rt.dimension == TextureDimension.Cube)
  181. depthSlice = 0;
  182. return depthSlice;
  183. }
  184. private static int FixupDepthSlice(int depthSlice, CubemapFace cubemapFace)
  185. {
  186. if (depthSlice == -1 && cubemapFace != CubemapFace.Unknown)
  187. depthSlice = 0;
  188. return depthSlice;
  189. }
  190. /// <summary>
  191. /// Set the current render texture.
  192. /// </summary>
  193. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  194. /// <param name="buffer">RenderTargetIdentifier of the render texture.</param>
  195. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  196. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  197. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  198. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  199. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  200. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier buffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  201. {
  202. depthSlice = FixupDepthSlice(depthSlice, cubemapFace);
  203. cmd.SetRenderTarget(buffer, miplevel, cubemapFace, depthSlice);
  204. ClearRenderTarget(cmd, clearFlag, clearColor);
  205. }
  206. /// <summary>
  207. /// Set the current render texture.
  208. /// </summary>
  209. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  210. /// <param name="buffer">RenderTargetIdentifier of the render texture.</param>
  211. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  212. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  213. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  214. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  215. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier buffer, ClearFlag clearFlag = ClearFlag.None, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  216. {
  217. SetRenderTarget(cmd, buffer, clearFlag, Color.clear, miplevel, cubemapFace, depthSlice);
  218. }
  219. /// <summary>
  220. /// Set the current render texture.
  221. /// </summary>
  222. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  223. /// <param name="colorBuffer">RenderTargetIdentifier of the color render texture.</param>
  224. /// <param name="depthBuffer">RenderTargetIdentifier of the depth render texture.</param>
  225. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  226. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  227. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  228. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  229. {
  230. SetRenderTarget(cmd, colorBuffer, depthBuffer, ClearFlag.None, Color.clear, miplevel, cubemapFace, depthSlice);
  231. }
  232. /// <summary>
  233. /// Set the current render texture.
  234. /// </summary>
  235. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  236. /// <param name="colorBuffer">RenderTargetIdentifier of the color render texture.</param>
  237. /// <param name="depthBuffer">RenderTargetIdentifier of the depth render texture.</param>
  238. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  239. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  240. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  241. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  242. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  243. {
  244. SetRenderTarget(cmd, colorBuffer, depthBuffer, clearFlag, Color.clear, miplevel, cubemapFace, depthSlice);
  245. }
  246. /// <summary>
  247. /// Set the current render texture.
  248. /// </summary>
  249. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  250. /// <param name="colorBuffer">RenderTargetIdentifier of the color render texture.</param>
  251. /// <param name="depthBuffer">RenderTargetIdentifier of the depth render texture.</param>
  252. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  253. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  254. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  255. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  256. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  257. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  258. {
  259. depthSlice = FixupDepthSlice(depthSlice, cubemapFace);
  260. cmd.SetRenderTarget(colorBuffer, depthBuffer, miplevel, cubemapFace, depthSlice);
  261. ClearRenderTarget(cmd, clearFlag, clearColor);
  262. }
  263. /// <summary>
  264. /// Set the current multiple render texture.
  265. /// </summary>
  266. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  267. /// <param name="colorBuffers">RenderTargetIdentifier array of the color render textures.</param>
  268. /// <param name="depthBuffer">RenderTargetIdentifier of the depth render texture.</param>
  269. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer)
  270. {
  271. SetRenderTarget(cmd, colorBuffers, depthBuffer, ClearFlag.None, Color.clear);
  272. }
  273. /// <summary>
  274. /// Set the current multiple render texture.
  275. /// </summary>
  276. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  277. /// <param name="colorBuffers">RenderTargetIdentifier array of the color render textures.</param>
  278. /// <param name="depthBuffer">RenderTargetIdentifier of the depth render texture.</param>
  279. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  280. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag = ClearFlag.None)
  281. {
  282. SetRenderTarget(cmd, colorBuffers, depthBuffer, clearFlag, Color.clear);
  283. }
  284. /// <summary>
  285. /// Set the current multiple render texture.
  286. /// </summary>
  287. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  288. /// <param name="colorBuffers">RenderTargetIdentifier array of the color render textures.</param>
  289. /// <param name="depthBuffer">RenderTargetIdentifier of the depth render texture.</param>
  290. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  291. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  292. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor)
  293. {
  294. cmd.SetRenderTarget(colorBuffers, depthBuffer, 0, CubemapFace.Unknown, -1);
  295. ClearRenderTarget(cmd, clearFlag, clearColor);
  296. }
  297. // Explicit load and store actions
  298. /// <summary>
  299. /// Set the current render texture.
  300. /// </summary>
  301. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  302. /// <param name="buffer">Color buffer RenderTargetIdentifier.</param>
  303. /// <param name="loadAction">Load action.</param>
  304. /// <param name="storeAction">Store action.</param>
  305. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  306. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  307. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier buffer, RenderBufferLoadAction loadAction, RenderBufferStoreAction storeAction, ClearFlag clearFlag, Color clearColor)
  308. {
  309. cmd.SetRenderTarget(buffer, loadAction, storeAction);
  310. ClearRenderTarget(cmd, clearFlag, clearColor);
  311. }
  312. /// <summary>
  313. /// Set the current render texture.
  314. /// </summary>
  315. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  316. /// <param name="buffer">Color buffer RenderTargetIdentifier.</param>
  317. /// <param name="loadAction">Load action.</param>
  318. /// <param name="storeAction">Store action.</param>
  319. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  320. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier buffer, RenderBufferLoadAction loadAction, RenderBufferStoreAction storeAction, ClearFlag clearFlag)
  321. {
  322. SetRenderTarget(cmd, buffer, loadAction, storeAction, clearFlag, Color.clear);
  323. }
  324. /// <summary>
  325. /// Set the current render texture.
  326. /// </summary>
  327. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  328. /// <param name="colorBuffer">Color buffer RenderTargetIdentifier.</param>
  329. /// <param name="colorLoadAction">Color buffer load action.</param>
  330. /// <param name="colorStoreAction">Color buffer store action.</param>
  331. /// <param name="depthBuffer">Depth buffer RenderTargetIdentifier.</param>
  332. /// <param name="depthLoadAction">Depth buffer load action.</param>
  333. /// <param name="depthStoreAction">Depth buffer store action.</param>
  334. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  335. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  336. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderBufferLoadAction colorLoadAction, RenderBufferStoreAction colorStoreAction,
  337. RenderTargetIdentifier depthBuffer, RenderBufferLoadAction depthLoadAction, RenderBufferStoreAction depthStoreAction,
  338. ClearFlag clearFlag, Color clearColor)
  339. {
  340. cmd.SetRenderTarget(colorBuffer, colorLoadAction, colorStoreAction, depthBuffer, depthLoadAction, depthStoreAction);
  341. ClearRenderTarget(cmd, clearFlag, clearColor);
  342. }
  343. /// <summary>
  344. /// Set the current render texture.
  345. /// </summary>
  346. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  347. /// <param name="colorBuffer">Color buffer RenderTargetIdentifier.</param>
  348. /// <param name="colorLoadAction">Color buffer load action.</param>
  349. /// <param name="colorStoreAction">Color buffer store action.</param>
  350. /// <param name="depthBuffer">Depth buffer RenderTargetIdentifier.</param>
  351. /// <param name="depthLoadAction">Depth buffer load action.</param>
  352. /// <param name="depthStoreAction">Depth buffer store action.</param>
  353. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  354. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderBufferLoadAction colorLoadAction, RenderBufferStoreAction colorStoreAction,
  355. RenderTargetIdentifier depthBuffer, RenderBufferLoadAction depthLoadAction, RenderBufferStoreAction depthStoreAction,
  356. ClearFlag clearFlag)
  357. {
  358. SetRenderTarget(cmd, colorBuffer, colorLoadAction, colorStoreAction, depthBuffer, depthLoadAction, depthStoreAction, clearFlag, Color.clear);
  359. }
  360. private static void SetViewportAndClear(CommandBuffer cmd, RTHandle buffer, ClearFlag clearFlag, Color clearColor)
  361. {
  362. // Clearing a partial viewport currently does not go through the hardware clear.
  363. // Instead it goes through a quad rendered with a specific shader.
  364. // When enabling wireframe mode in the scene view, unfortunately it overrides this shader thus breaking every clears.
  365. // That's why in the editor we don't set the viewport before clearing (it's set to full screen by the previous SetRenderTarget) but AFTER so that we benefit from un-bugged hardware clear.
  366. // We consider that the small loss in performance is acceptable in the editor.
  367. // A refactor of wireframe is needed before we can fix this properly (with not doing anything!)
  368. #if !UNITY_EDITOR
  369. SetViewport(cmd, buffer);
  370. #endif
  371. CoreUtils.ClearRenderTarget(cmd, clearFlag, clearColor);
  372. #if UNITY_EDITOR
  373. SetViewport(cmd, buffer);
  374. #endif
  375. }
  376. // This set of RenderTarget management methods is supposed to be used when rendering RTHandle render texture.
  377. // This will automatically set the viewport based on the RTHandle System reference size and the RTHandle scaling info.
  378. /// <summary>
  379. /// Setup the current render texture using an RTHandle
  380. /// </summary>
  381. /// <param name="cmd">CommandBuffer used for rendering commands</param>
  382. /// <param name="buffer">Color buffer RTHandle</param>
  383. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  384. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  385. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  386. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  387. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  388. public static void SetRenderTarget(CommandBuffer cmd, RTHandle buffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  389. {
  390. depthSlice = FixupDepthSlice(depthSlice, buffer);
  391. cmd.SetRenderTarget(buffer, miplevel, cubemapFace, depthSlice);
  392. SetViewportAndClear(cmd, buffer, clearFlag, clearColor);
  393. }
  394. /// <summary>
  395. /// Setup the current render texture using an RTHandle
  396. /// </summary>
  397. /// <param name="cmd">CommandBuffer used for rendering commands</param>
  398. /// <param name="buffer">Color buffer RTHandle</param>
  399. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  400. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  401. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  402. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  403. public static void SetRenderTarget(CommandBuffer cmd, RTHandle buffer, ClearFlag clearFlag = ClearFlag.None, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  404. => SetRenderTarget(cmd, buffer, clearFlag, Color.clear, miplevel, cubemapFace, depthSlice);
  405. /// <summary>
  406. /// Setup the current render texture using an RTHandle
  407. /// </summary>
  408. /// <param name="cmd">CommandBuffer used for rendering commands</param>
  409. /// <param name="colorBuffer">Color buffer RTHandle</param>
  410. /// <param name="depthBuffer">Depth buffer RTHandle</param>
  411. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  412. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  413. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  414. public static void SetRenderTarget(CommandBuffer cmd, RTHandle colorBuffer, RTHandle depthBuffer, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  415. {
  416. int cw = colorBuffer.rt.width;
  417. int ch = colorBuffer.rt.height;
  418. int dw = depthBuffer.rt.width;
  419. int dh = depthBuffer.rt.height;
  420. Debug.Assert(cw == dw && ch == dh);
  421. SetRenderTarget(cmd, colorBuffer, depthBuffer, ClearFlag.None, Color.clear, miplevel, cubemapFace, depthSlice);
  422. }
  423. /// <summary>
  424. /// Setup the current render texture using an RTHandle
  425. /// </summary>
  426. /// <param name="cmd">CommandBuffer used for rendering commands</param>
  427. /// <param name="colorBuffer">Color buffer RTHandle</param>
  428. /// <param name="depthBuffer">Depth buffer RTHandle</param>
  429. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  430. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  431. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  432. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  433. public static void SetRenderTarget(CommandBuffer cmd, RTHandle colorBuffer, RTHandle depthBuffer, ClearFlag clearFlag, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  434. {
  435. int cw = colorBuffer.rt.width;
  436. int ch = colorBuffer.rt.height;
  437. int dw = depthBuffer.rt.width;
  438. int dh = depthBuffer.rt.height;
  439. Debug.Assert(cw == dw && ch == dh);
  440. SetRenderTarget(cmd, colorBuffer, depthBuffer, clearFlag, Color.clear, miplevel, cubemapFace, depthSlice);
  441. }
  442. /// <summary>
  443. /// Setup the current render texture using an RTHandle
  444. /// </summary>
  445. /// <param name="cmd">CommandBuffer used for rendering commands</param>
  446. /// <param name="colorBuffer">Color buffer RTHandle</param>
  447. /// <param name="depthBuffer">Depth buffer RTHandle</param>
  448. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  449. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  450. /// <param name="miplevel">Mip level that should be bound as a render texture if applicable.</param>
  451. /// <param name="cubemapFace">Cubemap face that should be bound as a render texture if applicable.</param>
  452. /// <param name="depthSlice">Depth slice that should be bound as a render texture if applicable.</param>
  453. public static void SetRenderTarget(CommandBuffer cmd, RTHandle colorBuffer, RTHandle depthBuffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown, int depthSlice = -1)
  454. {
  455. int cw = colorBuffer.rt.width;
  456. int ch = colorBuffer.rt.height;
  457. int dw = depthBuffer.rt.width;
  458. int dh = depthBuffer.rt.height;
  459. Debug.Assert(cw == dw && ch == dh);
  460. CoreUtils.SetRenderTarget(cmd, colorBuffer.rt, depthBuffer.rt, miplevel, cubemapFace, depthSlice);
  461. SetViewportAndClear(cmd, colorBuffer, clearFlag, clearColor);
  462. }
  463. /// <summary>
  464. /// Set the current multiple render texture.
  465. /// </summary>
  466. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  467. /// <param name="colorBuffers">RenderTargetIdentifier array of the color render textures.</param>
  468. /// <param name="depthBuffer">Depth Buffer RTHandle.</param>
  469. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RTHandle depthBuffer)
  470. {
  471. CoreUtils.SetRenderTarget(cmd, colorBuffers, depthBuffer.rt, ClearFlag.None, Color.clear);
  472. SetViewport(cmd, depthBuffer);
  473. }
  474. /// <summary>
  475. /// Set the current multiple render texture.
  476. /// </summary>
  477. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  478. /// <param name="colorBuffers">RenderTargetIdentifier array of the color render textures.</param>
  479. /// <param name="depthBuffer">Depth Buffer RTHandle.</param>
  480. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  481. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RTHandle depthBuffer, ClearFlag clearFlag = ClearFlag.None)
  482. {
  483. CoreUtils.SetRenderTarget(cmd, colorBuffers, depthBuffer.rt); // Don't clear here, viewport needs to be set before we do.
  484. SetViewportAndClear(cmd, depthBuffer, clearFlag, Color.clear);
  485. }
  486. /// <summary>
  487. /// Set the current multiple render texture.
  488. /// </summary>
  489. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  490. /// <param name="colorBuffers">RenderTargetIdentifier array of the color render textures.</param>
  491. /// <param name="depthBuffer">Depth Buffer RTHandle.</param>
  492. /// <param name="clearFlag">If not set to ClearFlag.None, specifies how to clear the render target after setup.</param>
  493. /// <param name="clearColor">If applicable, color with which to clear the render texture after setup.</param>
  494. public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RTHandle depthBuffer, ClearFlag clearFlag, Color clearColor)
  495. {
  496. cmd.SetRenderTarget(colorBuffers, depthBuffer, 0, CubemapFace.Unknown, -1);
  497. SetViewportAndClear(cmd, depthBuffer, clearFlag, clearColor);
  498. }
  499. // Scaling viewport is done for auto-scaling render targets.
  500. // In the context of SRP, every auto-scaled RT is scaled against the maximum RTHandles reference size (that can only grow).
  501. // When we render using a camera whose viewport is smaller than the RTHandles reference size (and thus smaller than the RT actual size), we need to set it explicitly (otherwise, native code will set the viewport at the size of the RT)
  502. // For auto-scaled RTs (like for example a half-resolution RT), we need to scale this viewport accordingly.
  503. // For non scaled RTs we just do nothing, the native code will set the viewport at the size of the RT anyway.
  504. /// <summary>
  505. /// Setup the viewport to the size of the provided RTHandle.
  506. /// </summary>
  507. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  508. /// <param name="target">RTHandle from which to compute the proper viewport.</param>
  509. public static void SetViewport(CommandBuffer cmd, RTHandle target)
  510. {
  511. if (target.useScaling)
  512. {
  513. Vector2Int scaledViewportSize = target.GetScaledSize(target.rtHandleProperties.currentViewportSize);
  514. cmd.SetViewport(new Rect(0.0f, 0.0f, scaledViewportSize.x, scaledViewportSize.y));
  515. }
  516. }
  517. /// <summary>
  518. /// Generate a name based on render texture parameters.
  519. /// </summary>
  520. /// <param name="width">With of the texture.</param>
  521. /// <param name="height">Height of the texture.</param>
  522. /// <param name="depth">Depth of the texture.</param>
  523. /// <param name="format">Format of the render texture.</param>
  524. /// <param name="name">Base name of the texture.</param>
  525. /// <param name="mips">True if the texture has mip maps.</param>
  526. /// <param name="enableMSAA">True if the texture is multisampled.</param>
  527. /// <param name="msaaSamples">Number of MSAA samples.</param>
  528. /// <returns>Generated names bassed on the provided parameters.</returns>
  529. public static string GetRenderTargetAutoName(int width, int height, int depth, RenderTextureFormat format, string name, bool mips = false, bool enableMSAA = false, MSAASamples msaaSamples = MSAASamples.None)
  530. => GetRenderTargetAutoName(width, height, depth, format.ToString(), name, mips, enableMSAA, msaaSamples);
  531. /// <summary>
  532. /// Generate a name based on render texture parameters.
  533. /// </summary>
  534. /// <param name="width">With of the texture.</param>
  535. /// <param name="height">Height of the texture.</param>
  536. /// <param name="depth">Depth of the texture.</param>
  537. /// <param name="format">Graphics format of the render texture.</param>
  538. /// <param name="name">Base name of the texture.</param>
  539. /// <param name="mips">True if the texture has mip maps.</param>
  540. /// <param name="enableMSAA">True if the texture is multisampled.</param>
  541. /// <param name="msaaSamples">Number of MSAA samples.</param>
  542. /// <returns>Generated names bassed on the provided parameters.</returns>
  543. public static string GetRenderTargetAutoName(int width, int height, int depth, GraphicsFormat format, string name, bool mips = false, bool enableMSAA = false, MSAASamples msaaSamples = MSAASamples.None)
  544. => GetRenderTargetAutoName(width, height, depth, format.ToString(), name, mips, enableMSAA, msaaSamples);
  545. static string GetRenderTargetAutoName(int width, int height, int depth, string format, string name, bool mips = false, bool enableMSAA = false, MSAASamples msaaSamples = MSAASamples.None)
  546. {
  547. string result = string.Format("{0}_{1}x{2}", name, width, height);
  548. if (depth > 1)
  549. result = string.Format("{0}x{1}", result, depth);
  550. if (mips)
  551. result = string.Format("{0}_{1}", result, "Mips");
  552. result = string.Format("{0}_{1}", result, format);
  553. if (enableMSAA)
  554. result = string.Format("{0}_{1}", result, msaaSamples.ToString());
  555. return result;
  556. }
  557. /// <summary>
  558. /// Generate a name based on texture parameters.
  559. /// </summary>
  560. /// <param name="width">With of the texture.</param>
  561. /// <param name="height">Height of the texture.</param>
  562. /// <param name="format">Format of the texture.</param>
  563. /// <param name="dim">Dimension of the texture.</param>
  564. /// <param name="name">Base name of the texture.</param>
  565. /// <param name="mips">True if the texture has mip maps.</param>
  566. /// <param name="depth">Depth of the texture.</param>
  567. /// <returns>Generated names based on the provided parameters.</returns>
  568. public static string GetTextureAutoName(int width, int height, TextureFormat format, TextureDimension dim = TextureDimension.None, string name = "", bool mips = false, int depth = 0)
  569. => GetTextureAutoName(width, height, format.ToString(), dim, name, mips, depth);
  570. /// <summary>
  571. /// Generate a name based on texture parameters.
  572. /// </summary>
  573. /// <param name="width">With of the texture.</param>
  574. /// <param name="height">Height of the texture.</param>
  575. /// <param name="format">Graphics format of the texture.</param>
  576. /// <param name="dim">Dimension of the texture.</param>
  577. /// <param name="name">Base name of the texture.</param>
  578. /// <param name="mips">True if the texture has mip maps.</param>
  579. /// <param name="depth">Depth of the texture.</param>
  580. /// <returns>Generated names based on the provided parameters.</returns>
  581. public static string GetTextureAutoName(int width, int height, GraphicsFormat format, TextureDimension dim = TextureDimension.None, string name = "", bool mips = false, int depth = 0)
  582. => GetTextureAutoName(width, height, format.ToString(), dim, name, mips, depth);
  583. static string GetTextureAutoName(int width, int height, string format, TextureDimension dim = TextureDimension.None, string name = "", bool mips = false, int depth = 0)
  584. {
  585. string temp;
  586. if (depth == 0)
  587. temp = string.Format("{0}x{1}{2}_{3}", width, height, mips ? "_Mips" : "", format);
  588. else
  589. temp = string.Format("{0}x{1}x{2}{3}_{4}", width, height, depth, mips ? "_Mips" : "", format);
  590. temp = String.Format("{0}_{1}_{2}", name == "" ? "Texture" : name, (dim == TextureDimension.None) ? "" : dim.ToString(), temp);
  591. return temp;
  592. }
  593. /// <summary>
  594. /// Clear a cubemap render texture.
  595. /// </summary>
  596. /// <param name="cmd">CommandBuffer used for rendering commands.</param>
  597. /// <param name="renderTexture">Cubemap render texture that needs to be cleared.</param>
  598. /// <param name="clearColor">Color used for clearing.</param>
  599. /// <param name="clearMips">Set to true to clear the mip maps of the render texture.</param>
  600. public static void ClearCubemap(CommandBuffer cmd, RenderTexture renderTexture, Color clearColor, bool clearMips = false)
  601. {
  602. int mipCount = 1;
  603. if (renderTexture.useMipMap && clearMips)
  604. {
  605. mipCount = (int)Mathf.Log((float)renderTexture.width, 2.0f) + 1;
  606. }
  607. for (int i = 0; i < 6; ++i)
  608. {
  609. for (int mip = 0; mip < mipCount; ++mip)
  610. {
  611. SetRenderTarget(cmd, new RenderTargetIdentifier(renderTexture), ClearFlag.Color, clearColor, mip, (CubemapFace)i);
  612. }
  613. }
  614. }
  615. /// <summary>
  616. /// Draws a full screen triangle.
  617. /// </summary>
  618. /// <param name="commandBuffer">CommandBuffer used for rendering commands.</param>
  619. /// <param name="material">Material used on the full screen triangle.</param>
  620. /// <param name="properties">Optional material property block for the provided material.</param>
  621. /// <param name="shaderPassId">Index of the material pass.</param>
  622. public static void DrawFullScreen(CommandBuffer commandBuffer, Material material,
  623. MaterialPropertyBlock properties = null, int shaderPassId = 0)
  624. {
  625. commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties);
  626. }
  627. /// <summary>
  628. /// Draws a full screen triangle.
  629. /// </summary>
  630. /// <param name="commandBuffer">CommandBuffer used for rendering commands.</param>
  631. /// <param name="material">Material used on the full screen triangle.</param>
  632. /// <param name="colorBuffer">RenderTargetIdentifier of the color buffer that needs to be set before drawing the full screen triangle.</param>
  633. /// <param name="properties">Optional material property block for the provided material.</param>
  634. /// <param name="shaderPassId">Index of the material pass.</param>
  635. public static void DrawFullScreen(CommandBuffer commandBuffer, Material material,
  636. RenderTargetIdentifier colorBuffer,
  637. MaterialPropertyBlock properties = null, int shaderPassId = 0)
  638. {
  639. commandBuffer.SetRenderTarget(colorBuffer);
  640. commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties);
  641. }
  642. /// <summary>
  643. /// Draws a full screen triangle.
  644. /// </summary>
  645. /// <param name="commandBuffer">CommandBuffer used for rendering commands.</param>
  646. /// <param name="material">Material used on the full screen triangle.</param>
  647. /// <param name="colorBuffer">RenderTargetIdentifier of the color buffer that needs to be set before drawing the full screen triangle.</param>
  648. /// <param name="depthStencilBuffer">RenderTargetIdentifier of the depth buffer that needs to be set before drawing the full screen triangle.</param>
  649. /// <param name="properties">Optional material property block for the provided material.</param>
  650. /// <param name="shaderPassId">Index of the material pass.</param>
  651. public static void DrawFullScreen(CommandBuffer commandBuffer, Material material,
  652. RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthStencilBuffer,
  653. MaterialPropertyBlock properties = null, int shaderPassId = 0)
  654. {
  655. commandBuffer.SetRenderTarget(colorBuffer, depthStencilBuffer, 0, CubemapFace.Unknown, -1);
  656. commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties);
  657. }
  658. /// <summary>
  659. /// Draws a full screen triangle.
  660. /// </summary>
  661. /// <param name="commandBuffer">CommandBuffer used for rendering commands.</param>
  662. /// <param name="material">Material used on the full screen triangle.</param>
  663. /// <param name="colorBuffers">RenderTargetIdentifier array of the color buffers that needs to be set before drawing the full screen triangle.</param>
  664. /// <param name="depthStencilBuffer">RenderTargetIdentifier of the depth buffer that needs to be set before drawing the full screen triangle.</param>
  665. /// <param name="properties">Optional material property block for the provided material.</param>
  666. /// <param name="shaderPassId">Index of the material pass.</param>
  667. public static void DrawFullScreen(CommandBuffer commandBuffer, Material material,
  668. RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthStencilBuffer,
  669. MaterialPropertyBlock properties = null, int shaderPassId = 0)
  670. {
  671. commandBuffer.SetRenderTarget(colorBuffers, depthStencilBuffer, 0, CubemapFace.Unknown, -1);
  672. commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties);
  673. }
  674. // Important: the first RenderTarget must be created with 0 depth bits!
  675. /// <summary>
  676. /// Draws a full screen triangle.
  677. /// </summary>
  678. /// <param name="commandBuffer">CommandBuffer used for rendering commands.</param>
  679. /// <param name="material">Material used on the full screen triangle.</param>
  680. /// <param name="colorBuffers">RenderTargetIdentifier array of the color buffers that needs to be set before drawing the full screen triangle.</param>
  681. /// <param name="properties">Optional material property block for the provided material.</param>
  682. /// <param name="shaderPassId">Index of the material pass.</param>
  683. public static void DrawFullScreen(CommandBuffer commandBuffer, Material material,
  684. RenderTargetIdentifier[] colorBuffers,
  685. MaterialPropertyBlock properties = null, int shaderPassId = 0)
  686. {
  687. // It is currently not possible to have MRT without also setting a depth target.
  688. // To work around this deficiency of the CommandBuffer.SetRenderTarget() API,
  689. // we pass the first color target as the depth target. If it has 0 depth bits,
  690. // no depth target ends up being bound.
  691. DrawFullScreen(commandBuffer, material, colorBuffers, colorBuffers[0], properties, shaderPassId);
  692. }
  693. // Color space utilities
  694. /// <summary>
  695. /// Converts the provided sRGB color to the current active color space.
  696. /// </summary>
  697. /// <param name="color">Input color.</param>
  698. /// <returns>Linear color if the active color space is ColorSpace.Linear, the original input otherwise.</returns>
  699. public static Color ConvertSRGBToActiveColorSpace(Color color)
  700. {
  701. return (QualitySettings.activeColorSpace == ColorSpace.Linear) ? color.linear : color;
  702. }
  703. /// <summary>
  704. /// Converts the provided linear color to the current active color space.
  705. /// </summary>
  706. /// <param name="color">Input color.</param>
  707. /// <returns>sRGB color if the active color space is ColorSpace.Gamma, the original input otherwise.</returns>
  708. public static Color ConvertLinearToActiveColorSpace(Color color)
  709. {
  710. return (QualitySettings.activeColorSpace == ColorSpace.Linear) ? color : color.gamma;
  711. }
  712. /// <summary>
  713. /// Creates a Material with the provided shader path.
  714. /// hideFlags will be set to HideFlags.HideAndDontSave.
  715. /// </summary>
  716. /// <param name="shaderPath">Path of the shader used for the material.</param>
  717. /// <returns>A new Material instance using the shader found at the provided path.</returns>
  718. public static Material CreateEngineMaterial(string shaderPath)
  719. {
  720. Shader shader = Shader.Find(shaderPath);
  721. if (shader == null)
  722. {
  723. Debug.LogError("Cannot create required material because shader " + shaderPath + " could not be found");
  724. return null;
  725. }
  726. var mat = new Material(shader)
  727. {
  728. hideFlags = HideFlags.HideAndDontSave
  729. };
  730. return mat;
  731. }
  732. /// <summary>
  733. /// Creates a Material with the provided shader.
  734. /// hideFlags will be set to HideFlags.HideAndDontSave.
  735. /// </summary>
  736. /// <param name="shader">Shader used for the material.</param>
  737. /// <returns>A new Material instance using the provided shader.</returns>
  738. public static Material CreateEngineMaterial(Shader shader)
  739. {
  740. if (shader == null)
  741. {
  742. Debug.LogError("Cannot create required material because shader is null");
  743. return null;
  744. }
  745. var mat = new Material(shader)
  746. {
  747. hideFlags = HideFlags.HideAndDontSave
  748. };
  749. return mat;
  750. }
  751. /// <summary>
  752. /// Bitfield flag test.
  753. /// </summary>
  754. /// <typeparam name="T">Type of the enum flag.</typeparam>
  755. /// <param name="mask">Bitfield to test the flag against.</param>
  756. /// <param name="flag">Flag to be tested against the provided mask.</param>
  757. /// <returns>True if the flag is present in the mask.</returns>
  758. public static bool HasFlag<T>(T mask, T flag) where T : IConvertible
  759. {
  760. return (mask.ToUInt32(null) & flag.ToUInt32(null)) != 0;
  761. }
  762. /// <summary>
  763. /// Swaps two values.
  764. /// </summary>
  765. /// <typeparam name="T">Type of the values</typeparam>
  766. /// <param name="a">First value.</param>
  767. /// <param name="b">Second value.</param>
  768. public static void Swap<T>(ref T a, ref T b)
  769. {
  770. var tmp = a;
  771. a = b;
  772. b = tmp;
  773. }
  774. /// <summary>
  775. /// Set a global keyword using a CommandBuffer
  776. /// </summary>
  777. /// <param name="cmd">CommandBuffer on which to set the global keyword.</param>
  778. /// <param name="keyword">Keyword to be set.</param>
  779. /// <param name="state">Value of the keyword to be set.</param>
  780. public static void SetKeyword(CommandBuffer cmd, string keyword, bool state)
  781. {
  782. if (state)
  783. cmd.EnableShaderKeyword(keyword);
  784. else
  785. cmd.DisableShaderKeyword(keyword);
  786. }
  787. // Caution: such a call should not be use interlaced with command buffer command, as it is immediate
  788. /// <summary>
  789. /// Set a keyword immediatly on a Material.
  790. /// </summary>
  791. /// <param name="material">Material on which to set the keyword.</param>
  792. /// <param name="keyword">Keyword to set on the material.</param>
  793. /// <param name="state">Value of the keyword to set on the material.</param>
  794. public static void SetKeyword(Material material, string keyword, bool state)
  795. {
  796. if (state)
  797. material.EnableKeyword(keyword);
  798. else
  799. material.DisableKeyword(keyword);
  800. }
  801. /// <summary>
  802. /// Destroys a UnityObject safely.
  803. /// </summary>
  804. /// <param name="obj">Object to be destroyed.</param>
  805. public static void Destroy(UnityObject obj)
  806. {
  807. if (obj != null)
  808. {
  809. #if UNITY_EDITOR
  810. if (Application.isPlaying)
  811. UnityObject.Destroy(obj);
  812. else
  813. UnityObject.DestroyImmediate(obj);
  814. #else
  815. UnityObject.Destroy(obj);
  816. #endif
  817. }
  818. }
  819. static IEnumerable<Type> m_AssemblyTypes;
  820. /// <summary>
  821. /// Returns all assembly types.
  822. /// </summary>
  823. /// <returns>The list of all assembly types of the current domain.</returns>
  824. public static IEnumerable<Type> GetAllAssemblyTypes()
  825. {
  826. if (m_AssemblyTypes == null)
  827. {
  828. m_AssemblyTypes = AppDomain.CurrentDomain.GetAssemblies()
  829. .SelectMany(t =>
  830. {
  831. // Ugly hack to handle mis-versioned dlls
  832. var innerTypes = new Type[0];
  833. try
  834. {
  835. innerTypes = t.GetTypes();
  836. }
  837. catch {}
  838. return innerTypes;
  839. });
  840. }
  841. return m_AssemblyTypes;
  842. }
  843. /// <summary>
  844. /// Returns a list of types that inherit from the provided type.
  845. /// </summary>
  846. /// <typeparam name="T">Parent Type</typeparam>
  847. /// <returns>A list of types that inherit from the provided type.</returns>
  848. public static IEnumerable<Type> GetAllTypesDerivedFrom<T>()
  849. {
  850. #if UNITY_EDITOR && UNITY_2019_2_OR_NEWER
  851. return UnityEditor.TypeCache.GetTypesDerivedFrom<T>();
  852. #else
  853. return GetAllAssemblyTypes().Where(t => t.IsSubclassOf(typeof(T)));
  854. #endif
  855. }
  856. /// <summary>
  857. /// Safely release a Compute Buffer.
  858. /// </summary>
  859. /// <param name="buffer">Compute Buffer that needs to be released.</param>
  860. public static void SafeRelease(ComputeBuffer buffer)
  861. {
  862. if (buffer != null)
  863. buffer.Release();
  864. }
  865. /// <summary>
  866. /// Creates a cube mesh.
  867. /// </summary>
  868. /// <param name="min">Minimum corner coordinates in local space.</param>
  869. /// <param name="max">Maximum corner coordinates in local space.</param>
  870. /// <returns>A new instance of a cube Mesh.</returns>
  871. public static Mesh CreateCubeMesh(Vector3 min, Vector3 max)
  872. {
  873. Mesh mesh = new Mesh();
  874. Vector3[] vertices = new Vector3[8];
  875. vertices[0] = new Vector3(min.x, min.y, min.z);
  876. vertices[1] = new Vector3(max.x, min.y, min.z);
  877. vertices[2] = new Vector3(max.x, max.y, min.z);
  878. vertices[3] = new Vector3(min.x, max.y, min.z);
  879. vertices[4] = new Vector3(min.x, min.y, max.z);
  880. vertices[5] = new Vector3(max.x, min.y, max.z);
  881. vertices[6] = new Vector3(max.x, max.y, max.z);
  882. vertices[7] = new Vector3(min.x, max.y, max.z);
  883. mesh.vertices = vertices;
  884. int[] triangles = new int[36];
  885. triangles[0] = 0; triangles[1] = 2; triangles[2] = 1;
  886. triangles[3] = 0; triangles[4] = 3; triangles[5] = 2;
  887. triangles[6] = 1; triangles[7] = 6; triangles[8] = 5;
  888. triangles[9] = 1; triangles[10] = 2; triangles[11] = 6;
  889. triangles[12] = 5; triangles[13] = 7; triangles[14] = 4;
  890. triangles[15] = 5; triangles[16] = 6; triangles[17] = 7;
  891. triangles[18] = 4; triangles[19] = 3; triangles[20] = 0;
  892. triangles[21] = 4; triangles[22] = 7; triangles[23] = 3;
  893. triangles[24] = 3; triangles[25] = 6; triangles[26] = 2;
  894. triangles[27] = 3; triangles[28] = 7; triangles[29] = 6;
  895. triangles[30] = 4; triangles[31] = 1; triangles[32] = 5;
  896. triangles[33] = 4; triangles[34] = 0; triangles[35] = 1;
  897. mesh.triangles = triangles;
  898. return mesh;
  899. }
  900. /// <summary>
  901. /// Returns true if "Post Processes" are enabled for the view associated with the given camera.
  902. /// </summary>
  903. /// <param name="camera">Input camera.</param>
  904. /// <returns>True if "Post Processes" are enabled for the view associated with the given camera.</returns>
  905. public static bool ArePostProcessesEnabled(Camera camera)
  906. {
  907. bool enabled = true;
  908. #if UNITY_EDITOR
  909. if (camera.cameraType == CameraType.SceneView)
  910. {
  911. enabled = false;
  912. // Determine whether the "Post Processes" checkbox is checked for the current view.
  913. for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++)
  914. {
  915. var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView;
  916. // Post-processing is disabled in scene view if either showImageEffects is disabled or we are
  917. // rendering in wireframe mode.
  918. if (sv.camera == camera &&
  919. (sv.sceneViewState.showImageEffects && sv.cameraMode.drawMode != UnityEditor.DrawCameraMode.Wireframe))
  920. {
  921. enabled = true;
  922. break;
  923. }
  924. }
  925. }
  926. #endif
  927. return enabled;
  928. }
  929. /// <summary>
  930. /// Returns true if "Animated Materials" are enabled for the view associated with the given camera.
  931. /// </summary>
  932. /// <param name="camera">Input camera.</param>
  933. /// <returns>True if "Animated Materials" are enabled for the view associated with the given camera.</returns>
  934. public static bool AreAnimatedMaterialsEnabled(Camera camera)
  935. {
  936. bool animateMaterials = true;
  937. #if UNITY_EDITOR
  938. animateMaterials = Application.isPlaying; // For Game and VR views; Reflection views pass the parent camera
  939. if (camera.cameraType == CameraType.SceneView)
  940. {
  941. animateMaterials = false;
  942. // Determine whether the "Animated Materials" checkbox is checked for the current view.
  943. for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++) // Using a foreach on an ArrayList generates garbage ...
  944. {
  945. var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView;
  946. if (sv.camera == camera && sv.sceneViewState.showMaterialUpdate)
  947. {
  948. animateMaterials = true;
  949. break;
  950. }
  951. }
  952. }
  953. else if (camera.cameraType == CameraType.Preview)
  954. {
  955. // Enable for previews so the shader graph main preview works with time parameters.
  956. animateMaterials = true;
  957. }
  958. else if (camera.cameraType == CameraType.Reflection)
  959. {
  960. // Reflection cameras should be handled outside this function.
  961. // Debug.Assert(false, "Unexpected View type.");
  962. }
  963. // IMHO, a better solution would be:
  964. // A window invokes a camera render. The camera knows which window called it, so it can query its properies
  965. // (such as animated materials). This camera provides the space-time position. It should also be able
  966. // to access the rendering settings somehow. Using this information, it is then able to construct the
  967. // primary view with information about camera-relative rendering, LOD, time, rendering passes/features
  968. // enabled, etc. We then render this view. It can have multiple sub-views (shadows, reflections).
  969. // They inherit all the properties of the primary view, but also have the ability to override them
  970. // (e.g. primary cam pos and time are retained, matrices are modified, SSS and tessellation are disabled).
  971. // These views can then have multiple sub-views (probably not practical for games),
  972. // which simply amounts to a recursive call, and then the story repeats itself.
  973. //
  974. // TLDR: we need to know the caller and its status/properties to make decisions.
  975. #endif
  976. return animateMaterials;
  977. }
  978. /// <summary>
  979. /// Returns true if "Scene Lighting" is enabled for the view associated with the given camera.
  980. /// </summary>
  981. /// <param name="camera">Input camera.</param>
  982. /// <returns>True if "Scene Lighting" is enabled for the view associated with the given camera.</returns>
  983. public static bool IsSceneLightingDisabled(Camera camera)
  984. {
  985. bool disabled = false;
  986. #if UNITY_EDITOR
  987. if (camera.cameraType == CameraType.SceneView)
  988. {
  989. // Determine whether the "No Scene Lighting" checkbox is checked for the current view.
  990. for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++)
  991. {
  992. var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView;
  993. if (sv.camera == camera && !sv.sceneLighting)
  994. {
  995. disabled = true;
  996. break;
  997. }
  998. }
  999. }
  1000. #endif
  1001. return disabled;
  1002. }
  1003. #if UNITY_EDITOR
  1004. static Func<List<UnityEditor.MaterialEditor>> materialEditors;
  1005. static CoreUtils()
  1006. {
  1007. //quicker than standard reflection as it is compiled
  1008. System.Reflection.FieldInfo field = typeof(UnityEditor.MaterialEditor).GetField("s_MaterialEditors", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
  1009. var fieldExpression = System.Linq.Expressions.Expression.Field(null, field);
  1010. var lambda = System.Linq.Expressions.Expression.Lambda<Func<List<UnityEditor.MaterialEditor>>>(fieldExpression);
  1011. materialEditors = lambda.Compile();
  1012. }
  1013. #endif
  1014. /// <summary>
  1015. /// Returns true if "Fog" is enabled for the view associated with the given camera.
  1016. /// </summary>
  1017. /// <param name="camera">Input camera.</param>
  1018. /// <returns>True if "Fog" is enabled for the view associated with the given camera.</returns>
  1019. public static bool IsSceneViewFogEnabled(Camera camera)
  1020. {
  1021. bool fogEnable = true;
  1022. #if UNITY_EDITOR
  1023. if (camera.cameraType == CameraType.SceneView)
  1024. {
  1025. fogEnable = false;
  1026. // Determine whether the "Animated Materials" checkbox is checked for the current view.
  1027. for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++)
  1028. {
  1029. var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView;
  1030. if (sv.camera == camera && sv.sceneViewState.showFog)
  1031. {
  1032. fogEnable = true;
  1033. break;
  1034. }
  1035. }
  1036. }
  1037. #endif
  1038. return fogEnable;
  1039. }
  1040. }
  1041. }