Reputation: 197
I am generating a texture2D from the code given below. But instead of Rect, I want to transfer the contents of my Render Texture onto Texture2D. As my render texture is attached to a secondary camera.
I want to Copy the contents to the Texture2D I am generating inside the code. How do I achieve this?
public RenderTexture rt;
Texture2D mTexture;
Rect mRect;
void Start () {
//Create a rectangle width and height of the screen
mRect = new Rect (0, 0, Screen.width, Screen.height);
//Create a texture the size of the rectangle you just created
mTexture = new Texture2D ((int) mRect.width, (int) mRect.height, TextureFormat.BGRA32, false); //Get RenderTexture contents
}
void Update()
{
StartCoroutine (GetBytes_RT());
}
IEnumerator GetBytes_RT() {
yield return new WaitForEndOfFrame ();
//Read the Pixels inside the Rectangle
mTexture.ReadPixels (mRect, 0, 0);
//Apply the Pixels read from the rectangle to the texture
mTexture.Apply ();
// Get the Raw Texture data from the the from the texture and apply it to an array of bytes
byte[] bytes = mTexture.GetRawTextureData ();
// Make enough space for the bytes array
int size = Marshal.SizeOf (bytes[0]) * bytes.Length;
}
Upvotes: 1
Views: 374
Reputation: 90629
See ReadPixels
This will copy a rectangular pixel area from the currently active RenderTexture or the view (specified by the source parameter) into the position defined by destX and destY. Both coordinates use pixel space - (0,0) is lower left.
So before reading you would also set the RenderTexture.active
otherwise it just reads from the entire screen output
// Store the current RenderTexture (if any at all)
var beforeActiveRenderTexture = RenderTexture.active;
// Make your RenderTexture the active one
RenderTexture.active = rt;
// Now read from the active RenderTexture
mTexture.ReadPixels (mRect, 0, 0);
mTexture.Apply();
// Restore whatever was the previous state
RenderTexture.active = beforeActiveRenderTexture;
byte[] bytes = mTexture.GetRawTextureData ();
int size = Marshal.SizeOf (bytes[0]) * bytes.Length;
In general instead of starting a new routine every frame and using class fields I personally would rather use something like
// Yes if you use this return type Untiy automatically runs it as a Coroutine
IEnumerator Start ()
{
var rect = new Rect (0, 0, rt.width, rt.height);
var texture = new Texture2D (rect.width, rect.height, TextureFormat.BGRA32, false);
// Yes this is fine as long as you yield somewhere inside
while(true)
{
yield return new WaitForEndOfFrame ();
var beforeActiveRenderTexture = RenderTexture.active;
RenderTexture.active = rt;
texture.ReadPixels (rect, 0, 0);
texture.Apply();
RenderTexture.active = beforeActiveRenderTexture;
var bytes = texture.GetRawTextureData();
var size = Marshal.SizeOf (bytes[0]) * bytes.Length;
}
}
Upvotes: 1