Reading pixel data from material.mainTexture returns grey color

Hello everyone,

I am trying to get texture2d from a material, which I play a movie on it by using a plug-in. I create a texture2D and assigned materials.mainTexture component to it. I can draw that texture screen using GUI.DrawTexture but when I try to Encode it to PNG file or when I read colors using GetPixels I got (0.804,0.804,0.804,0.804).

Do you have an idea about this issue? I found out some problems related to textures appearing grey when texture data is lost but I couldn’t solve my problem.

I don’t understand that why I can draw texture correctly on screen but when I try to retrieve its content it is grey.

Is it because I convert Texture to Texture2D? I do this because I can’t read pixels from Texture.

	void Update () {
        if (_mat == null) return;
        tex = _mat.mainTexture as Texture2D;

        if (tex == null) return;
        for (int i = 0; i < 50; i++)
        {
            Debug.Log(tex.GetPixel(100, 100 + i)); // Prints (RGBA(0.804, 0.804, 0.804, 0.804))
        }
        
        count++;

	}

    void OnGUI() {
        GUI.DrawTexture(new Rect(0, 0, 200, 200), tex); // Draws texture correctly so its content is not grey
       
    }

Hey,

I had exactly the same problem.

It seems not to be possible to directly convert from Texture to Texture2D.
You can solve the problem by first converting the Texture into RenderTexture using Graphics.Blit() and then save it as Texture2D.

Now you can call GetPixel() or encode it as PNG or JPG and it works.

            Texture mainTexture = renderer.material.mainTexture;
            Texture2D texture2D = new Texture2D(mainTexture.width, mainTexture.height, TextureFormat.RGBA32, false);

            RenderTexture currentRT = RenderTexture.active;

            RenderTexture renderTexture = new RenderTexture(mainTexture.width, mainTexture.height, 32);
            Graphics.Blit(mainTexture, renderTexture);

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

            Color[] pixels = texture2D.GetPixels();

            RenderTexture.active = currentRT;

I using a Texture to Texture2D casting

example

Texture2D t = (Texture2D)GetComponent().material.mainTexture;

Debug.Log(t.GetPixel(100, 100));

I’ve found a shorter way, so hopefully this is useful for someone who stumble the same issue, apparently its because Graphics.CopyTexture uses GPU, and GetPixels uses CPU, and this is where the synchronization issues are happening. a way to work around that is to set the RenderTexture active, like code below:

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

Source link: https://forum.unity.com/threads/graphics-copytexture-then-getpixels.482601/

You maybe forgot to call Apply() method in the final texture!
I’ve this issue before.