//================================================================================================================================ // // Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved. // EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China // and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd. // //================================================================================================================================ using System; using UnityEngine; namespace easyar { /// /// Material to render camera image. /// 用于渲染camera图像的材质。 /// public class CameraImageMaterial : IDisposable { private static CameraImageShaders shaders; private Material mat; private Texture2D[] textures = new Texture2D[0]; private PixelFormat format; private int imageWidth; private int imageHeight; public CameraImageMaterial() { if (!shaders) { shaders = Resources.Load("EasyAR/Shaders"); } } ~CameraImageMaterial() { DisposeResources(); } /// /// Dispose resources. /// 销毁资源。 /// public void Dispose() { DisposeResources(); GC.SuppressFinalize(this); } /// /// Update material using . /// 使用更新材质。 /// public Material UpdateByImage(Image image) { var recreateMaterial = false; if (image.width() != imageWidth || image.height() != imageHeight || image.format() != format) { DisposeResources(); imageWidth = image.width(); imageHeight = image.height(); format = image.format(); recreateMaterial = true; } using (var buffer = image.buffer()) { var ptr = buffer.data(); var resolution = imageWidth * imageHeight; switch (format) { case PixelFormat.Gray: if (recreateMaterial) { textures = new Texture2D[1]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.Alpha8, false); mat = new Material(shaders.GRAY); mat.SetTexture("_grayTexture", textures[0]); } textures[0].LoadRawTextureData(ptr, resolution); textures[0].Apply(); break; case PixelFormat.YUV_NV21: if (recreateMaterial) { textures = new Texture2D[2]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.Alpha8, false); textures[1] = new Texture2D(imageWidth / 2, imageHeight / 2, TextureFormat.RGBA4444, false); mat = new Material(shaders.YUV_NV21); mat.SetTexture("_yTexture", textures[0]); mat.SetTexture("_uvTexture", textures[1]); } textures[0].LoadRawTextureData(ptr, resolution); textures[0].Apply(); textures[1].LoadRawTextureData(new IntPtr(ptr.ToInt64() + resolution), resolution); textures[1].Apply(); break; case PixelFormat.YUV_NV12: if (recreateMaterial) { textures = new Texture2D[2]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.Alpha8, false); textures[1] = new Texture2D(imageWidth / 2, imageHeight / 2, TextureFormat.RGBA4444, false); mat = new Material(shaders.YUV_NV12); mat.SetTexture("_yTexture", textures[0]); mat.SetTexture("_uvTexture", textures[1]); } textures[0].LoadRawTextureData(ptr, resolution); textures[0].Apply(); textures[1].LoadRawTextureData(new IntPtr(ptr.ToInt64() + resolution), resolution); textures[1].Apply(); break; case PixelFormat.YUV_I420: if (recreateMaterial) { textures = new Texture2D[3]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.Alpha8, false); textures[1] = new Texture2D(imageWidth / 2, imageHeight / 2, TextureFormat.Alpha8, false); textures[2] = new Texture2D(imageWidth / 2, imageHeight / 2, TextureFormat.Alpha8, false); mat = new Material(shaders.YUV_I420_YV12); mat.SetTexture("_yTexture", textures[0]); mat.SetTexture("_uTexture", textures[1]); mat.SetTexture("_vTexture", textures[2]); } textures[0].LoadRawTextureData(new IntPtr(ptr.ToInt64()), resolution); textures[0].Apply(); textures[1].LoadRawTextureData(new IntPtr(ptr.ToInt64() + resolution), resolution / 4); textures[1].Apply(); textures[2].LoadRawTextureData(new IntPtr(ptr.ToInt64() + resolution + resolution / 4), resolution / 4); textures[2].Apply(); break; case PixelFormat.YUV_YV12: if (recreateMaterial) { textures = new Texture2D[3]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.Alpha8, false); textures[1] = new Texture2D(imageWidth / 2, imageHeight / 2, TextureFormat.Alpha8, false); textures[2] = new Texture2D(imageWidth / 2, imageHeight / 2, TextureFormat.Alpha8, false); mat = new Material(shaders.YUV_I420_YV12); mat.SetTexture("_yTexture", textures[0]); mat.SetTexture("_uTexture", textures[1]); mat.SetTexture("_vTexture", textures[2]); } textures[0].LoadRawTextureData(new IntPtr(ptr.ToInt64()), resolution); textures[0].Apply(); textures[1].LoadRawTextureData(new IntPtr(ptr.ToInt64() + resolution + resolution / 4), resolution / 4); textures[1].Apply(); textures[2].LoadRawTextureData(new IntPtr(ptr.ToInt64() + resolution), resolution / 4); textures[2].Apply(); break; case PixelFormat.RGB888: if (recreateMaterial) { textures = new Texture2D[1]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.RGB24, false); mat = new Material(shaders.RGB); mat.SetTexture("_MainTex", textures[0]); } textures[0].LoadRawTextureData(new IntPtr(ptr.ToInt64()), buffer.size()); textures[0].Apply(); break; case PixelFormat.BGR888: if (recreateMaterial) { textures = new Texture2D[1]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.RGB24, false); mat = new Material(shaders.BGR); mat.SetTexture("_MainTex", textures[0]); } textures[0].LoadRawTextureData(new IntPtr(ptr.ToInt64()), buffer.size()); textures[0].Apply(); break; case PixelFormat.RGBA8888: if (recreateMaterial) { textures = new Texture2D[1]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.RGBA32, false); mat = new Material(shaders.RGB); mat.SetTexture("_MainTex", textures[0]); } textures[0].LoadRawTextureData(new IntPtr(ptr.ToInt64()), buffer.size()); textures[0].Apply(); break; case PixelFormat.BGRA8888: if (recreateMaterial) { textures = new Texture2D[1]; textures[0] = new Texture2D(imageWidth, imageHeight, TextureFormat.RGBA32, false); mat = new Material(shaders.BGR); mat.SetTexture("_MainTex", textures[0]); } textures[0].LoadRawTextureData(new IntPtr(ptr.ToInt64()), buffer.size()); textures[0].Apply(); break; default: break; } } return mat; } private void DisposeResources() { if (mat) { UnityEngine.Object.Destroy(mat); } foreach(var texture in textures) { UnityEngine.Object.Destroy(texture); } } } }