how do you read pixels from a Custom Render Texture?

I tried this but the value of the pixel never changes.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReadCRT : MonoBehaviour {
public CustomRenderTexture texture;
public int index = 0;
    Texture2D output;
    void Start()
    {
        output = new Texture2D(1000, 1000);
    }
    void Update () {
        CustomRenderTexture.active = texture;
        output.ReadPixels(new Rect(0, 0, 1000, 1000), 0, 0);
        Debug.Log(index +" ... "+output.GetPixel(index, index));
    }
}

I’m using this example as customrendertexture GitHub - keijiro/RDSystem: Reaction-diffusion system with CustomRenderTexture.

Where does anything actually get rendered to the RenderTexture? (You’re setting it as active and immediately reading from it.)

Set it as target for a Camera and then do the ReadPixels part after the Camera is done rendering. (OnPostRender with the script being on the same GameObject as the Camera.)

Can’t do that, this CRT is used to calculate some gameplay stuff that I need to read from, no render.

Any luck with this? i need the same thing

@Branxord You need to copy the texture back from GPU to the CPU side of the things. You can do that with ReadPixels. Looks like the post above is almost correct?

Only thing I can see missing is the texture.Apply(). If you don’t apply a texture when you have set the pixels, it won’t get stored/saved. You should call it right after the texture.ReadPixels.

Here are a few links about this topic:

It’s not very fast and is said to cause some stalling so use it with consideration. i.e. probably not wise to try get a copy of some big texture every frame.

I’ve used it quite often when I’ve been testing if my compute shader experiments function at all. I’ve used very small test textures then (like 32x32 or 64x64) to read data back.

1 Like

Oh ok, yeah i kinda got it working now, except i need to know the coordinates of the pixels i retrieved (i’m doing a for loop and checking the GetPixels array) but i’m not finding a way to get the coords so far :frowning:

If you get the RenderTexture copied to a texture, just get the coordinates? :slight_smile:
I mean, it’s just an image? If you point to coordinate x=32, y=32, it’s that pixel.

Did you check the examples I linked? When you copy the RT to same resolution image, it’s a copy. I’m not sure what you are missing.

Assuming you have a RenderTexture rendered somewhere, like a compute shader that you dispatched just a moment before:

RenderTexture.active = myRenderTexture;
myTexture2D.ReadPixels(new Rect(0, 0, myRenderTexture.width, myRenderTexture.height), 0, 0);
myTexture2D.Apply();

Now your myTexture2D will have the size of the myRenderTexture.

1 Like

Sorry i was talking about a Texture2D, not a RT, i didnt specify that. Also i did read your links, again sorry, but it’s not what i’m looking for now.

Here’s what i’m doing so far:

EDIT: Just so you see that this works so far, here’s 2 gifs showing a completely white texture and a white texture with black spots, i’m trying to spawn quads in the black pixels but i need a position.
1: https://gyazo.com/8f43d168e4ead7964948153bf578d6dd
2: https://gyazo.com/0425c01a18ad34c1e37ded6c4ea42851

 void IsBlackOrWhite(Texture2D tex)
    {
        Color[] colorArray = tex.GetPixels(0, 0, tex.width, tex.height);
        for (int i = 0; i < colorArray.Length; i++)
        {
            if (colorArray[i].grayscale == 0)
            {
                GameObject grassTemp = Instantiate(grass,this.transform,true);
                grassTemp.transform.position = new Vector3(colorArray[i].grayscale, 1.7f, colorArray[i].grayscale);
                grassTemp.transform.eulerAngles = new Vector3(45,-180,0);
              
            }
          
        }
      
    }

Was there a best rule of thumb for this?
I’m about to need exactly that using a CustomRenderTexture that’s revealing terrain/gameplay stuff that’s double buffered (accumulates over time), most of the suggested samples are RenderTextures assigned to the camera (which isn’t what Custom Render Texture are meant to be used as).
Will be trial and error-ing and come back if I find something that works.

Any luck? I’m trying to use a similar method to read pixel color from a shadergraph material with multiple textures, to color dust particles correctly. Having a hard time finding relevant examples.

No, excuse me that, the whole feature I was doing where I was going to use that got put on the side potentially forever. Got sidetracked to other things higher in priority. If I ever get back to that I’ll be sure to post back here.

Recommend Unity - Scripting API: AsyncGPUReadback so you can then store the data copy and read from it without stalling the pipeline.