Yes, the phrase “shader-based” was missing — I apologize. I’m new to game development and trying to build things with the help of AI, so I’m not very familiar with many technical terms. However, I had the AI summarize what we are doing as follows:
Before (legacy path): Each grid cell was its own UI object: an Image plus a TextMeshProUGUI child, laid out with GridLayoutGroup. On large grids that means thousands of GameObjects, lots of layout work, many batches, and real text meshes per cell.
After (GPU grid path): The whole grid is drawn as one RawImage using a custom UI shader (PixelArt/ColoringGridUI). Cell state isn’t stored as per-cell widgets; it’s stored in a few low-resolution textures (base tint per cell, packed cell “number id,” paint layer, and a 0–9 digit atlas). The fragment shader figures out which logical cell a pixel belongs to, samples those textures, and composites borders, zoom whitening, selection highlight, and the digits.
It doesn’t “replace Unity’s renderer” in some magical way. It replaces thousands of UI draw/layout/text updates with: one draw (typically) + cheap per-pixel math that reads 2D data and a glyph atlas. Digits aren’t live TMP anymore; they’re sampled from a pre-baked atlas (TMP rendered once to a render texture, or a fallback bitmap). Two-digit numbers split the cell in UV space and sample two glyphs.
The gain is not “we used a shader.” The gain is removing O(cells) UI objects and TMP instances and replacing constant UI churn with updating a few textures / uniforms (e.g. zoom fades as material floats, paint as texture writes). That cuts draw calls, batch fragmentation, and text mesh cost—especially when zooming or scrolling.