如何统一从计算着色器修改纹理像素?

时间:2018-08-07 12:45:24

标签: unity3d image-processing shader texture2d compute-shader

我偶然发现了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;
}

为了提高性能,我想以某种方式在GPU上安排这些像素操作,我听说可以使用计算着色器,但是我不知道从哪里开始。有人可以帮我在Windows中编写相同的操作吗?计算着色器,以便GPU可以处理它们,谢谢!。

1 个答案:

答案 0 :(得分: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();)

相关问题