DevLog 002 — Hex texture cache

Martin Sikora
badgermakesagame
Published in
3 min readJul 16, 2023

One of the things I’m trying to plan ahead is limiting the number of rendered sprites on canvas. For example, a grid of 80x60 hexes means 4800 sprites where only a small portion is visible. If I was able to render only the currently visible hexes (let’s say 42x32 range) I’d still need 1344 sprites which is way too much.

I believe that any modern computer wouldn’t have any problem with that number but I knew I could improve this a lot. I know that I might have multiple layers covering the same map so each layer would add extra 1344 sprites.

This is where I’m suspicious I might have performance issues in the future and for this reason I came with a different approach. I can group hexes into smaller grids of let’s say 6x4 hexes and bake them into a texture. That’s what I call “texture cache”. Then, instead of creating a sprite for each hex on the map I can create sprites that cover 6x4 ranges. Instead of 1344 sprites for the visible portion of the grid I need only 56 sprites.

The red lines are borders of each sprite and the white coordinates are position of each cache sprite. The sprites overlap each other because hexes don’t have rectangular size. A single cached texture looks like this:

A single cached texture (tile 1x1 in the image above)

The following GIF shows how the cached textures are positioned on the canvas and how they repeat.

The coordinates repeat because the cached sprites cover only the visible area of the grid (based on my window size) and there’s no need to render all of them when they aren’t visible. Basically, I’m taking drag offset from the top-left corner of the map and divide it by texture size to get the first visible cached texture. Then when I drag the map I’m only switching what textures are rendered by each sprite which makes an illusion of scrolling the entire grid.

I’m already using the same technique for other layers created via map plugins such as hex coordinates or hex grid borders.

Each layer created by a plugin has it’s own cached textures that are updated at the same time when I drag the map. All layers for all enabled plugins in the white rectangle from the image above look like the following three PNGs.

What’s interesting here is that the last layer “hex coordinates” is not resized like the other layers. By default, I’m generating textures with 1:1 pixel ratio and then resize them (zoom) 3 times so the map looks pixelated. I’m doing the same for all cached textures created by all plugin except for “hex coordinates”.

This is the only exception where I’m pre-rendering zoomed-in textures because I want to use fixed font size (16px) for every zoom level so the text doesn’t overlay the hex too much.

For my next post, I’m going to implement variable zoom levels with UI controls.

--

--