DisplayIMGUI.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN
  2. #define UNITY_PLATFORM_SUPPORTS_LINEAR
  3. #elif UNITY_IOS || UNITY_ANDROID
  4. #if UNITY_5_5_OR_NEWER || (UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 && !UNITY_5_3 && !UNITY_5_4)
  5. #define UNITY_PLATFORM_SUPPORTS_LINEAR
  6. #endif
  7. #endif
  8. #if UNITY_5_4_OR_NEWER || (UNITY_5 && !UNITY_5_0)
  9. #define UNITY_HELPATTRIB
  10. #endif
  11. using UnityEngine;
  12. //-----------------------------------------------------------------------------
  13. // Copyright 2015-2020 RenderHeads Ltd. All rights reserved.
  14. //-----------------------------------------------------------------------------
  15. namespace RenderHeads.Media.AVProVideo
  16. {
  17. /// <summary>
  18. /// Displays the video from MediaPlayer component using IMGUI
  19. /// </summary>
  20. [AddComponentMenu("AVPro Video/Display IMGUI", 200)]
  21. #if UNITY_HELPATTRIB
  22. [HelpURL("http://renderheads.com/products/avpro-video/")]
  23. #endif
  24. [ExecuteInEditMode]
  25. public class DisplayIMGUI : MonoBehaviour
  26. {
  27. private const string PropChromaTexName = "_ChromaTex";
  28. private const string PropYpCbCrTransformName = "_YpCbCrTransform";
  29. public MediaPlayer _mediaPlayer;
  30. public bool _displayInEditor = true;
  31. public ScaleMode _scaleMode = ScaleMode.ScaleToFit;
  32. public Color _color = Color.white;
  33. public bool _alphaBlend = false;
  34. [SerializeField]
  35. private bool _useDepth = false;
  36. public int _depth = 0;
  37. public bool _fullScreen = true;
  38. [Range(0f, 1f)]
  39. public float _x = 0.0f;
  40. [Range(0f, 1f)]
  41. public float _y = 0.0f;
  42. [Range(0f, 1f)]
  43. public float _width = 1.0f;
  44. [Range(0f, 1f)]
  45. public float _height = 1.0f;
  46. private static int _propAlphaPack;
  47. private static int _propVertScale;
  48. private static int _propApplyGamma;
  49. private static int _propChromaTex;
  50. private static int _propYpCbCrTransform;
  51. private static Shader _shaderAlphaPacking;
  52. private Material _material;
  53. void Awake()
  54. {
  55. if (_propAlphaPack == 0)
  56. {
  57. _propAlphaPack = Shader.PropertyToID("AlphaPack");
  58. _propVertScale = Shader.PropertyToID("_VertScale");
  59. _propApplyGamma = Shader.PropertyToID("_ApplyGamma");
  60. _propChromaTex = Shader.PropertyToID(PropChromaTexName);
  61. _propYpCbCrTransform = Shader.PropertyToID(PropYpCbCrTransformName);
  62. }
  63. }
  64. void Start()
  65. {
  66. // Disabling this lets you skip the GUI layout phase which helps performance, but this also breaks the GUI.depth usage.
  67. if (!_useDepth)
  68. {
  69. this.useGUILayout = false;
  70. }
  71. if (_shaderAlphaPacking == null)
  72. {
  73. _shaderAlphaPacking = Shader.Find("AVProVideo/IMGUI/Texture Transparent");
  74. if (_shaderAlphaPacking == null)
  75. {
  76. Debug.LogWarning("[AVProVideo] Missing shader AVProVideo/IMGUI/Transparent Packed");
  77. }
  78. }
  79. }
  80. void OnDestroy()
  81. {
  82. // Destroy existing material
  83. if (_material != null)
  84. {
  85. #if UNITY_EDITOR
  86. Material.DestroyImmediate(_material);
  87. #else
  88. Material.Destroy(_material);
  89. #endif
  90. _material = null;
  91. }
  92. }
  93. private Shader GetRequiredShader()
  94. {
  95. Shader result = null;
  96. switch (_mediaPlayer.m_AlphaPacking)
  97. {
  98. case AlphaPacking.None:
  99. break;
  100. case AlphaPacking.LeftRight:
  101. case AlphaPacking.TopBottom:
  102. result = _shaderAlphaPacking;
  103. break;
  104. }
  105. #if UNITY_PLATFORM_SUPPORTS_LINEAR
  106. if (result == null && _mediaPlayer.Info != null)
  107. {
  108. // If the player does support generating sRGB textures then we need to use a shader to convert them for display via IMGUI
  109. if (QualitySettings.activeColorSpace == ColorSpace.Linear && !_mediaPlayer.Info.PlayerSupportsLinearColorSpace())
  110. {
  111. result = _shaderAlphaPacking;
  112. }
  113. }
  114. #endif
  115. if (result == null && _mediaPlayer.TextureProducer != null)
  116. {
  117. if (_mediaPlayer.TextureProducer.GetTextureCount() == 2)
  118. {
  119. result = _shaderAlphaPacking;
  120. }
  121. }
  122. return result;
  123. }
  124. void Update()
  125. {
  126. if (_mediaPlayer != null)
  127. {
  128. // Get required shader
  129. Shader currentShader = null;
  130. if (_material != null)
  131. {
  132. currentShader = _material.shader;
  133. }
  134. Shader nextShader = GetRequiredShader();
  135. // If the shader requirement has changed
  136. if (currentShader != nextShader)
  137. {
  138. // Destroy existing material
  139. if (_material != null)
  140. {
  141. #if UNITY_EDITOR
  142. Material.DestroyImmediate(_material);
  143. #else
  144. Material.Destroy(_material);
  145. #endif
  146. _material = null;
  147. }
  148. // Create new material
  149. if (nextShader != null)
  150. {
  151. _material = new Material(nextShader);
  152. }
  153. }
  154. // Apply material changes
  155. if (_material != null)
  156. {
  157. if (_material.HasProperty(_propAlphaPack))
  158. {
  159. Helper.SetupAlphaPackedMaterial(_material, _mediaPlayer.m_AlphaPacking);
  160. }
  161. #if UNITY_PLATFORM_SUPPORTS_LINEAR
  162. // Apply gamma
  163. if (_material.HasProperty(_propApplyGamma) && _mediaPlayer.Info != null)
  164. {
  165. Helper.SetupGammaMaterial(_material, _mediaPlayer.Info.PlayerSupportsLinearColorSpace());
  166. }
  167. #else
  168. _propApplyGamma |= 0;
  169. #endif
  170. }
  171. }
  172. }
  173. void OnGUI()
  174. {
  175. #if UNITY_EDITOR
  176. if (!Application.isPlaying && _displayInEditor)
  177. {
  178. GUI.depth = _depth;
  179. GUI.color = _color;
  180. Rect rect = GetRect();
  181. Texture2D icon = Resources.Load<Texture2D>("AVProVideoIcon");
  182. Rect uv = rect;
  183. uv.x /= Screen.width;
  184. uv.width /= Screen.width;
  185. uv.y /= Screen.height;
  186. uv.height /= Screen.height;
  187. uv.width *= 16f;
  188. uv.height *= 16f;
  189. uv.x += 0.5f;
  190. uv.y += 0.5f;
  191. GUI.DrawTextureWithTexCoords(rect, icon, uv);
  192. return;
  193. }
  194. #endif
  195. if (_mediaPlayer == null)
  196. {
  197. return;
  198. }
  199. bool requiresVerticalFlip = false;
  200. Texture texture = null;
  201. if (_displayInEditor)
  202. {
  203. #if UNITY_EDITOR
  204. texture = Texture2D.whiteTexture;
  205. #endif
  206. }
  207. if (_mediaPlayer.Info != null && !_mediaPlayer.Info.HasVideo())
  208. {
  209. texture = null;
  210. }
  211. if (_mediaPlayer.TextureProducer != null)
  212. {
  213. if (_mediaPlayer.m_Resample)
  214. {
  215. if (_mediaPlayer.FrameResampler.OutputTexture != null && _mediaPlayer.FrameResampler.OutputTexture[0] != null)
  216. {
  217. texture = _mediaPlayer.FrameResampler.OutputTexture[0];
  218. requiresVerticalFlip = _mediaPlayer.TextureProducer.RequiresVerticalFlip();
  219. }
  220. }
  221. else
  222. {
  223. if (_mediaPlayer.TextureProducer.GetTexture() != null)
  224. {
  225. texture = _mediaPlayer.TextureProducer.GetTexture();
  226. requiresVerticalFlip = _mediaPlayer.TextureProducer.RequiresVerticalFlip();
  227. }
  228. }
  229. if (_mediaPlayer.TextureProducer.GetTextureCount() == 2 && _material != null)
  230. {
  231. Texture resamplerTex = _mediaPlayer.FrameResampler == null || _mediaPlayer.FrameResampler.OutputTexture == null ? null : _mediaPlayer.FrameResampler.OutputTexture[1];
  232. Texture chroma = _mediaPlayer.m_Resample ? resamplerTex : _mediaPlayer.TextureProducer.GetTexture(1);
  233. _material.SetTexture(_propChromaTex, chroma);
  234. _material.SetMatrix(_propYpCbCrTransform, _mediaPlayer.TextureProducer.GetYpCbCrTransform());
  235. _material.EnableKeyword("USE_YPCBCR");
  236. }
  237. }
  238. if (texture != null)
  239. {
  240. if (!_alphaBlend || _color.a > 0f)
  241. {
  242. GUI.depth = _depth;
  243. GUI.color = _color;
  244. Rect rect = GetRect();
  245. if (_material != null)
  246. {
  247. if (requiresVerticalFlip)
  248. {
  249. _material.SetFloat(_propVertScale, -1f);
  250. }
  251. else
  252. {
  253. _material.SetFloat(_propVertScale, 1f);
  254. }
  255. #if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
  256. if (QualitySettings.activeColorSpace == ColorSpace.Linear && !GL.sRGBWrite)
  257. {
  258. // It seems that Graphics.Draw texture behaves differently than GUI.DrawTexture when it comes to sRGB writing
  259. // on newer versions of Unity (at least 2018.2.19 and above), so now we have to force the conversion to sRGB on writing
  260. GL.sRGBWrite = true;
  261. Helper.DrawTexture(rect, texture, _scaleMode, _mediaPlayer.m_AlphaPacking, _material);
  262. GL.sRGBWrite = false;
  263. }
  264. else
  265. {
  266. Helper.DrawTexture(rect, texture, _scaleMode, _mediaPlayer.m_AlphaPacking, _material);
  267. }
  268. #else
  269. Helper.DrawTexture(rect, texture, _scaleMode, _mediaPlayer.m_AlphaPacking, _material);
  270. #endif
  271. }
  272. else
  273. {
  274. if (requiresVerticalFlip)
  275. {
  276. GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0f, rect.y + (rect.height / 2f)));
  277. }
  278. GUI.DrawTexture(rect, texture, _scaleMode, _alphaBlend);
  279. }
  280. }
  281. }
  282. }
  283. public Rect GetRect()
  284. {
  285. Rect rect;
  286. if (_fullScreen)
  287. {
  288. rect = new Rect(0.0f, 0.0f, Screen.width, Screen.height);
  289. }
  290. else
  291. {
  292. rect = new Rect(_x * (Screen.width - 1), _y * (Screen.height - 1), _width * Screen.width, _height * Screen.height);
  293. }
  294. return rect;
  295. }
  296. }
  297. }