- Home /
How to capture screenshot with post process effect?
Im using Edge detection post process effect (https://docs.unity3d.com/540/Documentation/Manual/script-EdgeDetectEffectNormals.html) Script is attached to my camera and wondering how to capture screen with this effect. What I expect: What i have:
My outlines are renderer via shader and everything looks great at runtime. The problem is how to apply post effect to my rendertexture.
private Rect rect;
private RenderTexture renderTexture;
private Texture2D screenShot;
ImageFormat format = ImageFormat.PPM;
private void CreateScreenShoot()
{
camera.targetTexture = renderTexture;
camera.Render();
// read pixels will read from the currently active render texture so make our offscreen
// render texture active and then read the pixels
RenderTexture.active = renderTexture;
screenShot.ReadPixels(rect, 0, 0);
// reset active camera texture and render texture
camera.targetTexture = null;
RenderTexture.active = null;
DataStorageBase.CreateDirectory(DataStorageBase.MiniaturesDataPath);
string filename = Path.Combine(DataStorageBase.MiniaturesDataPath, DataStorageBase.ChosenImage + DataStorageBase.MiniaturesSavingExtension);
// string filename = Path.Combine(DataStorageBase.MiniaturesDataPath, DataStorageBase.ChosenImage + ".png");
SaveTexture(filename,screenShot, format);
}
private static void SaveTexture(string filename, Texture2D screenShot, ImageFormat format)
{
// pull in our file header/data bytes for the specified image format (has to be done from main thread)
byte[] fileHeader = null;
byte[] fileData = null;
if (format == ImageFormat.RAW)
{
fileData = screenShot.GetRawTextureData();
}
else if (format == ImageFormat.PNG)
{
fileData = screenShot.EncodeToPNG();
}
else if (format == ImageFormat.JPG)
{
fileData = screenShot.EncodeToJPG();
}
else // ppm
{
// create a file header for ppm formatted file
string headerStr = string.Format("P6\n{0} {1}\n255\n", screenShot.width, screenShot.height);
fileHeader = System.Text.Encoding.ASCII.GetBytes(headerStr);
fileData = screenShot.GetRawTextureData();
}
Debug.Log(filename);
// create new thread to save the image to file (only operation that can be done in background)
new System.Threading.Thread(() =>
{
// create file and write optional header with image bytes
var f = System.IO.File.Create(filename);
if (fileHeader != null)
f.Write(fileHeader, 0, fileHeader.Length);
f.Write(fileData, 0, fileData.Length);
f.Close();
}).Start();
}
shot it the dark here.. but in the docs for camera.Render():
You are not able to call the Render function from a camera that is currently rendering. If you wish to do this create a copy of the camera, and make it match the original one using CopyFrom.
Thanks for reply. Well camera script is disabled and i call camera.render to enable it. I forgot to mention that i have two cameras. First is main camera which render everything, and second one which render only shapes (like in picture above) and this camera is enable only when i want to capture a screenshot.
Answer by Hylus · Sep 19, 2019 at 08:58 AM
I find origin problem. Camera.render doesn't invoke OnRenderImage in my post effect script. Does exist any solution to invoke and correctly execute OnRenderImage after calling camera.render in the same frame? Because users couldn't see any changes in camera.
OnRenderImage is used to generate post processing effects(according to docs), so kinda makes sense it's not invoked inside the post-processing stuff. Perhaps OnPostRender() would work better for this part?
please explain what do you mean. Should i move some part of my code to onPostRender?
Yes, that's what I was suggesting- but honestly, it's just a guess.
Your answer
Follow this Question
Related Questions
Skybox and color correction with steamVR 0 Answers
Changing Post process V2 with C# 0 Answers
Running an OnRenderImage effect before the post processing stack (v2) 1 Answer
Unity Camera Capture for Android to video file 4 Answers
Is there any way to apply different textures to a plane on front and back? 1 Answer