Как изменить пиксели текстуры из вычислительного шейдера в единстве?

Я наткнулся на странную проблему в vuforia. Когда я запрашиваю изображение с камеры с помощью CameraDevice.GetCameraImage (mypixelformat), возвращаемое изображение переворачивается боком и поворачивается на 180 градусов. Из-за этого, чтобы получить нормальное изображение, мне нужно сначала повернуть изображение, а затем перевернуть его вбок. Я использую простой итерационный подход по пикселям изображения и их изменение. Этот подход очень плох с точки зрения производительности. код:

    Texture2D image;

    CameraDevice cameraDevice = Vuforia.CameraDevice.Instance;
    Vuforia.Image vufImage = cameraDevice.GetCameraImage(pixelFormat);
    image = new Texture2D(vufImage.Width, vufImage.Height);
    vufImage.CopyToTexture(image);

    Color32[] colors = image.GetPixels32();
    System.Array.Reverse(colors, 0, colors.Length);  //rotate 180deg
    image.SetPixels32(colors);                       //apply rotation
    image = FlipTexture(image);                      //flip sideways






                 //***** THE FLIP TEXTURE METHOD *******//

private Texture2D FlipTexture(Texture2D original, bool upSideDown = false)
{

    Texture2D flipped = new Texture2D(original.width, original.height);

    int width  = original.width;
    int height = original.height;


    for (int col = 0; col < width; col++)
    {
        for (int row = 0; row < height; row++)
        {
            if (upSideDown)
            {
                flipped.SetPixel(row, (width - 1) - col, original.GetPixel(row, col));
            }
            else
            {
                flipped.SetPixel((width - 1) - col, row, original.GetPixel(col, row));
            }
        }
    }

    flipped.Apply();

    return flipped;
}

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


person With A SpiRIT    schedule 07.08.2018    source источник
comment
VuforiaConfiguration имеет возможность перевернуть изображение камеры по горизонтали. может ли этот вариант решить вашу проблему?   -  person Senbazuru    schedule 07.08.2018
comment
Это переворачивает изображение только при включенной игре Vuforia (только в редакторе Unity)   -  person With A SpiRIT    schedule 07.08.2018
comment
И, кстати, это не работает !.   -  person With A SpiRIT    schedule 07.08.2018
comment
Могу я спросить, как вы хотите использовать Texture2D и как его применять?   -  person Senbazuru    schedule 08.08.2018
comment
Я не хочу применять текстуру к чему-либо, иначе я бы просто изменил УФ и отменил эффект переворачивания и поворота. У меня есть функция, которая обрезает переданную ей часть Texture2D, которая находится под RectTransform (интересующая область). Что-то похожее на инструмент для обрезки окон, за исключением того, что моя функция обрезается из текстуры, переданной ему.   -  person With A SpiRIT    schedule 08.08.2018


Ответы (1)


Для меня вычислительные шейдеры в целом тоже новы, но я воспользовался случаем, чтобы немного изучить его и для себя. Следующие действия предназначены для вертикального отражения текстуры (поворот и отражение по горизонтали должны быть просто вертикальным отражением). У кого-то может быть для вас более продуманное решение, но, возможно, этого будет достаточно, чтобы вы начали.

Код вычислительного шейдера:

 #pragma kernel CSMain
// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D<float4> Result;
Texture2D<float4> ImageInput;
float2 flip;
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    flip = float2(512 , 1024) - id.xy ;
    Result[id.xy] = float4(ImageInput[flip].x, ImageInput[flip].y, ImageInput[flip].z, 1.0);
}

и вызывается из любого скрипта:

public void FlipImage()
{
    int kernelHandle = shader.FindKernel("CSMain");
    RenderTexture tex = new RenderTexture(512, 1024, 24);
    tex.enableRandomWrite = true;
    tex.Create();

    shader.SetTexture(kernelHandle, "Result", tex);
    shader.SetTexture(kernelHandle, "ImageInput", myTexture);
    shader.Dispatch(kernelHandle, 512/8 , 1024 / 8, 1);

    RenderTexture.active = tex;
    result.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
    result.Apply();
}

Это принимает входной файл Texture2D, переворачивает его в шейдере, применяет его к RenderTexture и Texture2D, что вам нужно. Обратите внимание, что размеры изображений в моем случае жестко запрограммированы и должны быть заменены на любой размер, который вам нужен. (для внутри шейдера используйте shader.SetInt ();)

person Senbazuru    schedule 08.08.2018