Unity - обнаружение, если OpenGL на Android не поддерживает определенную операцию - PullRequest
0 голосов
/ 23 мая 2018

Я использую код масштабирования текстуры, найденный на pastebin (код ниже), и по некоторым причинам он не работает на некоторых устройствах, он создает недопустимую текстуру.Одно устройство, я уверен, что оно не работает, это планшет Nexus 7 (2012), но, вероятно, он не работает на многих других.Но на подавляющем большинстве устройств это работает.

Я не уверен, почему это не работает, или на каких операциях он выходит из строя, но, учитывая, что этот скейлер сделан на GPU, он намного быстрее, чем другие версии скейлеровЯ обнаружил.

Что я хочу сделать, так это как-то обнаружить, что он не работает, чтобы я мог запустить более медленную версию алгоритма масштабирования.Любые идеи на:

1) Как обнаружить?Я думал о том, чтобы проверить, является ли текстура недействительной после запуска, но она может вести себя по-разному на разных устройствах (на Nexus 7 она всегда превращает цвета пикселей в 205,205,205)

2) Почему это не работает?В ходе некоторых поисков я обнаружил, что некоторые операции с графическим процессором на Nexus 7 не выполняются, если текстура является NPOT, но я не знаю, связано ли это с этим.Я также подумал, что, возможно, это связано с версией Open GL ES, но я не знаю, как проверить версию (может быть, Nexus 7 - это GLES 2.0, а этот скалер работает только на GLES 3.0 +?).

Спасибо

using UnityEngine;

// from: https://pastebin.com/qkkhWs2J

/// A unility class with functions to scale Texture2D Data.
///
/// Scale is performed on the GPU using RTT, so it's blazing fast.
/// Setting up and Getting back the texture data is the bottleneck.
/// But Scaling itself costs only 1 draw call and 1 RTT State setup!
/// WARNING: This script override the RTT Setup! (It sets a RTT!)        
///
/// Note: This scaler does NOT support aspect ratio based scaling. You will have to do it yourself!
/// It supports Alpha, but you will have to divide by alpha in your shaders,
/// because of premultiplied alpha effect. Or you should use blend modes.
public class TextureScaler
{

    /// <summary>
    ///     Returns a scaled copy of given texture.
    /// </summary>
    /// <param name="tex">Source texure to scale</param>
    /// <param name="width">Destination texture width</param>
    /// <param name="height">Destination texture height</param>
    /// <param name="mode">Filtering mode</param>
    public static Texture2D scaled(Texture2D src, int width, int height, FilterMode mode = FilterMode.Trilinear)
    {
            Rect texR = new Rect(0,0,width,height);
            _gpu_scale(src,width,height,mode);

            //Get rendered data back to a new texture
            Texture2D result = new Texture2D(width, height, TextureFormat.ARGB32, true);
            result.Resize(width, height);
            result.ReadPixels(texR,0,0,true);
            return result;                 
    }

    /// <summary>
    /// Scales the texture data of the given texture.
    /// </summary>
    /// <param name="tex">Texure to scale</param>
    /// <param name="width">New width</param>
    /// <param name="height">New height</param>
    /// <param name="mode">Filtering mode</param>
    public static void scale(Texture2D tex, int width, int height, FilterMode mode = FilterMode.Trilinear)
    {
            Rect texR = new Rect(0,0,width,height);
            _gpu_scale(tex,width,height,mode);

            // Update new texture
            tex.Resize(width, height);
            tex.ReadPixels(texR,0,0,true);
            tex.Apply(true);        //Remove this if you hate us applying textures for you :)
    }

    // Internal unility that renders the source texture into the RTT - the scaling method itself.
    static void _gpu_scale(Texture2D src, int width, int height, FilterMode fmode)
    {
            //We need the source texture in VRAM because we render with it
            src.filterMode = fmode;
            src.Apply(true);       

            //Using RTT for best quality and performance. Thanks, Unity 5
            RenderTexture rtt = new RenderTexture(width, height, 32);

            //Set the RTT in order to render to it
            Graphics.SetRenderTarget(rtt);

            //Setup 2D matrix in range 0..1, so nobody needs to care about sized
            GL.LoadPixelMatrix(0,1,1,0);

            //Then clear & draw the texture to fill the entire RTT.
            GL.Clear(true,true,new Color(0,0,0,0));
            Graphics.DrawTexture(new Rect(0,0,1,1),src);
    }
}
...