Issues with Camera.Render()

Basically, I’m trying to render camera to Render to texture and then save that texture to disk as PNG file. It’s easy thing to do during runtime, I have it working, but I want to do it for my custom editor and not during the runtime.

After spending all day trying to figure out how to do it, I found out about rendering camera manually using Camera.Render().
So I tried that, and I thought it will work, because as documentation says onprerender, onpostrender and all those are called when rendering camera manually which is what I need (Unity - Scripting API: Camera.Render), how ever none of them are being called. I have a script attached to the camera with OnPreRender() and OnPostRender(), and when I manually render the camera through custom editor script, the camera DOES render manually, how ever none of those OnPreRender() etc. are being called…

What’s the problem? I seriously can’t figure out and I really need to get this working :frowning:

Thanks

when you do manual render you don’t need them, for the simple reason: you write the code before and after rendering :wink:

so you can do stuff like

  1. Set a rendertexture on the camera as target
  2. Call render
  3. Remove the texture again

there is no need for the overhead of the event handlers.

But when I do Camera.Render(), no matter if its in update function or not, and then try to save the render texture as png file by creating a texture2d, encoding to png etc… In other words it works fine during runtime, but when I try with manual rendering, it does create the texture and save it as png, how ever the image saved is not what was currently on that camera view/ render to texture, the saved image is just some crop out of unity interface lol. I remember same thing happened some time ago when I was trying to do pretty much same thing like now, but during runtime and the problem was that I was not doing it inside OnRenderImage() :S

That problem on the other hand is rather easy to fix: put the code that handles the taking of the screenshot exactly in there :slight_smile: (inside an if, if it is meant to happen at descrete points not each frame)

I know there is a screenshot script floating around that does exactly work like this to take a rendertexture based screenshot and encode it out to png by reading the pixels.

Yeh, I’ve got the code too, here it is and it works fine during runtime:

Sorry for sounding noobish, but where did you mean I should put the code that handles the taking of the screenshot to fix my problem? I didn’t quite get what you said there :wink:

The problem with this is, that it will never even run like this in the editor.
A first requirement to stand the slightest chance is [ExecuteInEditMode] attribute

But unsure if that on its own is enough cause editor is editor, its not meant to be runtime nor do the whole overhead the runtime has unless you are in play mode.

I’m not even sure if this is not a complete overkill here cause the cameras won’t render the effects etc either in the editor view.

Well all I need this for is to take a 32x32 snapshot of a single model, nothing complicated :slight_smile:

Edit:
Yay it worked with [ExecuteInEditMode] :slight_smile:
Thanks a bunch, dreamora. That will do for now, until I find a better way. At least I can put it aside now and go work on something else.

Ok, I “cheap-haxed” it and now it works perfectly fine for me and won’t be needing any modifications :slight_smile:

Here is how I’ve done it, so in case you need it as well, feel free to use it:

I create one script which handles the capturing:
(DO NOT ATTACH IT TO ANY CAMERA)

using UnityEngine;
using System.Collections;
using System.IO;
[ExecuteInEditMode]
public class CaptureIcon : MonoBehaviour {

public bool Capture = false;
byte[] iconTex = null;
public RenderTexture renderTexture;
	
void OnRenderImage(RenderTexture source, RenderTexture dest)
    {
		if (Capture) {
		CaptIcon();
			Capture = false;
			DestroyImmediate(GetComponent<CaptureIcon>());
		}
    }
	

public void CaptIcon() {
	Texture2D sshot = new Texture2D(renderTexture.width, renderTexture.height);
    sshot.ReadPixels(new Rect(0, 0,renderTexture.width, renderTexture.height), 0, 0);
    sshot.Apply();

  iconTex = sshot.EncodeToPNG();
	DestroyImmediate(sshot);
  File.WriteAllBytes(Application.dataPath+"/Resources/test1.png", iconTex);
		
	}
}

Then in the editor script, I’ve done this:

if (GUILayout.Button("capture")) {
dropCamera.AddComponent<CaptureIcon>();
dropCamera.GetComponent<CaptureIcon>().Capture = true;
}

where dropCamera is the camera with your RenderToTexture.
Basically the way it works is, when you click the button, it adds the CaptureIcon script to the camera, takes screen shot and destroys the script component as soon as icon is captured. :slight_smile:

Have fun and thanks dreamora for help :stuck_out_tongue:

glad it worked :slight_smile:

has some similarities to what I did back then with adding temporary components which are used only by the editor.

Now with U3 its even simpler cause you can make the component “meaningless” outside the editor through #if UNITY_EDITOR in case you have a tendency to forget stuff :wink: