-
-
Save bitbutter/302da1c840b7c93bc789 to your computer and use it in GitHub Desktop.
using UnityEngine; | |
using System.Collections; | |
using System.IO; | |
/* | |
Usage: | |
1. Attach this script to your chosen camera's game object. | |
2. Set that camera's Clear Flags field to Solid Color. | |
3. Use the inspector to set frameRate and framesToCapture | |
4. Choose your desired resolution in Unity's Game window (must be less than or equal to your screen resolution) | |
5. Turn on "Maximise on Play" | |
6. Play your scene. Screenshots will be saved to YourUnityProject/Screenshots by default. | |
*/ | |
public class TransparentBackgroundScreenshotRecorder : MonoBehaviour { | |
#region public fields | |
[Tooltip("A folder will be created with this base name in your project root")] | |
public string folderBaseName = "Screenshots"; | |
[Tooltip("How many frames should be captured per second of game time")] | |
public int frameRate = 24; | |
[Tooltip("How many frames should be captured before quitting")] | |
public int framesToCapture = 24; | |
#endregion | |
#region private fields | |
private string folderName = ""; | |
private GameObject whiteCamGameObject; | |
private Camera whiteCam; | |
private GameObject blackCamGameObject; | |
private Camera blackCam; | |
private Camera mainCam; | |
private int videoFrame = 0; // how many frames we've rendered | |
private float originalTimescaleTime; | |
private bool done=false; | |
private int screenWidth; | |
private int screenHeight; | |
private Texture2D textureBlack; | |
private Texture2D textureWhite; | |
private Texture2D textureTransparentBackground; | |
#endregion | |
void Awake () { | |
mainCam = gameObject.GetComponent<Camera>(); | |
CreateBlackAndWhiteCameras (); | |
CreateNewFolderForScreenshots (); | |
CacheAndInitialiseFields (); | |
Time.captureFramerate = frameRate; | |
} | |
void LateUpdate () { | |
if(!done){ | |
StartCoroutine(CaptureFrame()); | |
} else { | |
Debug.Log("Complete! "+videoFrame+" videoframes rendered. File names are 0 indexed)"); | |
Debug.Break(); | |
} | |
} | |
IEnumerator CaptureFrame (){ | |
yield return new WaitForEndOfFrame(); | |
if(videoFrame < framesToCapture) { | |
RenderCamToTexture(blackCam,textureBlack); | |
RenderCamToTexture(whiteCam,textureWhite); | |
CalculateOutputTexture (); | |
SavePng (); | |
videoFrame++; | |
Debug.Log("Rendered frame " +videoFrame); | |
videoFrame++; | |
} else { | |
done=true; | |
StopCoroutine("CaptureFrame"); | |
} | |
} | |
void RenderCamToTexture (Camera cam, Texture2D tex){ | |
cam.enabled=true; | |
cam.Render(); | |
WriteScreenImageToTexture(tex); | |
cam.enabled=false; | |
} | |
void CreateBlackAndWhiteCameras (){ | |
whiteCamGameObject = (GameObject) new GameObject(); | |
whiteCamGameObject.name="White Background Camera"; | |
whiteCam=whiteCamGameObject.AddComponent<Camera>(); | |
whiteCam.CopyFrom(mainCam); | |
whiteCam.backgroundColor=Color.white; | |
whiteCamGameObject.transform.SetParent(gameObject.transform, true); | |
blackCamGameObject = (GameObject) new GameObject(); | |
blackCamGameObject.name="Black Background Camera"; | |
blackCam=blackCamGameObject.AddComponent<Camera>(); | |
blackCam.CopyFrom(mainCam); | |
blackCam.backgroundColor=Color.black; | |
blackCamGameObject.transform.SetParent(gameObject.transform, true); | |
} | |
void CreateNewFolderForScreenshots (){ | |
// Find a folder name that doesn't exist yet. Append number if necessary. | |
folderName = folderBaseName; | |
int count = 1; | |
while (System.IO.Directory.Exists (folderName)) { | |
folderName = folderBaseName + count; | |
count++; | |
} | |
System.IO.Directory.CreateDirectory (folderName); // Create the folder | |
} | |
void WriteScreenImageToTexture (Texture2D tex){ | |
tex.ReadPixels (new Rect (0, 0, screenWidth, screenHeight), 0, 0); | |
tex.Apply (); | |
} | |
void CalculateOutputTexture (){ | |
Color color; | |
for (int y = 0; y < textureTransparentBackground.height; ++y) { | |
// each row | |
for (int x = 0; x < textureTransparentBackground.width; ++x) { | |
// each column | |
float alpha = textureWhite.GetPixel (x, y).r - textureBlack.GetPixel (x, y).r; | |
alpha = 1.0f - alpha; | |
if (alpha == 0) { | |
color = Color.clear; | |
} | |
else { | |
color = textureBlack.GetPixel (x, y) / alpha; | |
} | |
color.a = alpha; | |
textureTransparentBackground.SetPixel (x, y, color); | |
} | |
} | |
} | |
void SavePng (){ | |
string name = string.Format ("{0}/{1:D04} shot.png", folderName, videoFrame); | |
var pngShot = textureTransparentBackground.EncodeToPNG (); | |
File.WriteAllBytes (name, pngShot); | |
} | |
void CacheAndInitialiseFields (){ | |
originalTimescaleTime = Time.timeScale; | |
screenWidth = Screen.width; | |
screenHeight = Screen.height; | |
textureBlack = new Texture2D (screenWidth, screenHeight, TextureFormat.RGB24, false); | |
textureWhite = new Texture2D (screenWidth, screenHeight, TextureFormat.RGB24, false); | |
textureTransparentBackground = new Texture2D (screenWidth, screenHeight, TextureFormat.ARGB32, false); | |
} | |
} |
Hello. It would seem this script is unable to render post-process effects. Would this be something that could be enabled?
Cheers.
is it working fo urp?
test in urp2022. the bg is black not tranparent
hi I found the problem in URP and resolve it:
the prolem is using cam.enable can not switch to next camera/overlap the previous camera, the "render screen" stay still in this case(URP).
so I turn to use a RenderTexture, to confirm render the needed screen via create and destory thr RenderTexture. here is the code, free to use:
https://gist.github.com/haosizheng/ee23b75dac7fb12f02cae55959dad59f#file-transparentbackgroundscreenshotrecorder-cs
Worked perfectly for me On Unity 2018.4.6f1.
And I manage to incorporate with post processing stack v2 effects
Just out of curiosity, how did you manage to do that? I have been trying to figure it out for a while.
perfect
Black on URP :(
Remove "videoFrame++;" line 70