OVRCameraComposition.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. using UnityEngine;
  2. using System.Collections;
  3. #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
  4. public abstract class OVRCameraComposition : OVRComposition {
  5. protected GameObject cameraFramePlaneObject;
  6. protected float cameraFramePlaneDistance;
  7. protected readonly bool hasCameraDeviceOpened = false;
  8. protected readonly bool useDynamicLighting = false;
  9. internal readonly OVRPlugin.CameraDevice cameraDevice = OVRPlugin.CameraDevice.WebCamera0;
  10. private OVRCameraRig cameraRig;
  11. private Mesh boundaryMesh = null;
  12. private float boundaryMeshTopY = 0.0f;
  13. private float boundaryMeshBottomY = 0.0f;
  14. private OVRManager.VirtualGreenScreenType boundaryMeshType = OVRManager.VirtualGreenScreenType.Off;
  15. protected OVRCameraComposition(OVRManager.CameraDevice inCameraDevice, bool inUseDynamicLighting, OVRManager.DepthQuality depthQuality)
  16. {
  17. cameraDevice = OVRCompositionUtil.ConvertCameraDevice(inCameraDevice);
  18. Debug.Assert(!hasCameraDeviceOpened);
  19. Debug.Assert(!OVRPlugin.IsCameraDeviceAvailable(cameraDevice) || !OVRPlugin.HasCameraDeviceOpened(cameraDevice));
  20. hasCameraDeviceOpened = false;
  21. useDynamicLighting = inUseDynamicLighting;
  22. bool cameraSupportsDepth = OVRPlugin.DoesCameraDeviceSupportDepth(cameraDevice);
  23. if (useDynamicLighting && !cameraSupportsDepth)
  24. {
  25. Debug.LogWarning("The camera device doesn't support depth. The result of dynamic lighting might not be correct");
  26. }
  27. if (OVRPlugin.IsCameraDeviceAvailable(cameraDevice))
  28. {
  29. OVRPlugin.CameraExtrinsics extrinsics;
  30. OVRPlugin.CameraIntrinsics intrinsics;
  31. if (OVRPlugin.GetExternalCameraCount() > 0 && OVRPlugin.GetMixedRealityCameraInfo(0, out extrinsics, out intrinsics))
  32. {
  33. OVRPlugin.SetCameraDevicePreferredColorFrameSize(cameraDevice, intrinsics.ImageSensorPixelResolution.w, intrinsics.ImageSensorPixelResolution.h);
  34. }
  35. if (useDynamicLighting)
  36. {
  37. OVRPlugin.SetCameraDeviceDepthSensingMode(cameraDevice, OVRPlugin.CameraDeviceDepthSensingMode.Fill);
  38. OVRPlugin.CameraDeviceDepthQuality quality = OVRPlugin.CameraDeviceDepthQuality.Medium;
  39. if (depthQuality == OVRManager.DepthQuality.Low)
  40. {
  41. quality = OVRPlugin.CameraDeviceDepthQuality.Low;
  42. }
  43. else if (depthQuality == OVRManager.DepthQuality.Medium)
  44. {
  45. quality = OVRPlugin.CameraDeviceDepthQuality.Medium;
  46. }
  47. else if (depthQuality == OVRManager.DepthQuality.High)
  48. {
  49. quality = OVRPlugin.CameraDeviceDepthQuality.High;
  50. }
  51. else
  52. {
  53. Debug.LogWarning("Unknown depth quality");
  54. }
  55. OVRPlugin.SetCameraDevicePreferredDepthQuality(cameraDevice, quality);
  56. }
  57. OVRPlugin.OpenCameraDevice(cameraDevice);
  58. if (OVRPlugin.HasCameraDeviceOpened(cameraDevice))
  59. {
  60. hasCameraDeviceOpened = true;
  61. }
  62. }
  63. }
  64. public override void Cleanup()
  65. {
  66. OVRCompositionUtil.SafeDestroy(ref cameraFramePlaneObject);
  67. if (hasCameraDeviceOpened)
  68. {
  69. OVRPlugin.CloseCameraDevice(cameraDevice);
  70. }
  71. }
  72. public override void RecenterPose()
  73. {
  74. boundaryMesh = null;
  75. }
  76. protected void CreateCameraFramePlaneObject(GameObject parentObject, Camera mixedRealityCamera, bool useDynamicLighting)
  77. {
  78. Debug.Assert(cameraFramePlaneObject == null);
  79. cameraFramePlaneObject = GameObject.CreatePrimitive(PrimitiveType.Quad);
  80. cameraFramePlaneObject.name = "MRCameraFrame";
  81. cameraFramePlaneObject.transform.parent = parentObject.transform;
  82. cameraFramePlaneObject.GetComponent<Collider>().enabled = false;
  83. cameraFramePlaneObject.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
  84. Material cameraFrameMaterial = new Material(Shader.Find(useDynamicLighting ? "Oculus/OVRMRCameraFrameLit" : "Oculus/OVRMRCameraFrame"));
  85. cameraFramePlaneObject.GetComponent<MeshRenderer>().material = cameraFrameMaterial;
  86. cameraFrameMaterial.SetColor("_Color", Color.white);
  87. cameraFrameMaterial.SetFloat("_Visible", 0.0f);
  88. cameraFramePlaneObject.transform.localScale = new Vector3(4, 4, 4);
  89. cameraFramePlaneObject.SetActive(true);
  90. OVRCameraFrameCompositionManager cameraFrameCompositionManager = mixedRealityCamera.gameObject.AddComponent<OVRCameraFrameCompositionManager>();
  91. cameraFrameCompositionManager.cameraFrameGameObj = cameraFramePlaneObject;
  92. cameraFrameCompositionManager.composition = this;
  93. }
  94. private bool nullcameraRigWarningDisplayed = false;
  95. protected void UpdateCameraFramePlaneObject(Camera mainCamera, Camera mixedRealityCamera, RenderTexture boundaryMeshMaskTexture)
  96. {
  97. bool hasError = false;
  98. Material cameraFrameMaterial = cameraFramePlaneObject.GetComponent<MeshRenderer>().material;
  99. Texture2D colorTexture = Texture2D.blackTexture;
  100. Texture2D depthTexture = Texture2D.whiteTexture;
  101. if (OVRPlugin.IsCameraDeviceColorFrameAvailable(cameraDevice))
  102. {
  103. colorTexture = OVRPlugin.GetCameraDeviceColorFrameTexture(cameraDevice);
  104. }
  105. else
  106. {
  107. Debug.LogWarning("Camera: color frame not ready");
  108. hasError = true;
  109. }
  110. bool cameraSupportsDepth = OVRPlugin.DoesCameraDeviceSupportDepth(cameraDevice);
  111. if (useDynamicLighting && cameraSupportsDepth)
  112. {
  113. if (OVRPlugin.IsCameraDeviceDepthFrameAvailable(cameraDevice))
  114. {
  115. depthTexture = OVRPlugin.GetCameraDeviceDepthFrameTexture(cameraDevice);
  116. }
  117. else
  118. {
  119. Debug.LogWarning("Camera: depth frame not ready");
  120. hasError = true;
  121. }
  122. }
  123. if (!hasError)
  124. {
  125. Vector3 offset = mainCamera.transform.position - mixedRealityCamera.transform.position;
  126. float distance = Vector3.Dot(mixedRealityCamera.transform.forward, offset);
  127. cameraFramePlaneDistance = distance;
  128. cameraFramePlaneObject.transform.position = mixedRealityCamera.transform.position + mixedRealityCamera.transform.forward * distance;
  129. cameraFramePlaneObject.transform.rotation = mixedRealityCamera.transform.rotation;
  130. float tanFov = Mathf.Tan(mixedRealityCamera.fieldOfView * Mathf.Deg2Rad * 0.5f);
  131. cameraFramePlaneObject.transform.localScale = new Vector3(distance * mixedRealityCamera.aspect * tanFov * 2.0f, distance * tanFov * 2.0f, 1.0f);
  132. float worldHeight = distance * tanFov * 2.0f;
  133. float worldWidth = worldHeight * mixedRealityCamera.aspect;
  134. float cullingDistance = float.MaxValue;
  135. cameraRig = null;
  136. if (OVRManager.instance.virtualGreenScreenType != OVRManager.VirtualGreenScreenType.Off)
  137. {
  138. cameraRig = mainCamera.GetComponentInParent<OVRCameraRig>();
  139. if (cameraRig != null)
  140. {
  141. if (cameraRig.centerEyeAnchor == null)
  142. {
  143. cameraRig = null;
  144. }
  145. }
  146. RefreshBoundaryMesh(mixedRealityCamera, out cullingDistance);
  147. }
  148. cameraFrameMaterial.mainTexture = colorTexture;
  149. cameraFrameMaterial.SetTexture("_DepthTex", depthTexture);
  150. cameraFrameMaterial.SetVector("_FlipParams", new Vector4((OVRManager.instance.flipCameraFrameHorizontally ? 1.0f : 0.0f), (OVRManager.instance.flipCameraFrameVertically ? 1.0f : 0.0f), 0.0f, 0.0f));
  151. cameraFrameMaterial.SetColor("_ChromaKeyColor", OVRManager.instance.chromaKeyColor);
  152. cameraFrameMaterial.SetFloat("_ChromaKeySimilarity", OVRManager.instance.chromaKeySimilarity);
  153. cameraFrameMaterial.SetFloat("_ChromaKeySmoothRange", OVRManager.instance.chromaKeySmoothRange);
  154. cameraFrameMaterial.SetFloat("_ChromaKeySpillRange", OVRManager.instance.chromaKeySpillRange);
  155. cameraFrameMaterial.SetVector("_TextureDimension", new Vector4(colorTexture.width, colorTexture.height, 1.0f / colorTexture.width, 1.0f / colorTexture.height));
  156. cameraFrameMaterial.SetVector("_TextureWorldSize", new Vector4(worldWidth, worldHeight, 0, 0));
  157. cameraFrameMaterial.SetFloat("_SmoothFactor", OVRManager.instance.dynamicLightingSmoothFactor);
  158. cameraFrameMaterial.SetFloat("_DepthVariationClamp", OVRManager.instance.dynamicLightingDepthVariationClampingValue);
  159. cameraFrameMaterial.SetFloat("_CullingDistance", cullingDistance);
  160. if (OVRManager.instance.virtualGreenScreenType == OVRManager.VirtualGreenScreenType.Off || boundaryMesh == null || boundaryMeshMaskTexture == null)
  161. {
  162. cameraFrameMaterial.SetTexture("_MaskTex", Texture2D.whiteTexture);
  163. }
  164. else
  165. {
  166. if (cameraRig == null)
  167. {
  168. if (!nullcameraRigWarningDisplayed)
  169. {
  170. Debug.LogWarning("Could not find the OVRCameraRig/CenterEyeAnchor object. Please check if the OVRCameraRig has been setup properly. The virtual green screen has been temporarily disabled");
  171. nullcameraRigWarningDisplayed = true;
  172. }
  173. cameraFrameMaterial.SetTexture("_MaskTex", Texture2D.whiteTexture);
  174. }
  175. else
  176. {
  177. if (nullcameraRigWarningDisplayed)
  178. {
  179. Debug.Log("OVRCameraRig/CenterEyeAnchor object found. Virtual green screen is activated");
  180. nullcameraRigWarningDisplayed = false;
  181. }
  182. cameraFrameMaterial.SetTexture("_MaskTex", boundaryMeshMaskTexture);
  183. }
  184. }
  185. }
  186. }
  187. protected void RefreshBoundaryMesh(Camera camera, out float cullingDistance)
  188. {
  189. float depthTolerance = OVRManager.instance.virtualGreenScreenApplyDepthCulling ? OVRManager.instance.virtualGreenScreenDepthTolerance : float.PositiveInfinity;
  190. cullingDistance = OVRCompositionUtil.GetMaximumBoundaryDistance(camera, OVRCompositionUtil.ToBoundaryType(OVRManager.instance.virtualGreenScreenType)) + depthTolerance;
  191. if (boundaryMesh == null || boundaryMeshType != OVRManager.instance.virtualGreenScreenType || boundaryMeshTopY != OVRManager.instance.virtualGreenScreenTopY || boundaryMeshBottomY != OVRManager.instance.virtualGreenScreenBottomY)
  192. {
  193. boundaryMeshTopY = OVRManager.instance.virtualGreenScreenTopY;
  194. boundaryMeshBottomY = OVRManager.instance.virtualGreenScreenBottomY;
  195. boundaryMesh = OVRCompositionUtil.BuildBoundaryMesh(OVRCompositionUtil.ToBoundaryType(OVRManager.instance.virtualGreenScreenType), boundaryMeshTopY, boundaryMeshBottomY);
  196. boundaryMeshType = OVRManager.instance.virtualGreenScreenType;
  197. // Creating GameObject for testing purpose only
  198. //GameObject boundaryMeshObject = new GameObject("BoundaryMeshObject");
  199. //boundaryMeshObject.AddComponent<MeshFilter>().mesh = boundaryMesh;
  200. //boundaryMeshObject.AddComponent<MeshRenderer>();
  201. }
  202. }
  203. public class OVRCameraFrameCompositionManager : MonoBehaviour
  204. {
  205. public GameObject cameraFrameGameObj;
  206. public OVRCameraComposition composition;
  207. public RenderTexture boundaryMeshMaskTexture;
  208. private Material cameraFrameMaterial;
  209. private Material whiteMaterial;
  210. void Start()
  211. {
  212. Shader shader = Shader.Find("Oculus/Unlit");
  213. if (!shader)
  214. {
  215. Debug.LogError("Oculus/Unlit shader does not exist");
  216. return;
  217. }
  218. whiteMaterial = new Material(shader);
  219. whiteMaterial.color = Color.white;
  220. }
  221. void OnPreRender()
  222. {
  223. if (OVRManager.instance.virtualGreenScreenType != OVRManager.VirtualGreenScreenType.Off && boundaryMeshMaskTexture != null && composition.boundaryMesh != null)
  224. {
  225. RenderTexture oldRT = RenderTexture.active;
  226. RenderTexture.active = boundaryMeshMaskTexture;
  227. // The camera matrices haven't been setup when OnPreRender() is executed. Load the projection manually
  228. GL.PushMatrix();
  229. GL.LoadProjectionMatrix(GetComponent<Camera>().projectionMatrix);
  230. GL.Clear(false, true, Color.black);
  231. for (int i = 0; i < whiteMaterial.passCount; ++i)
  232. {
  233. if (whiteMaterial.SetPass(i))
  234. {
  235. Graphics.DrawMeshNow(composition.boundaryMesh, composition.cameraRig.ComputeTrackReferenceMatrix());
  236. }
  237. }
  238. GL.PopMatrix();
  239. RenderTexture.active = oldRT;
  240. }
  241. if (cameraFrameGameObj)
  242. {
  243. if (cameraFrameMaterial == null)
  244. cameraFrameMaterial = cameraFrameGameObj.GetComponent<MeshRenderer>().material;
  245. cameraFrameMaterial.SetFloat("_Visible", 1.0f);
  246. }
  247. }
  248. void OnPostRender()
  249. {
  250. if (cameraFrameGameObj)
  251. {
  252. Debug.Assert(cameraFrameMaterial);
  253. cameraFrameMaterial.SetFloat("_Visible", 0.0f);
  254. }
  255. }
  256. }
  257. }
  258. #endif