【问题标题】:How to access raw data from RenderTexture in Unity如何在 Unity 中从 RenderTexture 访问原始数据
【发布时间】:2017-06-03 11:07:20
【问题描述】:

问题的简短版本

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

Graphics.Blit (null, renderTexture, material);

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

不过,我还需要二维码扫描仪的原始数据。我这样做就像我会按照here 的解释从相机访问它一样。在那里的评论中提到,也可以从填充了 Graphics.Blit 的 RenderTexture 中提取。但是当我尝试这样做时,我的纹理只包含 205 的值。这是我在 Update 函数中使用的代码,直接在 Graphics.Blit 调用之后:

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

当将此纹理分配给同一个 UI 元素时,它是灰色的并且略微透明。查看图像值时,都是205。

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

完整代码

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

/** 
 * 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;
        }
    }
}

【问题讨论】:

    标签: c# unity3d framebuffer rendertarget


    【解决方案1】:

    好的,抱歉,我必须自己回答我的问题。解决方法很简单:

    我在这一行中使用的宽度和高度属性:

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

    哪里没有初始化,所以他们哪里是0。

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

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

    【讨论】:

      猜你喜欢
      • 2021-10-12
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      • 2012-01-22
      • 2021-11-28
      • 2011-01-07
      • 2021-11-22
      • 1970-01-01
      相关资源
      最近更新 更多