Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Rendering screenshot larger than screen resolution

Discussion in 'Scripting' started by trudnai, Jul 1, 2014.

  1. trudnai

    trudnai

    Joined:
    Jul 8, 2013
    Posts:
    12
    Hi Guys,

    I try to create a skybox out of a rendered game scene, and for that wanted to render a specific screenshot for 6 directions with a camera. What I wanted to achieve is to render the screenshot in 4096x4096 but instead of getting a large box I get a white box with a small screenshot at the bottom of it. The screen is much smaller than 4096, but I know all my textures are in 4096 so theoretically I should be able to do this, should not I?

    Any ideas where to look at samples or guidance as so far non of the examples I have found seem to work for me. Again, I do not want to upscale the image with interpolation, but get the 1:1 native resolution of the scene into a texture buffer and then save that into a file.
     
  2. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    maybe this can help you (not sure). if you want to invest into unity pro you could use rendertextures for that.
     
  3. trudnai

    trudnai

    Joined:
    Jul 8, 2013
    Posts:
    12
    Thanks, that asset looks nice, however, I was trying to avoid upscaling anti-aliased or not. Actually I was trying to achieve this with RenderTexture, and still using the Free version of Unity3D -- planning to buy it soon, but I was not aware that the render to texture "almost" works, no error or warning but just wrong results? Still thinking if I am doing something wrong here?

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class HiResScreenShots : MonoBehaviour {
    5.     public int resWidth = 1024;
    6.     public int resHeight = 1024;
    7.  
    8.     public static string ScreenShotName(int width, int height) {
    9.         return string.Format("{0}/Screenshots/screen_{1}x{2}_{3}.png",
    10.                              Application.dataPath,
    11.                              width, height,
    12.                              System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
    13.     }
    14.  
    15.     void LateUpdate() {
    16.         if ( Input.GetKeyDown("k") ) {
    17.             RenderTexture rt = new RenderTexture(resWidth, resHeight, 24);
    18.             RenderTexture origRT = RenderTexture.active;
    19.             RenderTexture.active = rt;
    20.  
    21.             // create screenshot
    22.             Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false);
    23.             camera.targetTexture = rt;
    24.             camera.Render();
    25.             screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
    26.             camera.targetTexture = null;
    27.  
    28.             // revert to original render texture
    29.             RenderTexture.active = origRT;
    30.             Destroy(rt);
    31.  
    32.             // create image file
    33.             byte[] bytes = screenShot.EncodeToPNG();
    34.             string filename = ScreenShotName(resWidth, resHeight);
    35.             System.IO.File.WriteAllBytes(filename, bytes);
    36.             Debug.Log(string.Format("Took screenshot to: {0}", filename));
    37.         }
    38.     }
    39. }
    40.  
    This is what I get (see attached screenshot) Screen Shot 2014-07-01 at 12.34.49.PNG

    Edit: What you can see is that the original screen with the correct content of it is at the bottom-left and the rest of the 1024x1024 area is "clean". What I would like to do is to re-render the scene for that screenshot in a 1024x1024 (later on 4096x4096) virtual screen and take the screenshot for that instead of the displayed screen.

    (Trying to create a skybox out of the rendered scene)

    Thanks,
    Tamas
     
    Last edited: Jul 1, 2014
  4. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    do you set the camera which renders into the rt to the proper resolution? i'm not sure wether they support 4096² resolution but try to set it 1024². thats all i can think of.
    you could fe setup a separate camera to render the skybox once in start of a script and then discard it when its done.
     
  5. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
    Code (CSharp):
    1.     void LateUpdate() {
    2.         Camera Mcamera = Camera.main;
    3.         if(Input.GetKeyDown(KeyCode.S)) {
    4.             int rw = (int)Mathf.Round(Mcamera.pixelWidth * 4);
    5.             int rh = (int)Mathf.Round(Mcamera.pixelHeight * 4);
    6.             RenderTexture rt = new RenderTexture(rw, rh, 24);
    7.             Mcamera.targetTexture = rt;
    8.             Texture2D ss = new Texture2D(rw, rh, TextureFormat.RGB24, false);
    9.             Mcamera.Render();
    10.             RenderTexture.active = rt;
    11.             ss.ReadPixels(new Rect(0, 0, rw, rh), 0, 0);
    12.             Mcamera.targetTexture = null;
    13.             RenderTexture.active = null;
    14.             Destroy(rt);
    15.             byte[] bytes = ss.EncodeToPNG();
    16.             string filename = "screenshot.png";
    17.             System.IO.File.WriteAllBytes(filename, bytes);
    18.             Debug.Log(string.Format("Took screenshot to: {0}", filename));
    19.         }
    20.     }
     
  6. trudnai

    trudnai

    Joined:
    Jul 8, 2013
    Posts:
    12
    For some reason the screen resolution is the one it snaps to. So the only workaround I had right now is to compile it to standalone and set screen res to the one I want, do the screenshots. Bit of work, but at least there is a workaround, right? ;-)

    Thanks for the help anyways!
     
  7. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
    If you just want higher resolution, then script in my message above will work.
    If you want different aspect ratio for camera then you have to specify it before taking a picture and reset it back after. Then it will look like this:

    Code (CSharp):
    1.     void LateUpdate() {
    2.         Camera Mcamera = Camera.main;
    3.         if(Input.GetKeyDown(KeyCode.S)) {
    4.             int rw = (int)Mathf.Round(10000);
    5.             int rh = (int)Mathf.Round(1000);
    6.             RenderTexture rt = new RenderTexture(rw, rh, 24);
    7.             Mcamera.targetTexture = rt;
    8.             Texture2D ss = new Texture2D(rw, rh, TextureFormat.RGB24, false);
    9.             float a = Mcamera.aspect;
    10.             Mcamera.aspect = rw / rh;
    11.             Mcamera.Render();
    12.             RenderTexture.active = rt;
    13.             ss.ReadPixels(new Rect(0, 0, rw, rh), 0, 0);
    14.             Mcamera.targetTexture = null;
    15.             RenderTexture.active = null;
    16.             Mcamera.aspect = a;
    17.             Destroy(rt);
    18.             byte[] bytes = ss.EncodeToPNG();
    19.             string filename = "screenshot.png";
    20.             System.IO.File.WriteAllBytes(filename, bytes);
    21.             Debug.Log(string.Format("Took screenshot to: {0}", filename));
    22.         }
    23.     }
     
    vonSchlank likes this.
  8. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
    And of course if you are still using your own code, need to fix your mistakes there.
     
  9. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
    Example with AngryBots.
     

    Attached Files:

  10. Agent_007

    Agent_007

    Joined:
    Dec 18, 2011
    Posts:
    899
    First, resurrect apologies to all parties. (OLD thread is OLD)

    I reworked the script zaxvax posted earlier to better match the current situation
    Code (csharp):
    1.  
    2. private IEnumerator takeshot()
    3.     {
    4.         // We should only read the screen buffer after rendering is complete
    5.         yield return new WaitForEndOfFrame();
    6.  
    7.         Camera Mcamera = Camera.main;
    8.         int rw = 3840;
    9.         int rh = 2160;
    10.         RenderTexture rt = new RenderTexture(rw, rh, 24);
    11.         Mcamera.targetTexture = rt;
    12.         Texture2D ss = new Texture2D(rw, rh, TextureFormat.RGB24, false);
    13.         float a = Mcamera.aspect;
    14.         Mcamera.aspect = (float)rw / (float)rh;
    15.         Mcamera.Render();
    16.         RenderTexture.active = rt;
    17.         ss.ReadPixels(new Rect(0, 0, rw, rh), 0, 0);
    18.         Mcamera.targetTexture = null;
    19.         RenderTexture.active = null;
    20.         Mcamera.aspect = a;
    21.         Destroy(rt);
    22.         byte[] bytes = ss.EncodeToPNG();
    23.         string filename = "screenshotBIG.png";
    24.         System.IO.File.WriteAllBytes(filename, bytes);
    25.         Debug.Log(string.Format("Took screenshot to: {0}", filename));
    26.     }
    27.  
    and it can be called with StartCoroutine(takeshot());