如何在Unity中从RenderTexture访问原始数据 [英] How to access raw data from RenderTexture in Unity

查看:131
本文介绍了如何在Unity中从RenderTexture访问原始数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Unity中访问RenderTexture的内容,而我一直在使用Graphics.Blit用自己的材质进行绘制.

I am trying to access the contents of a RenderTexture in Unity which I have been drawing with an own Material using Graphics.Blit.

Graphics.Blit (null, renderTexture, material);

我的材料成功地将一些yuv图像转换为rgb,我已经通过将其分配给UI元素的纹理进行了测试.结果是在屏幕上可见的正确RGB图像.

My material converts some yuv image to rgb successfully, which I have tested by assigning it to the texture of an UI element. The result is the correct RGB image visible on the screen.

但是,我还需要QR扫描仪的原始数据.我这样做的方式就像我要从相机访问它一样,如

However, I also need the raw data for a QR code scanner. I am doing this like I would access it from a camera as explained here. In a comment down there, it was mentioned that the extraction is also possible from a RenderTexture that was filled with Graphics.Blit. But when I am trying to that, my texture only contains the value 205 everywhere. This is the code I am using in the Update function, directly after the Graphics.Blit call:

RenderTexture.active = renderTexture;
texture.ReadPixels (new Rect (0, 0, width, height), 0, 0);
texture.Apply ();
RenderTexture.active = null;

将此纹理分配给相同的UI元素时,它为灰色且略微透明.查看图像值时,它们全都是205.

When assigning this texture to the same UI element, it is gray and slightly transparent. When viewing the image values, they are all 205.

为什么可能?我尝试填充的RenderTexture和Texture2D格式可能存在问题吗?

Why is the possible? May there be problems with the formats that the RenderTexture and Texture2D I am trying to fill?

在下面,我添加了我正在使用的整个代码.变量的名称与我上面使用的名称略有不同,但是它们的作用基本相同:

In the following I add the whole code I am using. The names of the variables slightly differ to the ones I used above but they do essentially the same:

/** 
 * This class continously converts the y and uv textures in 
 * YUV color space to a RGB texture, which can be used somewhere else
 */
public class YUV2RGBConverter : MonoBehaviour {
    public Material yuv2rgbMat;

    // Input textures, set these when they are available
    [HideInInspector]
    public Texture2D yTex;
    [HideInInspector]
    public Texture2D uvTex;

    // Output, the converted textures
    [HideInInspector]
    public RenderTexture rgbRenderTex;
    [HideInInspector]
    public Texture2D rgbTex;
    [HideInInspector]
    public Color32[] rawRgbData;

    /// Describes how often per second the image should be transferred to the CPU
    public float GPUTransferRate = 1.0f;
    private float timeSinceLastGPUTransfer = 0.0f;

    private int width;
    private int height;

    /**
     * Initializes the used textures 
     */
    void Start () {
        updateSize (width, height);
    }

    /**
     * Depending on the sizes of the texture, creating the needed textures for this class 
     */
    public void updateSize(int width, int height)
    {
        // Generate the input textures
        yTex = new Texture2D(width / 4, height, TextureFormat.RGBA32, false);
        uvTex = new Texture2D ((width / 2) * 2 / 4, height / 2, TextureFormat.RGBA32, false);

        // Generate the output texture
        rgbRenderTex = new RenderTexture(width, height, 0);
        rgbRenderTex.antiAliasing = 0;
        rgbTex = new Texture2D (width, height, TextureFormat.RGBA32, false);

        // Set to shader
        yuv2rgbMat.SetFloat("_TexWidth", width);
        yuv2rgbMat.SetFloat("_TexHeight", height);
    }

    /**
     * Sets the y and uv textures to some dummy data
     */
    public void fillYUWithDummyData()
    {
        // Set the y tex everywhere to time rest
        float colorValue = (float)Time.time - (float)((int)Time.time); 
        for (int y = 0; y < yTex.height; y++) {
            for (int x = 0; x < yTex.width; x++) {
                Color yColor = new Color (colorValue, colorValue, colorValue, colorValue);
                yTex.SetPixel (x, y, yColor);
            }
        }
        yTex.Apply ();

        // Set the uv tex colors 
        for (int y = 0; y < uvTex.height; y++) {
            for (int x = 0; x < uvTex.width; x++) {
                int firstXCoord = 2 * x;
                int secondXCoord = 2 * x + 1;
                int yCoord = y;

                float firstXRatio = (float)firstXCoord / (2.0f * (float)uvTex.width);
                float secondXRatio = (float)secondXCoord / (2.0f * (float)uvTex.width);
                float yRatio = (float)y / (float)uvTex.height;

                Color uvColor = new Color (firstXRatio, yRatio, secondXRatio, yRatio);
                uvTex.SetPixel (x, y, uvColor);
            }
        }
        uvTex.Apply ();
    }

    /**
     * Continuously convert y and uv texture to rgb texture with custom yuv2rgb shader
     */
    void Update () {
        // Draw to it with the yuv2rgb shader
        yuv2rgbMat.SetTexture ("_YTex", yTex);
        yuv2rgbMat.SetTexture ("_UTex", uvTex);
        Graphics.Blit (null, rgbRenderTex, yuv2rgbMat);

        // Only scan once per second
        if (timeSinceLastGPUTransfer > 1 / GPUTransferRate) {
            timeSinceLastGPUTransfer = 0;

            // Fetch its pixels and set it to rgb texture
            RenderTexture.active = rgbRenderTex;
            rgbTex.ReadPixels (new Rect (0, 0, width, height), 0, 0);
            rgbTex.Apply ();
            RenderTexture.active = null;

            rawRgbData = rgbTex.GetPixels32 ();
        } else {
            timeSinceLastGPUTransfer += Time.deltaTime;
        }
    }
}

推荐答案

好的,很抱歉,我必须自己回答问题.解决方案非常简单:

Ok, sorry that I have to answer my question on my own. The solution is very easy:

我在此行中使用的width和height属性:

The width and height property that I was using in this line:

rgbTex.ReadPixels (new Rect (0, 0, width, height), 0, 0);

未初始化的位置,因此它们在0的位置.

where not initialized, so they where 0.

我只需要将这些行添加到updateSize函数中即可:

I just had to add those lines to the updateSize function:

this.width = width;
this.height = height;

这篇关于如何在Unity中从RenderTexture访问原始数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆