Tilt Five™ Unity API  1.3.0
 
Loading...
Searching...
No Matches
SplitStereoCamera.cs
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020-2022 Tilt Five, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17using System.Collections;
18using System.Collections.Generic;
19using UnityEngine;
21
22#if TILT_FIVE_SRP
23using UnityEngine.Rendering;
24#endif
25
27
28namespace TiltFive
29{
30
34 [System.Serializable]
35 public class DisplaySettings
36 {
37 private static DisplaySettings instance;
39 {
40 get
41 {
42 if(instance == null)
43 {
45 }
46 return instance;
47 }
48 set => instance = value;
49 }
50
52 {
54 {
55 Log.Warn("Could not retrieve display settings from the plugin.");
56 }
57 }
58
60 public static int monoWidth => (stereoWidth / 2);
62 public static int stereoWidth => Instance.defaultDimensions.x;
64 public static int height => Instance.defaultDimensions.y;
66 public static float monoWidthToHeightRatio => (float) monoWidth / height;
68 public static float stereoWidthToHeightRatio => (float) stereoWidth / height;
70 public const int depthBuffer = 24;
71
72 // Provide a texture format compatible with the glasses.
73 public const RenderTextureFormat nativeTextureFormat = RenderTextureFormat.ARGB32;
74
75 // Provide a hardcoded default resolution if the plugin is somehow unavailable.
76 private readonly Vector2Int defaultDimensions = new Vector2Int(2432, 768);
77 }
78
79 [RequireComponent(typeof(Camera))]
80 public partial class SplitStereoCamera : MonoBehaviour
81 {
82 [HideInInspector]
83 internal GlassesHandle glassesHandle;
84
85 internal SpectatorSettings spectatorSettings = null;
86 private Camera spectatorCamera => spectatorSettings?.spectatorCamera;
87
88 internal GlassesSettings glassesSettings = null;
90 public Camera cameraTemplate => glassesSettings?.cameraTemplate;
92 public GameObject headPose = null;
93 private bool useSpectatorCamera;
94 internal bool UseSpectatorCamera
95 {
96 get => useSpectatorCamera;
97 set
98 {
99 if (useSpectatorCamera != value)
100 {
101 // If we set a new value here, force the letterboxing/pillarboxing to be redrawn.
103 }
104 useSpectatorCamera = value;
105 }
106 }
108
109 private IEnumerator presentStereoImagesCoroutine;
110
112 private const string LEFT_EYE_CAMERA_NAME = "Left Eye Camera";
114 private GameObject leftEye;
116 public Camera leftEyeCamera { get { return eyeCameras[AREyes.EYE_LEFT]; } }
117
119 private const string RIGHT_EYE_CAMERA_NAME = "Right Eye Camera";
121 private GameObject rightEye;
123 public Camera rightEyeCamera { get { return eyeCameras[AREyes.EYE_RIGHT]; } }
124
126 public bool showCameras = true;
128 private Dictionary<AREyes, Camera> eyeCameras = new Dictionary<AREyes, Camera>()
129 {
130 { AREyes.EYE_LEFT, null },
131 { AREyes.EYE_RIGHT, null }
132 };
133
138 public Vector3 posUGBD_UWRLD = Vector3.zero;
139
144 public Quaternion rotToUGBD_UWRLD = Quaternion.identity;
145
150 public float scaleToUGBD_UWRLD = 1.0f;
151
153 private const string SHADER_DISPLAY_BLIT = "Tilt Five/Simple Blend Shader";
155 private Material displayBlitShader;
156
160
161#if TILT_FIVE_SRP
162 private CommandBuffer commandBuffer;
163#endif
164
166 [System.Obsolete("fieldOfView is deprecated, please use GlassesSettings' fieldOfView instead.")]
167 public float fieldOfView
168 {
169 get { return spectatorCamera.fieldOfView; }
170 set { rightEyeCamera.fieldOfView = leftEyeCamera.fieldOfView = spectatorCamera.fieldOfView = value; }
171 }
172
174 [System.Obsolete("nearClipPlane is deprecated, please use GlassesSettings' nearClipPlane instead.")]
175 public float nearClipPlane
176 {
177 get { return spectatorCamera.nearClipPlane; }
178 set { rightEyeCamera.nearClipPlane = leftEyeCamera.nearClipPlane = spectatorCamera.nearClipPlane = value; }
179 }
180
182 [System.Obsolete("farClipPlane is deprecated, please use GlassesSettings' farClipPlane instead.")]
183 public float farClipPlane
184 {
185 get { return spectatorCamera.farClipPlane; }
186 set { rightEyeCamera.farClipPlane = leftEyeCamera.farClipPlane = spectatorCamera.farClipPlane = value; }
187 }
188
190 [System.Obsolete("aspectRatio is deprecated, please use DisplaySettings.monoWidthToHeightRatio instead.")]
191 public float aspectRatio
192 {
193 get { return spectatorCamera.aspect; }
194 set { spectatorCamera.aspect = value; }
195 }
196
200 private void Awake()
201 {
202 enabled = false;
203 useSpectatorCamera = false;
205 }
206
207 public void Initialize(GameObject headPoseRoot, GlassesSettings glassesSettings, SpectatorSettings spectatorSettings)
208 {
209 if(headPoseRoot == null || spectatorSettings == null)
210 {
211 Log.Error("Arguments cannot be null");
212 return;
213 }
214
215 headPose = headPoseRoot;
216 this.glassesSettings = glassesSettings;
217 this.spectatorSettings = spectatorSettings;
218
219#if TILT_FIVE_SRP
220 commandBuffer = new CommandBuffer() { name = "Onscreen Preview" };
221#endif
222
223 // For this mode, we need the headPose Camera to be enabled, as it is the
224 // primary Camera for blitting to the backbuffer.
225 if(spectatorCamera != null)
226 {
227 spectatorCamera.enabled = true;
228 }
229
230 if(cameraTemplate != null)
231 {
233 }
234 else
235 {
237 }
239
240 // Load the blitting shader to copy the the left & right render textures
241 // into the backbuffer
242 displayBlitShader = new Material(Shader.Find(SHADER_DISPLAY_BLIT));
243 // Did we find it?
244 if (null == displayBlitShader)
245 {
246 Log.Error("Failed to load Shader '{0}'", SHADER_DISPLAY_BLIT);
247 }
248
249 SyncFields();
252
253 enabled = true;
254 }
255
256 private void InstantiateEyeCameras(out GameObject leftEye, out GameObject rightEye)
257 {
258 var cloneCameraTemplateChildren = glassesSettings.cloneCameraTemplateChildren;
259
260 // When we clone the head pose camera using Instantiate, we may not want to clone its children.
261 // If this is the case, detach the children and reparent them under a placeholder/babysitter GameObject
262 GameObject placeholder = cloneCameraTemplateChildren ? null : new GameObject("Placeholder");
263 if (!cloneCameraTemplateChildren)
264 {
265 placeholder.transform.parent = headPose.transform.parent;
266 while (cameraTemplate.transform.childCount > 0)
267 {
268 cameraTemplate.transform.GetChild(0).parent = placeholder.transform;
269 }
270 }
271
272 // Instantiate left and right eye cameras from the camera template.
273 leftEye = Instantiate(cameraTemplate.gameObject, headPose.transform.position, headPose.transform.rotation, headPose.transform);
274 leftEye.name = LEFT_EYE_CAMERA_NAME;
275 eyeCameras[AREyes.EYE_LEFT] = leftEye.GetComponent<Camera>();
276
277 rightEye = Instantiate(cameraTemplate.gameObject, headPose.transform.position, headPose.transform.rotation, headPose.transform);
278 rightEye.name = RIGHT_EYE_CAMERA_NAME;
279 eyeCameras[AREyes.EYE_RIGHT] = rightEye.GetComponent<Camera>();
280
281 var splitStereoCamerasLeft = leftEye.GetComponents<SplitStereoCamera>();
282 for (int i = 0; i < splitStereoCamerasLeft.Length; i++)
283 {
284 Destroy(splitStereoCamerasLeft[i]);
285 }
286
287 var splitStereoCamerasRight = rightEye.GetComponents<SplitStereoCamera>();
288 for (int i = 0; i < splitStereoCamerasRight.Length; i++)
289 {
290 Destroy(splitStereoCamerasRight[i]);
291 }
292
293
294 if (!cloneCameraTemplateChildren)
295 {
296 // Reclaim the head pose camera's children from the placeholder/babysitter GameObject
297 while (placeholder.transform.childCount > 0)
298 {
299 placeholder.transform.GetChild(0).parent = cameraTemplate.transform;
300 }
301 Destroy(placeholder);
302 }
303 }
304
305 private void GenerateEyeCameras(out GameObject leftEye, out GameObject rightEye)
306 {
307 leftEye = new GameObject(LEFT_EYE_CAMERA_NAME, typeof(Camera));
308 rightEye = new GameObject(RIGHT_EYE_CAMERA_NAME, typeof(Camera));
309
310 eyeCameras[AREyes.EYE_LEFT] = leftEye.GetComponent<Camera>();
311 eyeCameras[AREyes.EYE_RIGHT] = rightEye.GetComponent<Camera>();
312
313 leftEye.transform.parent = headPose.transform;
314 rightEye.transform.parent = headPose.transform;
315
316 leftEye.transform.SetPositionAndRotation(headPose.transform.position, headPose.transform.rotation);
317 rightEye.transform.SetPositionAndRotation(headPose.transform.position, headPose.transform.rotation);
318 }
319
320 private void ConfigureEyeCameras()
321 {
322 // Use the head pose camera's preferred texture format, rather than forcing it to render in LDR
324
325 // Configure the left eye camera's render target
326 RenderTexture leftTex = splitStereoTextures.LeftTexture_GLS;
327 if (leftEyeCamera.allowMSAA && QualitySettings.antiAliasing > 1)
328 {
329 leftTex.antiAliasing = QualitySettings.antiAliasing;
330
331 // Ensure that the preview textures' antiAliasing settings match.
332 // Otherwise, Unity 2020.3 complains during Graphics.CopyTexture about the mismatch,
333 // resulting in a broken onscreen preview (manifesting as a black screen).
334 splitStereoTextures.MonoPreviewTex.antiAliasing = QualitySettings.antiAliasing;
335 splitStereoTextures.StereoPreviewTex.antiAliasing = QualitySettings.antiAliasing;
336 }
337
338 leftEyeCamera.targetTexture = leftTex;
339 leftEyeCamera.depth = spectatorCamera.depth - 1;
340
341 // Configure the right eye camera's render target
342 RenderTexture rightTex = splitStereoTextures.RightTexture_GLS;
343 if (rightEyeCamera.allowMSAA && QualitySettings.antiAliasing > 1)
344 {
345 rightTex.antiAliasing = QualitySettings.antiAliasing;
346 }
347
348 rightEyeCamera.targetTexture = rightTex;
349 rightEyeCamera.depth = spectatorCamera.depth - 1;
350 }
351
357 {
358
359#if UNITY_EDITOR
360 // We move the eye Cameras in the Editor to emulate head pose and eye movement.
361 // In builds, we only set the camera transforms with Glasses tracking data.
362
363 if (null == cameraTemplate)
364 return;
365
366 if (!Glasses.updated)
367 {
368 GameObject pose = headPose;
369 // left eye copy and adjust
370 leftEye.transform.position = pose.transform.position;
371 leftEye.transform.localPosition = pose.transform.localPosition;
372 leftEye.transform.rotation = pose.transform.rotation;
373 leftEye.transform.localRotation = pose.transform.localRotation;
374 leftEye.transform.localScale = pose.transform.localScale;
375 leftEye.transform.Translate(-leftEye.transform.right.normalized * (cameraTemplate.stereoSeparation * 0.5f));
376
377 //right eye copy and adjust
378 rightEye.transform.position = pose.transform.position;
379 rightEye.transform.localPosition = pose.transform.localPosition;
380 rightEye.transform.rotation = pose.transform.rotation;
381 rightEye.transform.localRotation = pose.transform.localRotation;
382 rightEye.transform.localScale = headPose.transform.localScale;
383 rightEye.transform.Translate(rightEye.transform.right.normalized * (cameraTemplate.stereoSeparation * 0.5f));
384 }
385#endif
386 }
387
388 void OnEnable()
389 {
390 leftEye.SetActive(true);
391 rightEye.SetActive(true);
392 leftEyeCamera.enabled = true;
393 rightEyeCamera.enabled = true;
395 StartCoroutine(presentStereoImagesCoroutine);
396
397#if TILT_FIVE_SRP
398 if(Application.isPlaying)
399 {
400 RenderPipelineManager.beginFrameRendering += OnBeginFrameRendering;
401 RenderPipelineManager.endFrameRendering += OnEndFrameRendering;
402 }
403#endif
404 }
405
406 private void OnDisable()
407 {
409 {
411 // If OnDisable() is being called from Destroy(), then the children may no longer
412 // exist. Check before acting on them.
413 if (leftEye)
414 {
415 leftEye.SetActive(false);
416 leftEyeCamera.enabled = false;
417 }
418 if (rightEye)
419 {
420 rightEye.SetActive(false);
421 rightEyeCamera.enabled = false;
422 }
423 }
424
426 {
427 StopCoroutine(presentStereoImagesCoroutine);
428 }
429#if TILT_FIVE_SRP
430 RenderPipelineManager.beginFrameRendering -= OnBeginFrameRendering;
431 RenderPipelineManager.endFrameRendering -= OnEndFrameRendering;
432#endif
433 }
434
435#if TILT_FIVE_SRP
440 private void OnBeginFrameRendering(ScriptableRenderContext context, Camera[] cameras)
441 {
442 // TODO: Determine whether this is necessary, or even permitted; the docs on RenderTexture.IsCreated() are lacking.
443 // We want to check for invalidated render textures before rendering,
444 // and this event should occur at the beginning of RenderPipeline.Render
445 // before any actual render passes occur, so in principle this should work as a substitute for OnPreRender.
446
447 // Check whether the left/right render textures' states have been invalidated,
448 // and reset the cached texture handles if so. See the longer explanation below in Update()
450 }
451#endif
452
457 {
459
460 if(!UseSpectatorCamera)
461 {
462 return;
463 }
464
465 spectatorCamera.targetTexture = null;
466
467 /* If the screen mirror mode changes, junk data will be displayed
468 * in the black bars unless we clear the screen buffer.
469 *
470 * This has to be done before we adjust the headpose camera rect,
471 * since GL.Clear's effect is limited by the active viewport.
472 *
473 * We also must ensure that we call GL.Clear once as soon as we begin mirroring to the screen.
474 * See Gerrit #3013 for additional detail, but in short, there's an implicit mirror mode transition
475 * at the moment we begin mirroring to the onscreen preview that isn't captured by comparing
476 * glassesMirrorMode against previousMirrorMode, and if we don't check for it using the
477 * startedMirroringToOnscreenPreview flag, junk data could fill the letterboxing/pillarboxing.*/
479 {
480 // Before calling GL.Clear(), we need to reset the viewport.
481 // Otherwise, we may not clear the entire screen in some cases.
482 GL.Viewport(spectatorCamera.pixelRect);
483 GL.Clear(true, true, Color.black);
486 }
487
489 {
490 return;
491 }
492
493 spectatorCamera.cullingMask = 0; // Cull all layers, render nothing.
494 spectatorCamera.fieldOfView = glassesSettings.fieldOfView;
495 spectatorCamera.nearClipPlane = glassesSettings.nearClipPlane / scaleToUGBD_UWRLD;
496 spectatorCamera.farClipPlane = glassesSettings.farClipPlane / scaleToUGBD_UWRLD;
497
498 // Lock the aspect ratio and add pillarboxing/letterboxing as needed.
499 float screenRatio = Screen.width / (float)Screen.height;
500 float targetRatio = glassesMirrorMode == GlassesMirrorMode.Stereoscopic
503
504 if(screenRatio > targetRatio) {
505 // Screen or window is wider than the target: pillarbox.
506 float normalizedWidth = targetRatio / screenRatio;
507 float barThickness = (1f - normalizedWidth) / 2f;
508 spectatorCamera.rect = new Rect(barThickness, 0, normalizedWidth, 1);
509 }
510 else {
511 // Screen or window is narrower than the target: letterbox.
512 float normalizedHeight = screenRatio / targetRatio;
513 float barThickness = (1f - normalizedHeight) / 2f;
514 spectatorCamera.rect = new Rect(0, barThickness, 1, normalizedHeight);
515 }
516 }
517
518
519#if TILT_FIVE_SRP
526 void OnEndFrameRendering(ScriptableRenderContext context, Camera[] cameras)
527 {
528 if (this == null || !enabled || glassesMirrorMode == GlassesMirrorMode.None || !UseSpectatorCamera)
529 {
530 spectatorCamera.rect = spectatorSettings.rect;
531 return;
532 }
533
534 // OnEndFrameRendering isn't picky about the camera(s) that finished rendering.
535 // This includes the scene view and/or material preview cameras.
536 // We need to make sure we only run the code in this function when we're performing stereoscopic rendering.
537 bool currentlyRenderingEyeCameras = false;
538
539 for (int i = 0; i < cameras.Length; i++)
540 {
541#if UNITY_EDITOR
542 if (cameras[i].Equals(UnityEditor.SceneView.lastActiveSceneView.camera))
543 {
544 return;
545 }
546#endif
547 if (cameras[i].Equals(leftEyeCamera) || cameras[i].Equals(rightEyeCamera) || cameras[i].Equals(spectatorCamera))
548 {
549 currentlyRenderingEyeCameras = true;
550 }
551 }
552 if (!currentlyRenderingEyeCameras)
553 {
554 return;
555 }
556
557 // Determine the aspect ratio to enable pillarboxing/letterboxing.
558 float screenRatio = Screen.width / (float)Screen.height;
559 float targetRatio = glassesMirrorMode == GlassesMirrorMode.Stereoscopic
562 Vector2 frameScale = Vector2.one;
563
564 if (screenRatio != targetRatio)
565 {
566 frameScale = screenRatio > targetRatio
567 ? new Vector2(screenRatio / targetRatio, 1f)
568 : new Vector2(1f, targetRatio / screenRatio);
569 }
570
571 splitStereoTextures.SubmitPreviewTexturesSRP(glassesMirrorMode, spectatorCamera, commandBuffer, frameScale);
572
573 context.ExecuteCommandBuffer(commandBuffer);
574 context.Submit();
575 commandBuffer.Clear();
576
577 spectatorSettings.ResetSpectatorCamera();
578 }
579#endif
580
587 void OnRenderImage(RenderTexture src, RenderTexture dst)
588 {
589 // If we're not supposed to spectate due to the spectated player being set to None
590 // or to a player that isn't connected, have the first SplitStereoCamera attached to
591 // the SpectatorCamera perform a blit.
592 // TODO: Consider adding a spectator setting to define fallback behavior when the specified player isn't connected.
593 // The current behavior is indistinguishable from the PlayerIndex.None case, and perhaps it'd be desirable
594 // to spectate the next available player instead, if there is one?
595 if (spectatorSettings.spectatedPlayer == PlayerIndex.None || !Player.IsConnected(spectatorSettings.spectatedPlayer))
596 {
597 var splitStereoCameras = spectatorCamera.GetComponents<SplitStereoCamera>();
598 if(splitStereoCameras != null && splitStereoCameras.Length > 0 // These two checks should be redundant
599 && splitStereoCameras[0].Equals(this)) // This is the important one
600 {
601 Graphics.Blit(src, null as RenderTexture);
602 return;
603 }
604 // Any SplitStereoCameras that call OnRenderImage after the first one should return, otherwise they'll clear the screen
605 return;
606 }
607
608 if(!UseSpectatorCamera)
609 {
610 return;
611 }
612
614 {
616
617 var previewTex = glassesMirrorMode == GlassesMirrorMode.Stereoscopic
618 ? splitStereoTextures.StereoPreviewTex
620
621 // Blitting is required when overriding OnRenderImage().
622 // Setting the blit destination to null is the same as blitting to the screen backbuffer.
623 // This will effectively render previewTex to the screen.
624 Graphics.Blit(previewTex,
625 null as RenderTexture,
626 Vector2.one,
627 Vector2.zero);
628 }
629 else Graphics.Blit(src, null as RenderTexture);
630
631 // We're done with our letterboxing/pillarboxing now that we've blitted to the screen.
632 // If the SplitStereoCamera gets disabled next frame, ensure that the original behavior returns.
633 spectatorSettings.ResetSpectatorCamera();
634 }
635
637 {
638 // WaitForEndOfFrame() will let us wait until the last possible moment to send frames to the glasses.
639 // This allows the results of rendering, postprocessing, and even GUI to be displayed.
640 var cachedWaitForEndOfFrame = new WaitForEndOfFrame();
641
642 while (enabled)
643 {
644 yield return cachedWaitForEndOfFrame;
645
647 }
648 }
649
650 private void PresentStereoImages()
651 {
652 splitStereoTextures.GetNativeTexturePointers(out var leftTexHandle, out var rightTexHandle);
653
654 var leftTargetTex = splitStereoTextures.LeftTexture_GLS;
655 var rightTargetTex = splitStereoTextures.RightTexture_GLS;
656
657 bool isSrgb = leftTargetTex.sRGB;
658
659 Vector3 posOfULVC_UWRLD = leftEyeCamera.transform.position;
660 Quaternion rotToUWRLD_ULVC = leftEyeCamera.transform.rotation;
661 Vector3 posOfURVC_UWRLD = rightEyeCamera.transform.position;
662 Quaternion rotToUWRLD_URVC = rightEyeCamera.transform.rotation;
663
664 Vector3 posOfULVC_UGBD = rotToUGBD_UWRLD * (scaleToUGBD_UWRLD * (posOfULVC_UWRLD - posUGBD_UWRLD));
665 Quaternion rotToUGBD_ULVC = rotToUGBD_UWRLD * rotToUWRLD_ULVC;
666
667 Vector3 posOfURVC_UGBD = rotToUGBD_UWRLD * (scaleToUGBD_UWRLD * (posOfURVC_UWRLD - posUGBD_UWRLD));
668 Quaternion rotToUGBD_URVC = rotToUGBD_UWRLD * rotToUWRLD_URVC;
669
670
671 Display.PresentStereoImages(glassesHandle,
672 leftTexHandle, rightTexHandle,
673 leftTargetTex.width, rightTargetTex.height,
674 isSrgb,
675 glassesSettings.fieldOfView,
677 rotToUGBD_ULVC,
678 posOfULVC_UGBD,
679 rotToUGBD_URVC,
680 posOfURVC_UGBD);
681 }
682
686 private void SyncFields()
687 {
688 if (glassesSettings == null)
689 {
690 return;
691 }
692 if (leftEyeCamera != null)
693 {
694 leftEyeCamera.fieldOfView = glassesSettings.fieldOfView;
695 leftEyeCamera.nearClipPlane = glassesSettings.nearClipPlane;
696 leftEyeCamera.farClipPlane = glassesSettings.farClipPlane;
697 leftEyeCamera.aspect = DisplaySettings.monoWidthToHeightRatio;
698 }
699 if (rightEyeCamera != null)
700 {
701 rightEyeCamera.fieldOfView = glassesSettings.fieldOfView;
702 rightEyeCamera.nearClipPlane = glassesSettings.nearClipPlane;
703 rightEyeCamera.farClipPlane = glassesSettings.farClipPlane;
704 rightEyeCamera.aspect = DisplaySettings.monoWidthToHeightRatio;
705 }
706 }
707
712 {
713
714#if UNITY_EDITOR
715 if (false == UnityEditor.EditorApplication.isPlaying)
716 return;
717#endif
718 if (null == spectatorCamera)
719 return;
720
721 if (null != leftEye && null != rightEye)
723
724 SyncFields();
726 }
727
732 {
733 if (showCameras)
734 {
735 leftEye.hideFlags = HideFlags.None;
736 rightEye.hideFlags = HideFlags.None;
737 }
738 else
739 {
740 leftEye.hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy;
741 rightEye.hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy;
742 }
743 }
744 }
745}
TiltFive.Glasses.AREyes AREyes
static bool GetDisplayDimensions(ref Vector2Int displayDimensions)
Definition: Display.cs:372
static bool PresentStereoImages(PlayerIndex playerIndex, IntPtr leftTexHandle, IntPtr rightTexHandle, int texWidth_PIX, int texHeight_PIX, bool isSrgb, float fovYDegrees, float widthToHeightRatio, Quaternion rotToUGBD_ULVC, Vector3 posOfULVC_UGBD, Quaternion rotToUGBD_URVC, Vector3 posOfURVC_UGBD)
Definition: Display.cs:196
Display settings constants.
readonly Vector2Int defaultDimensions
static float monoWidthToHeightRatio
The display aspect ratio.
const RenderTextureFormat nativeTextureFormat
static int monoWidth
The display width for a single eye.
static float stereoWidthToHeightRatio
The double-width display aspect ratio.
static DisplaySettings Instance
static int height
The display height.
const int depthBuffer
The depth buffer's precision.
static DisplaySettings instance
static int stereoWidth
The display width for two eyes.
The Glasses API and runtime.
Definition: Glasses.cs:35
static bool updated
Gets a value indicating whether this T:TiltFive.Glasses is updated.
Definition: Glasses.cs:73
GlassesSettings encapsulates all configuration data used by the Glasses' tracking runtime to compute ...
Camera cameraTemplate
The camera used as a template for creating the eye cameras at runtime.
float farClipPlane
The far clip plane in physical space (meters), to adjust for content scale and gameboard size.
float nearClipPlane
The near clip plane in physical space (meters), to adjust for content scale and gameboard size.
bool cloneCameraTemplateChildren
Whether or not the camera template's child gameobjects should be cloned during eye camera instantiati...
The Logger.
Definition: Log.cs:42
static void Warn(string m, params object[] list)
WARN logging function call.
Definition: Log.cs:166
static void Error(string m, params object[] list)
ERROR logging function call.
Definition: Log.cs:127
Provides access to player settings and functionality.
Definition: Player.cs:16
static bool IsConnected(PlayerIndex playerIndex)
Determines whether the specified player has an associated pair of glasses connected.
Definition: Player.cs:32
PlayerIndex spectatedPlayer
The player that will have their perspective mirrored on screen.
Rect rect
The viewport rect used by the Spectator Camera.
GlassesMirrorMode glassesMirrorMode
The spectator camera will display content on screen depending on the mirroring mode....
Camera spectatorCamera
The camera used for rendering the onscreen preview.
float nearClipPlane
The Cameras' near clip plane property.
bool showCameras
In-editor toggle for displaying the eye cameras in the runtime Hierarchy.
void SyncTransform()
EDITOR-ONLY: Syncs the eye Cameras' transform to the Head Pose when tracking is not available.
float aspectRatio
The Cameras' aspect ratio property.
const string RIGHT_EYE_CAMERA_NAME
The name assigned to the dynamically created camera used for rendering the right eye.
void Initialize(GameObject headPoseRoot, GlassesSettings glassesSettings, SpectatorSettings spectatorSettings)
float farClipPlane
The Cameras' far clip plane property.
void OnPreRender()
Configure rendering parameters for the upcoming frame.
GameObject rightEye
The right eye camera GameObject.
void SyncFields()
Syncs the Cameras' fields to the settings.
Quaternion rotToUGBD_UWRLD
The rotation taking points from the Unity world-space reference frame to the game board reference fra...
void InstantiateEyeCameras(out GameObject leftEye, out GameObject rightEye)
void OnValidate()
EDITOR-ONLY.
void Awake()
Awake this instance.
Camera leftEyeCamera
The left eye Camera property.
SplitStereoTextures splitStereoTextures
IEnumerator PresentStereoImagesCoroutine()
GlassesMirrorMode previousMirrorMode
GlassesMirrorMode glassesMirrorMode
void ShowHideCameras()
Show/hide to the eye camerasin the hierarchy.
const string LEFT_EYE_CAMERA_NAME
The name assigned to the dynamically created camera used for rendering the left eye.
Camera cameraTemplate
The Camera used as a template when creating the eye cameras.
Vector3 posUGBD_UWRLD
The position of the game board reference frame w.r.t. the Unity world-space reference frame.
Material displayBlitShader
The Material used to store/reference the shader.
GameObject leftEye
The left eye camera GameObject.
Camera rightEyeCamera
The right eye Camera property.
float scaleToUGBD_UWRLD
The uniform scale factor that takes points from the Unity world-space to the game board reference fra...
const string SHADER_DISPLAY_BLIT
The name of the custom shader that blits the rendertextures to the backbuffer.
float fieldOfView
The Cameras' field of view property.
void OnRenderImage(RenderTexture src, RenderTexture dst)
Apply post-processing effects to the final image before it is presented.
void GenerateEyeCameras(out GameObject leftEye, out GameObject rightEye)
GameObject headPose
The head pose GameObject property.
Dictionary< AREyes, Camera > eyeCameras
The Camera objects.
RenderTexture MonoPreviewTex
The rendertexture used to display onscreen previews for the left or right eye camera.
void ValidateNativeTexturePointers()
Determines whether the left/right texture handles are still valid, and resets them if needed.
void GetNativeTexturePointers(out IntPtr leftTexHandle, out IntPtr rightTexHandle)
Acquires the native output textures upon startup or invalidaiton.
void SubmitPreviewTextures(GlassesMirrorMode glassesMirrorMode)
Copies frame data from the HDR input textures to the onscreen preview textures.
RenderTexture LeftTexture_GLS
The left eye rendertexture.
RenderTexture RightTexture_GLS
The right eye rendertexture.
void Initialize()
Creates and configures the stereo rendertextures.
Definition: Log.cs:21
PlayerIndex
The Player index (e.g. Player One, Player Two, etc)