Hi all! So what I’ve been working on is a thing that records gameplay, and then at the end of the game compresses it to an animated gif, which the player can then share on social media. It’s coming along great and it’s nearly there, but I’ve ran into a few wrinkles…
The way I’m currently recording gameplay is by grabbing a screenshot using GraphicDevice.GetBackBufferData(). It works great on desktop because there is horsepower to spare, but on android/iOS the performance is in the toilet. As soon as I turn the recorder on, I get a janky frame everytime it calls GetBackBufferData. I tried to cheat and wrap it in Task.Run to pitch to a separate task, which fixes the performance issue but on opengl platforms it grabs a blank screen.
My next step is to try spinning up a dedicated BackgroundWorker to grab screenshots, maybe that will work but I don’t really have my hopes up. Does anyone have a better idea? Is there some other technique that would be better than GetBackBufferData? Is there a way to speed it up?
if you look at PlatformGetBackBufferData() you see that it has to flip the buffer up/down.
it uses 3 copies for each pair of rows. you can make it 2/3 times faster (1 copy per row + a full size tmpBuffer), but I assume that’s not good enough.
possibly you want a custom build of MG or use reflection to get the flipped backbuffer and save it.
then correct it in post processing.
I never tried to do anything like that but im thinking that getting the back buffer would be slow for other reasons then the ones stated. Primarily because i think that a call to the backbuffer is actually interacting with more then just monogame in reality its also dealing with the os calls so i think its more like a hardware interrupt though im not sure this is even remotely true anymore.
Wouldn’t it be faster to rendertarget it then cast to texture2d then set data or save as png it ?
Anyways didn’t someone around here already write a gif creator ?
Yeah I started from a fork of jmoral4’s work. His code used GDI for gif creation though, so it couldn’t be ported to platforms other than windows. I refactored it to use ImageSharp so there are a lot more image manipulation options available, ported to android and iOS, did a bunch of optimization to get .gif creation under 10 seconds on a phone, and pushed up in a nuget package. It’s pretty much production ready, just a little janky right now while recording gameplay. The screenshot capability works perfectly though It’ll even ask for the correct Android permissions and save to external storage
I think your rendertarget idea will probably solve the jankiness problem. I’m going to try and get this Megacool binding library working first, it’d be nice to get the social sharing and link-tracking out of the box.
Ok Megacool was a bust, I got the whole binding library working and found out that their native Android implementation just dumps the main view to a buffer. They haven’t finished OpenGL screen capturing yet, so it doesn’t work on MonoGame. (I think their main focus is Unity developers, not native iOS and Android)
The good news is the rendertarget thing worked perfectly! This thing is ready to go… I feel like I’m living on the edge by using the ImageSharp prerelease package in production, but whatever this app has like 10 downloads total