SvrOverlay.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. public class SvrOverlay : MonoBehaviour, IComparable<SvrOverlay>
  6. {
  7. public static List<SvrOverlay> Instances = new List<SvrOverlay>();
  8. public enum eSide
  9. {
  10. Left = 1,
  11. Right = 2,
  12. Both = 3,
  13. [HideInInspector]
  14. Count = Both
  15. };
  16. public enum eType
  17. {
  18. RenderTexture = 0,
  19. StandardTexture = 1,
  20. EglTexture = 2,
  21. };
  22. public delegate void OnPostRenderCallback(int sideMask, int layerMask);
  23. public OnPostRenderCallback OnPostRenderListener;
  24. public delegate void OnPreRenderCallback(int sideMask, int textureId, int previousId);
  25. public OnPreRenderCallback OnPreRenderListener;
  26. [Tooltip("Layer depth stack")]
  27. public int layerDepth = 0;
  28. [Tooltip("Image display transform")]
  29. public Camera imageCamera;
  30. [Tooltip("Image type: 0/Camera render target, 1/Texture 2d, 2/External egl")]
  31. public eType imageType = eType.RenderTexture;
  32. [Tooltip("Image texture used when ImageType is StandardTexture")]
  33. public Texture imageTexture;
  34. [Tooltip("Image transform for scale, rotation and position (optional)")]
  35. public Transform imageTransform;
  36. [Tooltip("Image display region (camera clip space)")]
  37. public Vector4 clipLowerLeft = new Vector4(-1, -1, 0, 1);
  38. public Vector4 clipUpperLeft = new Vector4(-1, 1, 0, 1);
  39. public Vector4 clipUpperRight = new Vector4(1, 1, 0, 1);
  40. public Vector4 clipLowerRight = new Vector4(1, -1, 0, 1);
  41. [Tooltip("Image source region (texture uv space)")]
  42. public Vector2 uvLowerLeft = new Vector2(0, 0);
  43. public Vector2 uvUpperLeft = new Vector2(0, 1);
  44. public Vector2 uvUpperRight = new Vector2(1, 1);
  45. public Vector2 uvLowerRight = new Vector2(1, 0);
  46. [Tooltip("Side mask")]
  47. public eSide side = eSide.Both;
  48. private RenderTextureFormat format = RenderTextureFormat.Default;
  49. private Vector2 resolution = new Vector2(1920, 1080);
  50. private float resolutionScaleFactor = 1.0f;
  51. private int antiAliasing = 1;
  52. private int depth = 24;
  53. private int frustumType = 0;
  54. private const int bufferCount = 3;
  55. private RenderTexture[] overlayTextures = new RenderTexture[bufferCount];
  56. private int[] overlayTextureIds = new int[bufferCount];
  57. private int currentTextureIndex = 0;
  58. private Camera[] mainCameras = null;
  59. private bool dirty = false;
  60. private Coroutine recreateBuffersCoroutine = null;
  61. public int CompareTo(SvrOverlay that)
  62. {
  63. return this.layerDepth.CompareTo(that.layerDepth);
  64. }
  65. public int FrustumType
  66. {
  67. get { return frustumType; }
  68. set { frustumType = value; }
  69. }
  70. public void SetImage(Texture2D texture)
  71. {
  72. imageTexture = texture;
  73. InitializeBuffers();
  74. }
  75. public eType ImageType
  76. {
  77. get { return imageType; }
  78. set { imageType = value; }
  79. }
  80. public eSide Side
  81. {
  82. get { return side; }
  83. set { side = value; }
  84. }
  85. public RenderTextureFormat Format
  86. {
  87. get { return format; }
  88. set { SetDirty(format != value); format = value; }
  89. }
  90. public int AntiAliasing
  91. {
  92. get { return antiAliasing; }
  93. set { SetDirty(antiAliasing != value); antiAliasing = value; }
  94. }
  95. public int Depth
  96. {
  97. get { return depth; }
  98. set { SetDirty(depth != value); depth = value; }
  99. }
  100. public Vector2 Resolution
  101. {
  102. get { return resolution; }
  103. set { SetDirty(!Mathf.Approximately(resolution.x, value.x) || !Mathf.Approximately(resolution.y, value.y)); resolution = value; }
  104. }
  105. public float ResolutionScaleFactor
  106. {
  107. get { return resolutionScaleFactor; }
  108. set { SetDirty(!Mathf.Approximately(resolutionScaleFactor, value)); resolutionScaleFactor = value; }
  109. }
  110. void SetDirty(bool value)
  111. {
  112. dirty = dirty == true ? true : value;
  113. }
  114. public int TextureId
  115. {
  116. get { return overlayTextureIds[currentTextureIndex]; }
  117. set { overlayTextureIds[currentTextureIndex] = value; }
  118. }
  119. public int PreviousId
  120. {
  121. get { return overlayTextureIds[(currentTextureIndex + bufferCount - 1) % bufferCount]; }
  122. }
  123. public Texture TexturePtr
  124. {
  125. get { return (imageTexture != null ? imageTexture : (Texture)overlayTextures[currentTextureIndex]); }
  126. }
  127. void Awake()
  128. {
  129. Instances.Add(this);
  130. AcquireComponents();
  131. InitializeCoords();
  132. }
  133. void OnDestroy()
  134. {
  135. Instances.Remove(this);
  136. }
  137. void AcquireComponents()
  138. {
  139. if (imageCamera == null) imageCamera = gameObject.GetComponent<Camera>();
  140. Debug.Assert(imageCamera != null, "ImageCamera object required");
  141. mainCameras = imageCamera.GetComponentsInChildren<Camera>();
  142. }
  143. void Start()
  144. {
  145. //Initialize(); Called by SvrManager.InitializeOverlays()
  146. }
  147. void LateUpdate()
  148. {
  149. UpdateCoords();
  150. }
  151. public void Initialize()
  152. {
  153. InitializeBuffers();
  154. InitializeCameras();
  155. }
  156. void InitializeBuffers()
  157. {
  158. for (int i = 0; i < bufferCount; ++i)
  159. {
  160. if (overlayTextures[i] != null)
  161. overlayTextures[i].Release();
  162. switch (imageType)
  163. {
  164. case eType.RenderTexture:
  165. overlayTextures[i] = new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format);
  166. overlayTextures[i].antiAliasing = antiAliasing;
  167. overlayTextures[i].Create();
  168. overlayTextureIds[i] = overlayTextures[i].GetNativeTexturePtr().ToInt32();
  169. //Debug.Log("Create Render Texture with ID: " + overlayTextureIds[i] + " Width: " + overlayTextures[i].width + " Height: " + overlayTextures[i].height + " AA: " + overlayTextures[i].antiAliasing);
  170. break;
  171. case eType.StandardTexture:
  172. if (imageTexture) overlayTextureIds[i] = imageTexture.GetNativeTexturePtr().ToInt32();
  173. break;
  174. case eType.EglTexture:
  175. overlayTextureIds[i] = 0;
  176. break;
  177. }
  178. }
  179. dirty = false;
  180. }
  181. void InitializeCameras()
  182. {
  183. var deviceInfo = SvrPlugin.Instance.deviceInfo;
  184. var deviceFov = new Vector2(deviceInfo.targetFovXRad, deviceInfo.targetFovYRad) * Mathf.Rad2Deg;
  185. var frustum = side == eSide.Right ? deviceInfo.targetFrustumRight : deviceInfo.targetFrustumLeft;
  186. foreach (var mainCamera in mainCameras)
  187. {
  188. mainCamera.fieldOfView = deviceFov.y;
  189. mainCamera.aspect = deviceFov.x / deviceFov.y;
  190. if (frustumType == (int)SvrManager.SvrSettings.eFrustumType.Device)
  191. {
  192. mainCamera.projectionMatrix = SvrManager.Perspective(frustum.left, frustum.right, frustum.bottom, frustum.top, frustum.near, mainCamera.farClipPlane);
  193. }
  194. }
  195. }
  196. void InitializeCoords()
  197. {
  198. //clipLowerLeft.Set(-1, -1, 0, 1);
  199. //clipUpperLeft.Set(-1, 1, 0, 1);
  200. //clipUpperRight.Set(1, 1, 0, 1);
  201. //clipLowerRight.Set(1, -1, 0, 1);
  202. }
  203. void UpdateCoords()
  204. {
  205. if (imageTransform == null)
  206. return;
  207. var viewCamera = mainCameras[0];
  208. if (viewCamera == null)
  209. return;
  210. var extents = 0.5f * Vector3.one;
  211. var center = Vector3.zero;
  212. var worldLowerLeft = new Vector4(center.x - extents.x, center.y - extents.y, 0, 1);
  213. var worldUpperLeft = new Vector4(center.x - extents.x, center.y + extents.y, 0, 1);
  214. var worldUpperRight = new Vector4(center.x + extents.x, center.y + extents.y, 0, 1);
  215. var worldLowerRight = new Vector4(center.x + extents.x, center.y - extents.y, 0, 1);
  216. Matrix4x4 MVP = viewCamera.projectionMatrix * viewCamera.worldToCameraMatrix * imageTransform.localToWorldMatrix;
  217. clipLowerLeft = MVP * worldLowerLeft;
  218. clipUpperLeft = MVP * worldUpperLeft;
  219. clipUpperRight = MVP * worldUpperRight;
  220. clipLowerRight = MVP * worldLowerRight;
  221. }
  222. void OnPreRender()
  223. {
  224. if (imageType != eType.RenderTexture) return;
  225. SwapBuffers();
  226. if (OnPreRenderListener != null)
  227. {
  228. OnPreRenderListener((int)side, TextureId, PreviousId);
  229. }
  230. }
  231. void SwapBuffers()
  232. {
  233. if (imageType != eType.RenderTexture) return;
  234. currentTextureIndex = ++currentTextureIndex % bufferCount;
  235. var targetTexture = overlayTextures[currentTextureIndex];
  236. if (targetTexture == null) return;
  237. for (int i = 0; i < mainCameras.Length; i++)
  238. {
  239. mainCameras[i].targetTexture = targetTexture;
  240. }
  241. targetTexture.DiscardContents();
  242. }
  243. void OnPostRender()
  244. {
  245. RecreateBuffersIfDirty();
  246. if (OnPostRenderListener != null)
  247. {
  248. OnPostRenderListener((int)side, 0x1/*kLayerFlagHeadLocked*/);
  249. }
  250. }
  251. void RecreateBuffersIfDirty()
  252. {
  253. if (dirty)
  254. {
  255. if (recreateBuffersCoroutine != null)
  256. {
  257. StopCoroutine(recreateBuffersCoroutine);
  258. recreateBuffersCoroutine = null;
  259. }
  260. recreateBuffersCoroutine = StartCoroutine(RecreateBuffersDeferred());
  261. dirty = false;
  262. }
  263. }
  264. IEnumerator RecreateBuffersDeferred()
  265. {
  266. int i = 0;
  267. while (i < bufferCount)
  268. {
  269. int index = currentTextureIndex - 1;
  270. index = index >= 0 ? index : bufferCount - 1;
  271. if (overlayTextures[index] != null)
  272. overlayTextures[index].Release();
  273. switch (imageType)
  274. {
  275. case eType.RenderTexture:
  276. overlayTextures[index] = new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format);
  277. overlayTextures[index].antiAliasing = antiAliasing;
  278. overlayTextures[index].Create();
  279. overlayTextureIds[index] = overlayTextures[index].GetNativeTexturePtr().ToInt32();
  280. Debug.Log("Re-create Render Texture with ID: " + overlayTextureIds[index] + " Width: " + overlayTextures[index].width + " Height: " + overlayTextures[index].height + " AA: " + overlayTextures[index].antiAliasing);
  281. break;
  282. case eType.StandardTexture:
  283. if (imageTexture) overlayTextureIds[index] = imageTexture.GetNativeTexturePtr().ToInt32();
  284. break;
  285. case eType.EglTexture:
  286. overlayTextureIds[index] = 0;
  287. break;
  288. }
  289. int prevTextureIndex = currentTextureIndex;
  290. yield return new WaitUntil(() => currentTextureIndex != prevTextureIndex);
  291. i++;
  292. }
  293. yield break;
  294. }
  295. }