Как я могу конвертировать из YV21 в NV21 в шейдере VideoBackground в приложении Unity с VUFORIA?
Моя команда разрабатывает приложение дополненной реальности для устройств Android и ios на Unity 3D 2018.1.3f1 и распознавании облаков vuforia 7.1.31, проблема в том, что на некоторых устройствах формат видео отличается, например, на ZTE v10 мы получили эту графику баг и на мото G5 plus отлично работает Srceenshot Moto G5 Plus Srceenshot ZTE v10
Мы используем этот шейдер для фона видео:
Shader "Custom/VideoBackground" {
// Used to render the Vuforia Video Background
Properties
{
[NoScaleOffset] _MainTex("Texture", 2D) = "white" {}
[NoScaleOffset] _UVTex("UV Texture", 2D) = "white" {}
}
SubShader
{
Tags {"Queue" = "geometry-11" "RenderType" = "opaque" }
Pass {
ZWrite Off
Cull Off
Lighting Off
CGPROGRAM
#pragma multi_compile VUFORIA_RGB VUFORIA_YUVNV12 VUFORIA_YUVNV21
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
#if (VUFORIA_YUVNV12 || VUFORIA_YUVNV21)
sampler2D _UVTex;
float4 _UVTex_ST;
#endif
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
#if (VUFORIA_YUVNV12 || VUFORIA_YUVNV21)
float2 uv2 : TEXCOORD1;
#endif
};
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
#if (VUFORIA_YUVNV12 || VUFORIA_YUVNV21)
o.uv2 = TRANSFORM_TEX(v.texcoord, _UVTex);
#endif
return o;
}
#if (VUFORIA_YUVNV12 || VUFORIA_YUVNV21)
half4 frag(v2f i) : COLOR
{
half4 c;
half2 uv = tex2D(_UVTex, i.uv2).rg;
float y = tex2D(_MainTex, i.uv).r;
#if VUFORIA_YUVNV12
half4 v4yuv1 = half4(y, uv, 1.0);
c.r = dot(half4(1.1640625, 0.000000000, 1.5957031250, -0.87060546875), v4yuv1);
c.g = dot(half4(1.1640625, -0.390625000, -0.8134765625, 0.52929687500), v4yuv1);
c.b = dot(half4(1.1640625, 2.017578125, 0.0000000000, -1.08154296875), v4yuv1);
c.a = 1.0;
#else
half4 v4yuv1 = half4(y, uv, 1.0);
c.r = dot(half4(1.1640625, 1.5957031250, 0.000000000, -0.87060546875), v4yuv1);
c.g = dot(half4(1.1640625, -0.8134765625, -0.390625000, 0.52929687500), v4yuv1);
c.b = dot(half4(1.1640625, 0.0000000000, 2.017578125, -1.08154296875), v4yuv1);
c.a = 1.0;
#endif
#ifdef UNITY_COLORSPACE_GAMMA
return c;
#else
return fixed4(GammaToLinearSpace(c.rgb), c.a);
#endif
}
#else
half4 frag(v2f i) : COLOR
{
half4 c = tex2D(_MainTex, i.uv);
c.rgb = c.rgb;
c.a = 1.0;
#ifdef UNITY_COLORSPACE_GAMMA
return c;
#else
return fixed4(GammaToLinearSpace(c.rgb), c.a);
#endif
}
#endif
ENDCG
}
}
Fallback "Legacy Shaders/Diffuse"
}
Другая проблема заключается в том, что только с тем шейдером у нас появился черный экран, мы используем этот код, чтобы изменить формат изображения камеры, но затем мы получили графическую ошибку на изображении:
#region PRIVATE_MEMBERS
private Image.PIXEL_FORMAT mPixelFormat = Image.PIXEL_FORMAT.UNKNOWN_FORMAT;
private bool mAccessCameraImage = true;
private bool mFormatRegistered = false;
#endregion // PRIVATE_MEMBERS
#region MONOBEHAVIOUR_METHODS
void Start()
{
//#if UNITY_EDITOR
// mPixelFormat = Image.PIXEL_FORMAT.GRAYSCALE; // Need Grayscale for Editor
//#else
// //mPixelFormat = Image.PIXEL_FORMAT.; // Use RGB888 for mobile
//#endif
mPixelFormat = Image.PIXEL_FORMAT.UNKNOWN_FORMAT; // Use RGB888 for mobile
// Register Vuforia life-cycle callbacks:
VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
VuforiaARController.Instance.RegisterTrackablesUpdatedCallback(OnTrackablesUpdated);
VuforiaARController.Instance.RegisterOnPauseCallback(OnPause);
}
void OnApplicationPaused(bool paused)
{
if (paused)
{
// invalidate registered format if app has been paused
mFormatRegistered = false;
}
}
void OnTrackablesUpdated()
{
if (mFormatRegistered)
{
if (mAccessCameraImage)
{
Vuforia.Image image = CameraDevice.Instance.GetCameraImage(mPixelFormat);
if (image != null)
{
Debug.Log(
"\nImage Format: " + image.PixelFormat +
"\nImage Size: " + image.Width + "x" + image.Height +
"\nBuffer Size: " + image.BufferWidth + "x" + image.BufferHeight +
"\nImage Stride: " + image.Stride + "\n"
);
byte[] pixels = image.Pixels;
byte[] output = new byte[pixels.Length];
pixels.CopyTo(output, 0);
if (image.Pixels != null && image.Pixels.Length > 0)
{
Debug.Log(image.Pixels.Length);
Debug.Log(
"\nImage pixels: " +
image.Pixels[0] + ", " +
image.Pixels[1] + ", " +
image.Pixels[2] + ", ...\n"
);
}
}
}
}
else
{
RegisterFormat();
}
}
void RegisterFormat()
{
if (CameraDevice.Instance.SetFrameFormat(mPixelFormat, true))
{
Debug.Log("Successfully registered camera pixel format " + mPixelFormat.ToString());
mFormatRegistered = true;
}
else
{
Debug.LogError("Failed to register camera pixel format " + mPixelFormat.ToString());
mFormatRegistered = false;
}
}
Есть в любом случае, мы можем конвертировать видео формат с YV21 на NV21 на шейдер?
Заранее спасибо.