Mapgen4 Renderer
It's been a while since I've worked on mapgen4 features. In 2018 I declared it finished. I then put it away and worked on other projects. Over the years I have updated the code (es6 modules, typescript, pointer events, boundary points, pnpm) without adding any features. I had been leaving all feature updates for a future map generator.
Last year I decided it was time to start thinking about new features. I started experimenting with some prototypes. That made me realize there are many improvements I'd like to make to mapgen4 before getting into big features.
I made a list. One of the projects on the list is rewriting the renderer. But why?
- Migrate to WebGL2. I started mapgen4 in 2017. WebGL2 wasn't widely available until 2021. I'd like to use it both for features and performance. I'm using a WebGL1 library, Regl.js, which does not support WebGL2.
- Reduce load time. Regl.js almost doubles the JS size of mapgen4. I would be able to shrink mapgen4 significantly by switching away from it.
Rewriting the renderer was not something I was looking forward to. It's work that has to be done in "one shot", where the intermediate steps aren't testable. I decided to use an LLM to help me. I rarely use LLMs for coding and learned a lot.
- In this project I used the LLM for translating existing working code from Regl.js to WebGL1. This felt different from having it write new code.
- The resulting code had some subtle bugs. I was able to track some of them down by comparing the output of the original mapgen4 renderer with the rewritten renderer. Having a previous working version was important.
- It got me out of my analysis paralysis. Having something that runs rather than a blank editor window was a huge win.
- I didn't like the structure of the code it generated. It triggered XKCD 386 for me. I ended up replacing all of its code, bit by bit, testing after each change.
Along the way I re-evaluated some of how the renderer worked. For example, I'm using nearest neighbor filtering in many places, even though linear might be better.
Look at how much smoother the ocean colors are with linear filtering! But there are blue splotches near rivers. I decided to keep nearest neighbor filtering for now.
I also discovered some bugs, like this one where one edge of the map is jagged, but only noticeable when the camera is rotated and zoomed in:
Overall, I don't think the LLM saved me any time. I didn't end up keeping the code it gave me. But it got me unstuck, and that meant I actually made progress.
The main benefit of the rewrite was output size:
| File | Size before | Size after |
|---|---|---|
| _worker.js | 18543 | 18579 |
| _bundle.js | 150672 | 69469 |
| (total) | 169215 | 88048 |
But the source code did get bigger, from 600 lines to 750 lines (to avoid 9500 lines of Regl.js).
The secondary benefits are that I got to revisit some of the decisions I made, I found some bugs, and I got unstuck. I didn't stop at the main renderer. I also rewrote the river renderer, which saved another 8666 bytes. That's for the next blog post.