Как я могу конвертировать из 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 на шейдер?

Заранее спасибо.

0 ответов

Другие вопросы по тегам