/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal.Record { using UnityEngine; /// A frame blender. public class FrameBlender : BlenderBase { /// Target camera. protected Camera m_TargetCamera; /// The encoder. protected IEncoder m_Encoder; /// The blend material. private Material m_BlendMaterial; /// The blend mode. protected BlendMode m_BlendMode; /// The RGB source. protected RenderTexture m_RGBSource; /// The temporary combine tex. protected Texture2D m_TempCombineTex; /// The blend texture. private RenderTexture m_BlendTexture; /// Gets or sets the blend texture. /// The blend texture. public override RenderTexture BlendTexture { get { return m_BlendTexture; } protected set { m_BlendTexture = value; } } /// Gets the RGB texture. /// The RGB texture. public RenderTexture RGBTexture { get { return m_RGBSource; } } /// Gets the virtual texture. /// The virtual texture. public RenderTexture VirtualTexture { get { return m_TargetCamera.targetTexture; } } /// Initializes this object. /// The camera. /// The encoder. /// The parameter. public override void Init(Camera camera, IEncoder encoder, CameraParameters param) { Width = param.cameraResolutionWidth; Height = param.cameraResolutionHeight; m_BlendMode = param.blendMode; m_TargetCamera = camera; m_Encoder = encoder; // An extra rendering is required when BlendMode is RGBOnly or WidescreenBlend. switch (m_BlendMode) { case BlendMode.RGBOnly: BlendTexture = UnityExtendedUtility.CreateRenderTexture(Width, Height, 24, RenderTextureFormat.ARGB32, false); break; case BlendMode.VirtualOnly: BlendTexture = UnityExtendedUtility.CreateRenderTexture(Width, Height, 24, RenderTextureFormat.ARGB32, false); break; case BlendMode.Blend: BlendTexture = UnityExtendedUtility.CreateRenderTexture(Width, Height, 24, RenderTextureFormat.ARGB32, false); break; case BlendMode.WidescreenBlend: BlendTexture = UnityExtendedUtility.CreateRenderTexture(2 * Width, Height, 24, RenderTextureFormat.ARGB32, false); m_RGBSource = UnityExtendedUtility.CreateRenderTexture(Width, Height, 24, RenderTextureFormat.ARGB32, false); m_TempCombineTex = new Texture2D(2 * Width, Height, TextureFormat.ARGB32, false); break; default: break; } m_TargetCamera.enabled = false; m_TargetCamera.targetTexture = UnityExtendedUtility.CreateRenderTexture(Width, Height, 24, RenderTextureFormat.ARGB32); } /// Executes the 'frame' action. /// The frame. public override void OnFrame(UniversalTextureFrame frame) { Texture2D frametex = frame.textures[0] as Texture2D; if (m_BlendMode != BlendMode.RGBOnly) { m_TargetCamera.Render(); } if (m_BlendMaterial == null) { CreatBlendMaterial(m_BlendMode, frame.textureType); } bool isyuv = frame.textureType == TextureType.YUV; switch (m_BlendMode) { case BlendMode.RGBOnly: const string MainTextureStr = "_MainTex"; if (isyuv) { const string UTextureStr = "_UTex"; const string VTextureStr = "_VTex"; m_BlendMaterial.SetTexture(MainTextureStr, frame.textures[0]); m_BlendMaterial.SetTexture(UTextureStr, frame.textures[1]); m_BlendMaterial.SetTexture(VTextureStr, frame.textures[2]); } else { m_BlendMaterial.SetTexture(MainTextureStr, frame.textures[0]); } Graphics.Blit(frame.textures[0], BlendTexture, m_BlendMaterial); break; case BlendMode.VirtualOnly: m_BlendMaterial.SetTexture("_MainTex", m_TargetCamera.targetTexture); Graphics.Blit(m_TargetCamera.targetTexture, BlendTexture, m_BlendMaterial); break; case BlendMode.Blend: m_BlendMaterial.SetTexture("_MainTex", m_TargetCamera.targetTexture); if (isyuv) { m_BlendMaterial.SetTexture("_YTex", frame.textures[0]); m_BlendMaterial.SetTexture("_UTex", frame.textures[1]); m_BlendMaterial.SetTexture("_VTex", frame.textures[2]); } else { m_BlendMaterial.SetTexture("_BcakGroundTex", frame.textures[0]); } Graphics.Blit(m_TargetCamera.targetTexture, BlendTexture, m_BlendMaterial); break; case BlendMode.WidescreenBlend: if (isyuv) { throw new System.Exception("Not support yuv texture for this mode..."); } CombineTexture(frametex, m_TargetCamera.targetTexture, m_TempCombineTex, BlendTexture); break; default: break; } // Commit frame m_Encoder.Commit(BlendTexture, frame.timeStamp); FrameCount++; } private void CreatBlendMaterial(BlendMode mode, TextureType texturetype) { string shader_name; if (mode == BlendMode.Blend) { shader_name = "Record/Shaders/AlphaBlend{0}"; shader_name = string.Format(shader_name, texturetype == TextureType.RGB ? "" : "YUV"); } else if (mode == BlendMode.VirtualOnly) { shader_name = "Record/Shaders/NormalTexture"; } else { shader_name = "Record/Shaders/NormalBlend{0}"; shader_name = string.Format(shader_name, texturetype == TextureType.RGB ? "" : "YUV"); } m_BlendMaterial = new Material(Resources.Load(shader_name)); } /// Combine texture. /// The bgsource. /// The foresource. /// The tempdest. /// Destination for the. private void CombineTexture(Texture2D bgsource, RenderTexture foresource, Texture2D tempdest, RenderTexture dest) { const string MainTextureStr = "_MainTex"; m_BlendMaterial.SetTexture(MainTextureStr, m_RGBSource); Graphics.Blit(bgsource, m_RGBSource, m_BlendMaterial); RenderTexture prev = RenderTexture.active; RenderTexture.active = m_RGBSource; tempdest.ReadPixels(new Rect(0, 0, m_RGBSource.width, m_RGBSource.height), 0, 0); RenderTexture.active = foresource; tempdest.ReadPixels(new Rect(0, 0, foresource.width, foresource.height), foresource.width, 0); tempdest.Apply(); RenderTexture.active = prev; Graphics.Blit(tempdest, dest); } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged /// resources. public override void Dispose() { m_BlendTexture?.Release(); m_RGBSource?.Release(); GameObject.Destroy(m_TempCombineTex); m_BlendTexture = null; m_RGBSource = null; m_TempCombineTex = null; } } }