Going back to low poly palettes

Kumo Kairo
3 min readAug 9, 2017

--

Low poly 3D models give a great opportunity for optimization. Let’s take a look at some of them.

A popular 3D nature pack by Kenney contains a set of two-color (mostly) low-poly models. Two-color nature works using different submeshes and different materials, which results in unneeded movement between CPU and GPU (different materials can’t be batched together). This is an example in Unity:

We can see that with a standard colored material even when every object is marked as static, it only batches 32 draw calls out of 48 (while total number of objects is clearly less than 48). We still use much more draw calls than it’s really needed for this kind of objects. Also note that there are no shadows in the scene (they tend to double the number of draw calls in general)

One way to avoid this extensive usage of drawcalls is to use vertex colors. Basically each vertex is assigned with its own color and then drawn as if it was a color of material. It enables us as users to have only one material without any additional color, so all objects are batched together if they are marked as static:

Painting vertices in Blender

All objects share the same vertex color material and are batched (second batch is for Skybox)

And this way is usually present as the most optimal. But there’s a problem. What if one wants to change the mood of the scene? The whole repainting will be needed. I suggest a simpler thing (and I’m sure it’s been done before, I just didn’t stumble upon this solution myself). We separate objects into tiny color islands (as tiny as a vertex can be) and then assign a small 32x32 or even 16x16 texture with small color squares for those islands:

And then the 32x32 palette texture:

Blank space is for different kinds of objects in the future.

And this is what we get in Unity:

Still one batch for all of the objects. And here’s the funniest part, an autumn forest using a different palette texture:

No need to repaint all the models, just replace the texture. It even allows for mesh data optimization — UV coordinates take two floating point values per vertex (64 bits) while Vertex Paint usually takes four (128 bits). It also allows easier dynamic batching in case of Unity. 32x32 RGB texture, compressed with ETC, takes 500 bytes of space, which is very little compared to individual vertex colors of every mesh inside a project.

Cheers!

--

--