Patterns

March 2025

A large part of the koi DNA sequences will be made up of patterning data. This includes properties about the pigments a koi will have, the way these pigments grow into patterns and the material properties of each pigment. To be able to iterate quickly, I've made a DNA editor that helps me to quickly try out many different configurations and interpreting them as if they were produced "naturally" by the DNA system.

The pattern editor
The pattern editor

The final visual representation of a koi pattern is produced by "growing" the patterns over time; I scatter some unspecialized pigment cells on a petri dish shaped like the koi texture, and subdivide the cells until a certain density is reached (the debug interface on the right shows this target density as a little ruler on the bottom left, which is the average distance between cells). While subdividing, the cells specialize into certain pigment colors. Eventually, clusters of the same type of pigment cells are triangulated together to form a mesh, and pattern shapes are generated from them. The cell subdivision process uses a randomizer, so when the seed changes, the entire pattern will change as well. If I'd clone a koi many times, every instance would have exactly the same DNA while all patterns are similar but unique.

The colors are still "flat" now, but will be replaced by the pigment materials for each pigment, which can vary. Some spots may be shinier than others, some may reflect a different color under certain angles and so forth. There can now be three different pigments on a fish apart from the base layer, I may increase it to four depending on how it all looks. I'm also considering ways to implement gradient materials, which will change color along the length or height of the body while still counting as a single pigment type.

The pattern generating process was extremely slow in the Javascript prototype, it was one of the major performance problems I had with that technology stack. I had "solved" it by running four different worker threads for pattern generation, but that's not a serious solution, because I need many more worker threads for other tasks and some of the target hardware doesn't even expose four dedicated threads to the game. The Nintendo Switch for example only has three dedicated threads available (the fourth is used by the operating system). I've been able to optimize the C++ version way more, and pattern generation is now almost instantaneous. Loading up a game with thousands of koi will take a few seconds at most.