- Home /
Faster way to encode RenderTexture to png
So, I have an in-game camera the player can use, and I would like to be able to save the images instantly without noticing a lag. So far, I create render a camera into a RenderTexture and I feed it in this extension method:
public static void SaveToFile(this RenderTexture renderTexture, string name)
{
RenderTexture currentActiveRT = RenderTexture.active;
RenderTexture.active = renderTexture;
Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height);
tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
var bytes = tex.EncodeToPNG();
System.IO.File.WriteAllBytes(name, bytes);
UnityEngine.Object.Destroy(tex);
RenderTexture.active = currentActiveRT;
}
It does work, but ReadPixels is slow as hell and it creates a noticeable hiccup. I tried several ways to smooth out the performance spike created by it. First, I tried to call this method from another thread, but it has to be called in the main thread. Then, I tried to use renderTexture.GetNativeTexturePtr() with Marshal.Copy(), but I can't find a way to do it. I guess the only other way is to make a Native plugin, but my knowledge in C/C++ is pretty limited. Anybody has any idea on this?
Answer by AlexeyDrobyshevsky · Jan 22, 2021 at 12:18 PM
(This method wasn't available back when the question was asked, but it's still on the first page of google so) The modern (2019+) method to do that is to read texture data using AsyncGPUReadback (https://docs.unity3d.com/ScriptReference/Rendering.AsyncGPUReadback.html) - it's not fast, but it does not block the main thread at least; and then encode the data using ImageConversion.EncodeArrayToPNG (https://docs.unity3d.com/ScriptReference/ImageConversion.EncodeArrayToPNG.html) or a similar method. This one blocks, but according to the docs it's thread-safe.
Constructive necro posts which are on topic like this one are welcome :) Since the OP hasn't been seen for 3+ years I accepted this answer for now.
Answer by yoyo · Sep 13, 2014 at 06:23 AM
Have a look at Application.CaptureScreenshot, I believe it runs asynchronously, and handles all the file I/O for you as well.
More information on this Unity wiki page, which outlines several methods of capturing screenshots.
Your answer
Follow this Question
Related Questions
Save and load data via Facebook SDK 0 Answers
Using Texture2D.ReadPixels with a RenderTexture that has AntialiasingAsPostEffect 0 Answers
Pass a RenderTexture to a plugin with zero copies 2 Answers
Render to RenderTexture in android/gles (plugin) 0 Answers
Can a Texture2D be created at runtime from a snapshot of a RenderTexture? 3 Answers