Optimizing Texture Pages for a Card Game

Coded Games

Member
So one of the biggest questions I have in my game is about how I should optimize my texture pages.

Each card in the game has a 600x600 px piece of artwork. As of now, I have just been throwing all of them into a texture group and calling it good enough. My texture page sizes are 4096x4096 so each page has like 30 cards.

Besides cards, all of the assets needed in the game fit on one 4096x4096 texture page but cards result in my game using something like 6 or 7 texture pages and significantly more if I use 2048x2048.

The question I have is would it be beneficial to have each card be a separate texture page? Because you never know what cards will be in the players deck, you can't really group cards together to make optimal texture pages. Separating them out would result in smaller texture pages instead of loading one that contains cards that are not even in the player's deck.

I think this could be beneficial but it would result in more texture swaps, which is something that you want to minimize.

It ultimately comes down to is more smaller texture swaps better than less big texture swaps? Does this even matter?
 

obscene

Member
I'm going to completely make up a number out of thin air here, but I stand by it. :p 90% of the hit from a texture swap is because it causes a vertex batch break. The size makes little difference. More swaps will be worse than fewer swaps in every case.

Question... are your cards ever on top of one another or are they all displayed side by side? If there is no overlapping, you could arrange the groups so they correspond to different depths. If you had 150 cards, put them into 5 groups. Make sure each group is placed at a unique depth/layer so each group is drawn together. Then you know you'll never need more than 5 swaps to draw them all. If they overlap however, you couldn't control this.

Other than that, maybe if they all have a common border you could crop that from your graphics and fit more into groups and add the borders at runtime. Benefit would vary depending on a few things but just an idea.
 

Coded Games

Member
Question... are your cards ever on top of one another or are they all displayed side by side? If there is no overlapping, you could arrange the groups so they correspond to different depths. If you had 150 cards, put them into 5 groups. Make sure each group is placed at a unique depth/layer so each group is drawn together. Then you know you'll never need more than 5 swaps to draw them all. If they overlap however, you couldn't control this.

Other than that, maybe if they all have a common border you could crop that from your graphics and fit more into groups and add the borders at runtime. Benefit would vary depending on a few things but just an idea.
That is a really good idea but unfortunately cards do overlap fairly frequently for animations like this: https://twitter.com/CodedGames/status/1171226339312947201?s=20

Cards don't have a shared border but they do usually have a fair bit of blank space in their canvas. Doesn't GameMaker crop that out when generating texture pages? So there likely are more than 30 sprites per texture page.
 

obscene

Member
That looks pretty good. Sure doesn't look like they are 600x600 images though. Is the text part of the graphics or are you drawing that in GM? Looks to me that you could fit a few a lot more than 30 on a 4096x4096 page especially if the text was drawn after the fact. Same thing with the card shapes themselves. I would imagine you could fit one blank card, all the icons and a font onto one texture page and do it all with one swap unless you have hundreds of cards.

I'm not sure if GM crops them to what would be best or not, you would want to do a build and then look at the images.
 

Coded Games

Member
That looks pretty good. Sure doesn't look like they are 600x600 images though. Is the text part of the graphics or are you drawing that in GM? Looks to me that you could fit a few a lot more than 30 on a 4096x4096 page especially if the text was drawn after the fact. Same thing with the card shapes themselves. I would imagine you could fit one blank card, all the icons and a font onto one texture page and do it all with one swap unless you have hundreds of cards.

I'm not sure if GM crops them to what would be best or not, you would want to do a build and then look at the images.
They are scaled down a bunch in this video but there are cases where they are much bigger and on a 4k monitor they look crisp. The game can scale to whatever the resolution of the monitor is. The text and background shape of the card are generated by GM. The backgrounds are actually just primitives drawn to a surface. So that causes a few more texture swaps.

Unfortunately there are hundreds of cards so there is no possible way to fit everything onto one texture page.

Is it possible to put the font onto every texture page so that I don't have to switch between drawing art then drawing text, draw art, draw text? Not sure if these minor optimizations are worth it since in the majority of cases I'm drawing like 10 cards on the screen max.
 
Last edited:

obscene

Member
Sorry for late reply...

So 10 cards could result in a maximum of 10 swaps which isn't much, but the font could double that and that's probably worth trying to fix. Unfortunately there's no way to include a single font in multiple groups unless you just made copies of it, which might be feasible if you can come up with a way to make sure you know which font to pull with each card, and also you must make sure on texture group fits onto one texture page.

Just thinking out loud... you might be able to draw all the cards you are using at any given time onto a surface (arranged so there is no overlap) , draw all the text at once so you only have one swap for the font, and then use draw_surface_part_ext or similar to draw the cards. One surface would equal one texture swap, so if you could manage to do this surface draw only when needed (changing cards) you could actually reduce swaps down to 1 overall.
 

Coded Games

Member
That is a good idea, to basically make my own texture pages with surfaces. I actually just looked at my ancient code that I used to generate the surfaces and I am actually drawing the text to the surface alongside the "back" of the card. So I was actually smart enough and shouldn't be having a ton on texture swaps to render the text. Just one swap to draw the surface and one more to draw the artwork on top of the surface.

I should be able to add the card artwork itself to the surface to cut that swap out. So I could optimize it to one swap per card just to render each card's surface. Obviously there would be more swaps when the surface is being generated but I think that might be a good bit of optimization. I could draw all of the cards to one surface like you suggested but that sounds hard and adds a lot of complexity. I think just having one surface per card might be a significant enough optimization. That way I don't have to deal with figuring out where cards are positioned on a surface, what to do if new cards are added to a deck or if they are removed.

I'm not really having performance issues on Windows, but the game does get pretty laggy on my 2015 iPad. On my iPhone X it runs fine though.

Edit: The game actually works pretty well on my iPad. I think it was just because the battery was low or something. It probably was throttling a bit
 
Last edited:

FitBoy

Member
All your game graphics are placed on Texture pages in GameMaker Studio 2. A texture page is just an image with all the graphics of the game so distributed that they can be "dragged" on the screen at the moment.
You can now start taking many textures and have them spread over different ones after you have created several graphics for your game. This means that Game Maker Studio 2 may need texture exchanges to acquire the right sprite on the right page to draw them on the screen. That is not a challenge when this is only several pages, but it can create a constant exchange of information if they are scattered over many pages. this continuous swapping can cause lag and stutter.
How can this be prevented? Okay, in the beginning of your room you can create Texture Groups, flush and pre-fix unused images from texture memory, so that only those graphics which you are actually going to use are stored in the memory.
To begin with, open the Texture Group Editor at the top of the IDE in the Tools menu. Here the texture group groups you need can be formed, for example by creating a group for them if you have some graphics which only appear in the main menu. If you have a number of sprites and backgrounds only in a single level / room, then set up a group etc.
 
Top