Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411512 Posts in 69376 Topics- by 58430 Members - Latest Member: Jesse Webb

April 26, 2024, 08:18:48 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Texture2D.ReadPixels doesn't capture image effects
Pages: [1]
Print
Author Topic: Texture2D.ReadPixels doesn't capture image effects  (Read 3859 times)
Armageddon
Level 6
*



View Profile
« on: August 31, 2015, 11:52:42 AM »

Hi all, I'm making a game where you play as a photographer and you can show your photos to people. I needed to set the camera to a specific aspect ratio so your photos would fit the UI properly no matter the resolution and I decided to capture the screen with a Texure2D since RenderTexture wasn't working well.

The problem I'm having is that the Texture2D is not capturing any image effects. I've read that image effects are rendered in the order they're stacked in the camera GameObject, so I put my screenshot script at the bottom and even tried the top. No such luck.

Here's the main part of my script:

Code: (C#)
    	void SnapPhoto() {
     //yield return new WaitForEndOfFrame();
     Texture2D tex = new Texture2D(screenWidth,screenHeight, TextureFormat.RGBAFloat, false);
     tex.ReadPixels(new Rect(0,0,screenWidth,screenHeight),0,0, false);
     //tex.ReadPixels(screenRect,0,0, false);
     tex.Apply();
     //tex.EncodeToPNG();
    
     byte[] bytes = tex.EncodeToPNG();
     File.WriteAllBytes(Application.dataPath + "/../SavedScreen.png", bytes);
     //Application.CaptureScreenshot(Application.dataPath + "/../SavedScreenBIG.png");
    
     //bytes = File.ReadAllBytes(
    
     tex.LoadImage(bytes);
     //rawPhotoImg.texture = tex;
     photoImg.overrideSprite = Sprite.Create(tex,new Rect(0,0,tex.width,tex.height),new Vector2(0f,0f), 100);
     shutterImg.enabled = false;
    
     /*//float originalAspect = Camera.main.aspect;
     //Camera.main.aspect = 1.5f;
     RenderTexture rt = new RenderTexture(screenWidth,screenHeight,24,RenderTextureFormat.ARGBFloat);
     //rt.useMipMap = false;
     rt.Create();
     Camera.main.targetTexture = rt;
     //Camera.main.Render();
     RenderTexture.active = rt;
     Texture2D tex = new Texture2D(rt.width,rt.height, TextureFormat.RGBAFloat, false);
     tex.ReadPixels(new Rect(0,0,rt.width,rt.height),0,0, false);
     RenderTexture.active = null;
     Camera.main.targetTexture = null;
     byte[] bytes = tex.EncodeToPNG();
     File.WriteAllBytes(Application.dataPath + "/../SavedScreen.png", bytes);
     tex.LoadImage(bytes);
     photoImg.overrideSprite = Sprite.Create(tex,new Rect(0,0,tex.width,tex.height),new Vector2(0f,0f), 100);
     shutterImg.enabled = false;
     //Camera.main.aspect = originalAspect;*/
     }
    
     void OnPostRender() {
     if (doSnap) {
     doSnap = false;
     //Camera.main.Render();
     //StartCoroutine("SnapPhoto");
     SnapPhoto();
     }
     //SnapPhoto();
     }

I'm calling SnapPhoto() in OnPostRender() which should be doing the ReadPixels after the last camera render? I've tried calling it in LateUpdate() and Update() but nothing seems to capture the image effects. Here's a picture:


The script isn't super advanced yet, later I'm going to add a thing to create a new Photo object and add it to a UI panel with all the information needed. For now it just replaces a UI image.

I've been wrestling with this for a week and I'm all out of ideas. The thing is I think it was working before when I only had an SSAO effect. That was when the game was still in Gamma color space and the camera didn't have HDR. I had to change the Texture2D TextureFormat to accommodate the Linear HDR or else I got some pretty glitchy images.
Logged

Armageddon
Level 6
*



View Profile
« Reply #1 on: August 31, 2015, 02:41:59 PM »

Okay so I've found these:

http://docs.unity3d.com/ScriptReference/Camera.OnRenderImage.html

http://answers.unity3d.com/questions/29267/texture2dreadpixels-on-rendertexture-in-depth-mode.html

Also the reason my image is darker than the game appears is because of this I think?

http://forum.unity3d.com/threads/reading-pixelsfrom-argbhalf-render-texture.77280/

Anyways OnRenderImage displays the Unity UI well enough, but everything else is black, maybe it's because the default RenderTextures are null? I don't know what to set the material too. If I set the RenderTextures to the Camera.main.targetTexture it show the UI, if I don't the screen is just grey.

So no closer really but at least this is called after the post effects are done.
Logged

Armageddon
Level 6
*



View Profile
« Reply #2 on: August 31, 2015, 06:15:41 PM »

Yet another reply. Turns out my RenderTarget method worked all along, only problem is that the images are almost totally transparent and it looks like it's only rendering to a depth of about 10 units in front of the camera. I won't bother to post a screenshot, if I duplicate it a ton of times in an image editor a regular looking image with the image effects emerged.

Code: (C#)
                RenderTexture rt = new RenderTexture(screenWidth, screenHeight, 24, RenderTextureFormat.ARGBFloat);        
Texture2D screenShot = new Texture2D(screenWidth, screenHeight, TextureFormat.RGBAFloat, false);

I can't find any HDR TextureFormat for either that doesn't have transparency. I don't think I can convert a Texture2D to LDR either.
Logged

Armageddon
Level 6
*



View Profile
« Reply #3 on: August 31, 2015, 07:03:26 PM »

Sorry to spam this I guess but I think I've reached a dead end where it's a fault of Unity.

http://forum.unity3d.com/threads/using-render-textures-on-a-ugui-image-panel-or-button.272332/

http://forum.unity3d.com/threads/render-textures-are-transparent.4972/

I tried nearly every solution from both of these threads and none worked at all. I read a snippet somewhere saying Unity was going to fix it in the next version but who knows.
Logged

Armageddon
Level 6
*



View Profile
« Reply #4 on: August 31, 2015, 11:21:10 PM »

Well the code works absolutely flawlessly in Gamma color space, has the image effects and everything. In Linear it's a big blobby transparent mess because RenderTextures don't have a non-transparent HDR TextureFormat. Here's my final code if anyone's struggling, though it still doesn't support Linear like I said:

Code: (C#)
	IEnumerator SnapPhoto() {
yield return new WaitForEndOfFrame();

RenderTexture rt = new RenderTexture(screenWidth, screenHeight, 24, RenderTextureFormat.Default);        
Texture2D screenShot = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);

foreach(Camera cam in Camera.allCameras)
{
cam.targetTexture = rt;
cam.Render();
cam.targetTexture = null;
}

RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0, false);
Camera.main.targetTexture = null;
RenderTexture.active = null;
Destroy(rt);

yield return 0;

byte[] bytes = screenShot.EncodeToPNG();
File.WriteAllBytes(Application.dataPath + "/../testscreen-" + count + ".png", bytes);
count++;

screenShot.LoadImage(bytes); //this isn't really needed but just to be safe
photoImg.overrideSprite = Sprite.Create(screenShot,new Rect(0,0,screenShot.width,screenShot.height),new Vector2(0f,0f), 100); //this is your uGUI Image
shutterImg.enabled = false; //purely for my game
}

Linear rendering sure was pretty though, I guess I can always revisit this in the future no need to hold up development entirely for one problem.

EDIT: Oh darn, RenderTexture is stretching weirdly.


And it's not the uGUI Image it's in the source .png too. I can probably fix it just really brain dead right now.
« Last Edit: August 31, 2015, 11:40:30 PM by Armageddon » Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic