/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
namespace NRKernal.Experimental
{
using System;
using UnityEngine;
[ScriptOrder(NativeConstants.NRRENDER_ORDER)]
[RequireComponent(typeof(Camera))]
public class NRDisplayOverlay : OverlayBase
{
///
/// Which display this overlay should render to.
///
[Tooltip("Which display this overlay should render to.")]
public NativeDevice targetEye;
private Camera m_RenderCamera;
private int m_EyeWidth;
private int m_EyeHeight;
private bool m_IsTrackingModeChanging = false;
private RenderTexture m_HijackRenderTextureLeft = null;
private RenderTexture m_HijackRenderTextureRight = null;
protected override void Initialize()
{
base.Initialize();
m_RenderCamera = gameObject.GetComponent();
#if !UNITY_EDITOR
NRDevice.Instance.Init();
var resolution = NRFrame.GetDeviceResolution(NativeDevice.LEFT_DISPLAY);
m_EyeWidth = resolution.width;
m_EyeHeight = resolution.height;
#else
m_EyeWidth = 1920;
m_EyeHeight = 1080;
#endif
this.compositionDepth = int.MaxValue;
m_BufferSpec.size = new NativeResolution((int)m_EyeWidth, (int)m_EyeHeight);
m_BufferSpec.colorFormat = NRColorFormat.NR_COLOR_FORMAT_RGBA_8888;
m_BufferSpec.depthFormat = NRDepthStencilFormat.NR_DEPTH_STENCIL_FORMAT_DEPTH_24;
m_BufferSpec.samples = 1;
m_BufferSpec.useExternalSurface = false;
NRSessionManager.Instance.TrackingLostListener.OnTrackStateChanged -= OnTrackStateChanged;
NRSessionManager.Instance.TrackingLostListener.OnTrackStateChanged += OnTrackStateChanged;
}
private void OnTrackStateChanged(bool trackChanging, RenderTexture leftRT, RenderTexture rightRT)
{
if (trackChanging)
{
m_IsTrackingModeChanging = true;
m_HijackRenderTextureLeft = leftRT;
m_HijackRenderTextureRight = rightRT;
m_RenderCamera.targetTexture = null;
SetDirty(true);
}
else
{
m_IsTrackingModeChanging = false;
m_HijackRenderTextureLeft = null;
m_HijackRenderTextureRight = null;
SetDirty(true);
}
}
public override void SwapBuffers(IntPtr bufferHandler)
{
if (!Textures.ContainsKey(bufferHandler))
{
NRDebugger.Error("[NRDisplayOverlay] SwapBuffers: Can not find the texture-[{0}]", bufferHandler);
return;
}
Texture targetTexture;
Textures.TryGetValue(bufferHandler, out targetTexture);
RenderTexture renderTexture = targetTexture as RenderTexture;
if (renderTexture == null)
{
NRDebugger.Error("[NRDisplayOverlay] The texture is null...");
return;
}
if (m_IsTrackingModeChanging)
{
var srcTexture = (targetEye == NativeDevice.LEFT_DISPLAY) ? m_HijackRenderTextureLeft : m_HijackRenderTextureRight;
Graphics.CopyTexture(srcTexture, renderTexture);
}
else
{
m_RenderCamera.targetTexture = renderTexture;
}
}
public override void CreateViewport()
{
m_ViewPorts = new ViewPort[1];
m_ViewPorts[0].reprojection = m_IsTrackingModeChanging ? NRReprojectionType.NR_REPROJECTION_TYPE_NONE : NRReprojectionType.NR_REPROJECTION_TYPE_FULL;
m_ViewPorts[0].sourceUV = new Rect(0, 0, 1, 1);
m_ViewPorts[0].targetDisplay = targetEye == NativeDevice.LEFT_DISPLAY ? LayerSide.Left : LayerSide.Right;
m_ViewPorts[0].layerID = m_LayerId;
NRFrame.GetEyeFov(targetEye, ref m_ViewPorts[0].fov);
m_ViewPorts[0].is3DLayer = true;
NRSwapChainManager.Instance.CreateBufferViewport(ref m_ViewPorts[0]);
}
public override void DestroyViewPort()
{
base.DestroyViewPort();
if (m_ViewPorts != null)
{
var viewport = m_ViewPorts[0];
NRSwapChainManager.Instance.DestroyBufferViewPort(viewport.nativeHandler);
m_ViewPorts = null;
}
}
public override void UpdateViewPort()
{
if (m_ViewPorts == null)
{
NRDebugger.Warning("Can not update view port for this layer:{0}", gameObject.name);
return;
}
NRSwapChainManager.Instance.UpdateBufferViewport(ref m_ViewPorts[0]);
}
public override void CreateOverlayTextures()
{
NRDebugger.Info("[NRDisplayOverlay] CreateOverlayTextures. ");
ReleaseOverlayTextures();
for (int i = 0; i < m_BufferSpec.bufferCount; i++)
{
RenderTexture texture = UnityExtendedUtility.CreateRenderTexture((int)m_EyeWidth, (int)m_EyeHeight, 24, RenderTextureFormat.ARGB32);
IntPtr texturePtr = texture.GetNativeTexturePtr();
Textures.Add(texturePtr, texture);
// NRDebugger.Info("[NRDisplayOverlay] CreateOverlayTextures: {0} => {1}", i, texturePtr);
}
}
public override void ReleaseOverlayTextures()
{
if (Textures.Count == 0)
{
return;
}
NRDebugger.Info("[NRDisplayOverlay] ReleaseOverlayTextures. ");
foreach (var item in Textures)
{
RenderTexture rt = item.Value as RenderTexture;
if (rt != null) rt.Release();
}
Textures.Clear();
}
new void OnDestroy()
{
base.OnDestroy();
if (NRSessionManager.Instance.TrackingLostListener != null)
NRSessionManager.Instance.TrackingLostListener.OnTrackStateChanged -= OnTrackStateChanged;
}
}
}