I have not posted in many moons. Several years. In that time I've created several games and tools using other game toolkits, mainly Unity3D and Monogame.
But Ludum Dare 38 is comin' up, and I'm thinking I need to go back to my first game making love, Gosu. Monogame and Unity3D are nice, but I've come to realize that they're tanks. Maybe I just want a sword.
My question is about the performance of using the subimage functionality and its performance vs using an array of vanilla Gosu::Image. I have a lot of tile sheets that I have accumulated over the years, and they all have a one-pixel border between tiles. I was about to create a monkey patch that let me Gosu::Image.from_tiles_with_padding, but then I saw it may be easier to setup a solution using Gosu::Image.subimage instead. I also thought that perhaps if using subimage results in one OpenGL texture instead of many, it may end up more performant regardless.
Though I also am willing to bet that even the craziest Gosu game will not stress a modern GPU with OpenGL textures unless the game author is grossly irresponsible. Has anyone done any testing to see which is faster?
Image#subimage is extremely fast. So fast that you could recreate the subimages every tick, draw them once, and then discard them.
The difference between
Image#subimage and loading an image via the constructor is that the latter will add padding around the image when copying it to an OpenGL texture. Those pixels will either be translucent (default) or repeat the outermost colour values (
tileable: true). That ensures that the image looks good when scaling, rotating etc.
subimage, it is your responsibility to make sure the images have some padding. (If you use
retro: true, this doesn't matter.)
If you are worried about performance, you can just pre-process the tile sheets with RMagick or another image library, and then either use
subimage depending on what suits you better.
By the way: All of the image constructors (including
Image.load_tiles) dynamically build a tile atlas on 1024x1024px GL textures. You can observe whether images end up on the same texture internally by comparing
By the way: All of the image constructors (including Image.load_tiles) dynamically build a tile atlas on 1024x1024px GL textures. You can observe whether images end up on the same texture internally by comparing image.gl_tex_info.tex_name.
The more I read and thought about it I figured this would likely be the case.
I used the .subimage functionality to create a pretty simple yet fully working tilesheet loader that works in a couple situations that the built-in tile loader does not. It will work if there is padding, if the tiles are not wall-to-wall on the image, or both. It's not complex, but that is thanks to the subimage function being so useful. It would have required a bit more drama if this wasn't provided. Likely making a ton of Gosu::Image using the :rect option. This only hits the disk once as well, which may save memory and IO, depending on how Gosu handles loading images from disk, which I admit I am not familiar with.TileSheet class for Gosu - Gist
I would love it if .subimage was made part of the stable api. The ease at which you can use it to carve up different formatted sprite/tile sheets is a great help.
I've removed the comment about it being experimental 🎉 It's now a proper part of Gosu.
A note on your gist: The image does not have to be a power-of-two for subimage to work. Gosu will copy the image to a 1024x1024px texture and use the remaining space for other textures.
But the image must not be larger than 1024x1024px. Beyond that, Gosu will split it up into several 1024x1024px textures automatically, and then
subimage will stop working. (This is actually a limitation that I could work around. Hmm. Maybe in a future version...) You could add a check for that in the constructor to prevent surprises.
Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill