WebCamTexture returns Black Texture on Android Browsers and WebGL

I’m trying to get QR Code from a webcam stream on WebGL app.
Something that is working when I play the app on the Editor.

When I run on browser, the raw image is showing the camera background correctly.

But when I try to get Pixels32 colors to decode it using ZXing, I’m always giving back black texture.

This happens working on Chrome and WebGL.

 m_CameraBuffer = m_WebCameraTexture.GetPixels32();

… and also using Chrome on Windows.

I’m using Unity Editor 2022.2.6f1

Any ideas why, any workaround?

I think that this is an issue related to performance and compatibility reasons, by default the browser will clear WebGL canvas’s drawing buffer after you’ve drawn to it, as stated in this article:

So I’ve tried to set
“preserveDrawingBuffer”: true

modifying my WebGLTemplate but the problem still persists. (Unity - Manual: WebGL graphics)

I don’t know how to procede and Unity documentation is not relaying about this kind of WebGL specific behaviours.

Now, I’m trying to explain better what I’m doing.
Consider this code and attach it to a Plane then add a button or whatever and call Scan():

using UnityEngine;
using System.Collections;
using ZXing;

public class QRCodeReader : MonoBehaviour
{
    public GameObject qrCodePlane;
    private WebCamTexture webCamTexture;

    IEnumerator Start()
    {
        // Request permission to use the camera
        yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);

        // If permission is granted, start the camera
        if (Application.HasUserAuthorization(UserAuthorization.WebCam))
        {
            // Get the default camera device
            WebCamDevice[] devices = WebCamTexture.devices;
            webCamTexture = new WebCamTexture(devices[0].name);

            // Start the camera
            qrCodePlane.GetComponent<Renderer>().material.mainTexture = webCamTexture;
            webCamTexture.Play();
        }
    }

    private IBarcodeReader barcodeReader;
    private Result m_ScanResult;

    public void Scan()
    {
        barcodeReader = new BarcodeReader { AutoRotate = false, Options = new ZXing.Common.DecodingOptions { TryHarder = false } };
        Color32[] m_CameraBuffer = webCamTexture.GetPixels32();
        m_ScanResult = barcodeReader.Decode(m_CameraBuffer, webCamTexture.width, webCamTexture.height);

        if (m_ScanResult != null)
        {
            Debug.Log("ChatGPT wins, you are a LOOSER");
        }
    }

    void Update()
    {
        // Check if the camera is playing and the texture is not null
        if (webCamTexture != null && webCamTexture.isPlaying)
        {
            // Capture a frame from the camera
            Texture2D texture = new Texture2D(webCamTexture.width, webCamTexture.height, TextureFormat.RGBA32, false);
            texture.SetPixels(webCamTexture.GetPixels());
            texture.Apply();
          
        }
    }
}

Working on: 2021.3.11f1
Not working on: 2022.2.6f1
Not working on: 2023.1.0b4

Try to run this on Chrome ( win or mobile doesn’t matter, the problem is present on both sides).

The problem is that the call to GetPixels32 is giving a totally black texture when built with 2022.2.6f1.

Hope someone says to me hot to make a build. My project is stucked.

The same problem. Unity Editor 2022.3.4f1. Android device. Camera is detected, 640x480, but all pixels are black.

I have this problem to, any update on it?

Same here :frowning: any workaround around?

This isn’t working for me as well

This issue is very critical in the app I am currently creating and I hope it will be fixed ASAP.

It appears that this issue has already been registered. Please vote for this issue.

So, there is a Terrible work around.
Blit the texture from the camera to a rendertexture > convert it to Texture2D > GetPixels32 from this Texture2D

Does this work - Yes
Is it performant - Hell no!
Should you do it - how desperate are you?

var rdTexture = new RenderTexture(camTexture.width, camTexture.height, 0);         
Graphics.Blit(camTexture, rdTexture);
texture2D = ToTexture2D(rdTexture);
var pixelData = texture2D.GetPixels32();

public Texture2D ToTexture2D(RenderTexture rTex)
{
    Texture2D tex = new Texture2D(rTex.width, rTex.height, TextureFormat.RGB24, false);
    var old_rt = RenderTexture.active;
    RenderTexture.active = rTex;

    tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
    tex.Apply();

    RenderTexture.active = old_rt;
    return tex;
}

Thank you a lot @Nyro ! Clever work around!
You unblocked our project, because we can at least test our complete workflows and demo for our client.
We can now wait for the official fix without struggling.

I’m also having this issue on 2022.3.32f1, any suggestions? The script didn’t work for me