I’ve been trying to actually use Unity’s AsyncGPUReadback.Request with Jint in JavaScript also, but mainly just in C#, to make a basic screenshot without the use of IEnumerable or yield return new WaitForEndOfFrame
or something (don’t remember exactly), but I want to use it only with checking the .done
property in an Update loop. I have not been able to find any examples online, though I have read the documentation on it multiple times.
First this attempt
var cam = Camera.main;
RenderTexture rat = new RenderTexture(
1920, 1080, 24
);
cam.targetTexture = rat;
Texture2D actual = new Texture2D(
1920, 1080,
TextureFormat.RGB24, false
);
cam.Render();
RenderTexture.active = rat;
/* actual.ReadPixels(new Rect(0, 0, 1920, 1080),
0, 0);*/
var reqt = AsyncGPUReadback.Request(rat);
System.Action fncc = null;
fncc = new System.Action(() => {
if(reqt.done) {
Debug.Log("well" + reqt.ToString());
var data = reqt.GetData<byte>(0);
Debug.Log(data);
Yaakov.removeEvent("Update", fncc);
}
});
Achdus.Yaakov.on("LateUpdate", fncc);//just some custom function to add events to the "Update" loop without monbehaviorus...
cam.targetTexture = null;
RenderTexture.active = null;
var bite = actual.EncodeToPNG();
System.IO.File.WriteAllBytes(
path, bite
);
gives me an error InvalidOperationException: Cannot access the data as it is not available
, have absolutely no idea how to fix this
By combining some functions from the FFMPegOut library as well as [another script I found on github][1] I kind of almost got something
static Material blat;
public static
void GetScreenshot(
string path,
System.Func<object, object> fnc
) {
var cam = Camera.main;
var form = (
cam
.allowHDR ? RenderTextureFormat
.DefaultHDR
:
RenderTextureFormat.Default
);
int aal = cam.allowMSAA ? QualitySettings.
antiAliasing : 1;
int width = 1920;
int height = 1080;
RenderTexture rt;
GameObject bl;
if(cam.targetTexture == null) {
rt = (
new RenderTexture(
width, height,
24, form
)
);
rt.antiAliasing = aal;
cam.targetTexture = rt;
bl = FFmpegOut
.Blitter
.CreateInstance(cam);
}
if(blat == null) {
var shayd = Shader.Find(
"Hidden/FFmpegOut/Preprocess"
);
blat = new Material(shayd);
}
var temp = RenderTexture.GetTemporary(
cam.targetTexture.width,
cam.targetTexture.height,
0,
RenderTextureFormat.ARGB32
);
Graphics.Blit(
cam.targetTexture,
temp,
blat,
0
);
var raq = UnityEngine
.Rendering
.AsyncGPUReadback.Request(
temp
);
System.Action fncc = null;
var k = 0;
fncc = new System.Action(() => {
if(raq.done) {
Debug.Log("ok man" + raq);
var newTaxt = new Texture2D(
cam.targetTexture.width,
cam.targetTexture.height,
TextureFormat.ARGB32, false
);
newTaxt.LoadRawTextureData(
raq.GetData<uint>()
);
newTaxt.Apply();
System.IO.File
.WriteAllBytes(
path,
ImageConversion
.EncodeToPNG(newTaxt)
);
Debug.Log("ok");
Yaakov.removeEvent("Update", fncc);//not important here just imagine its all in another update
}
});
Achdus.Yaakov.on("Update", fncc);//same as earlier just the same thing as having the above in an "Update" loop just without monos....
RenderTexture.ReleaseTemporary(temp);
}
which doesn’t give any errors but returns this
[![enter image description here][2]][2]
Don’t see much? Neither do I…
So does anyone actually know how to take a simple screenshot with AsyncGPUReadback.Request WITHOUT any IEnumerators?
And BTW, for those just wondering why not IEnumerators, many reasons, but when I try to use the script from Github I literally get no result unity 2020:
using UnityEngine;
using UnityEngine.Rendering;
using System.IO;
using System.Collections;
public class AsyncCapture : MonoBehaviour
{
IEnumerator Start()
{
while (true)
{
yield return new WaitForSeconds(1);
yield return new WaitForEndOfFrame();
var rt = RenderTexture.GetTemporary(Screen.width, Screen.height, 0, RenderTextureFormat.ARGB32);
ScreenCapture.CaptureScreenshotIntoRenderTexture(rt);
AsyncGPUReadback.Request(rt, 0, TextureFormat.ARGB32, OnCompleteReadback);
RenderTexture.ReleaseTemporary(rt);
}
}
void OnCompleteReadback(AsyncGPUReadbackRequest request)
{
if (request.hasError)
{
Debug.Log("GPU readback error detected.");
return;
}
var tex = new Texture2D(Screen.width, Screen.height, TextureFormat.ARGB32, false);
tex.LoadRawTextureData(request.GetData<uint>());
tex.Apply();
File.WriteAllBytes("test.png", ImageConversion.EncodeToPNG(tex));
Destroy(tex);
}
}
it just seems to hang forever… but regardless I want to do this without IEnumerators
[1]: AsyncCaptureTest/Assets/AsyncCapture.cs at master · keijiro/AsyncCaptureTest · GitHub
[2]: https://i.stack.imgur.com/0QMUb.png